diff --git a/.changeset/README.md b/.changeset/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e5b6d8d6a67ad0dca8f20117fbfc72e076882d00
--- /dev/null
+++ b/.changeset/README.md
@@ -0,0 +1,8 @@
+# Changesets
+
+Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
+with multi-package repos, or single-package repos to help you version and publish your code. You can
+find the full documentation for it [in our repository](https://github.com/changesets/changesets)
+
+We have a quick list of common questions to get you started engaging with this project in
+[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
diff --git a/.changeset/changeset.cjs b/.changeset/changeset.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..b2c50fa96c1378a0dd83b75ba8648e7c0fccdd05
--- /dev/null
+++ b/.changeset/changeset.cjs
@@ -0,0 +1,280 @@
+const { getPackagesSync } = require("@manypkg/get-packages");
+const gh = require("@changesets/get-github-info");
+const { existsSync, readFileSync, writeFileSync } = require("fs");
+const { join } = require("path");
+
+const { getInfo, getInfoFromPullRequest } = gh;
+const { packages, rootDir } = getPackagesSync(process.cwd());
+
+/**
+ * @typedef {{packageJson: {name: string, python?: boolean}, dir: string}} Package
+ */
+
+/**
+ * @typedef {{summary: string, id: string, commit: string, releases: {name: string}}} Changeset
+ */
+
+/**
+ *
+ * @param {string} package_name The name of the package to find the directories for
+ * @returns {string[]} The directories for the package
+ */
+function find_packages_dirs(package_name) {
+ /** @type {string[]} */
+ let package_dirs = [];
+
+ /** @type {Package | undefined} */
+ const _package = packages.find((p) => p.packageJson.name === package_name);
+ if (!_package) throw new Error(`Package ${package_name} not found`);
+
+ package_dirs.push(_package.dir);
+ if (_package.packageJson.python) {
+ package_dirs.push(join(_package.dir, ".."));
+ }
+ return package_dirs;
+}
+
+const changelogFunctions = {
+ /**
+ *
+ * @param {Changeset[]} changesets The changesets that have been created
+ * @param {any} dependenciesUpdated The dependencies that have been updated
+ * @param {any} options The options passed to the changelog generator
+ * @returns {Promise} The release line for the dependencies
+ */
+ getDependencyReleaseLine: async (
+ changesets,
+ dependenciesUpdated,
+ options
+ ) => {
+ if (!options.repo) {
+ throw new Error(
+ 'Please provide a repo to this changelog generator like this:\n"changelog": ["@changesets/changelog-github", { "repo": "org/repo" }]'
+ );
+ }
+ if (dependenciesUpdated.length === 0) return "";
+
+ const changesetLink = `- Updated dependencies [${(
+ await Promise.all(
+ changesets.map(async (cs) => {
+ if (cs.commit) {
+ let { links } = await getInfo({
+ repo: options.repo,
+ commit: cs.commit
+ });
+ return links.commit;
+ }
+ })
+ )
+ )
+ .filter((_) => _)
+ .join(", ")}]:`;
+
+ const updatedDepenenciesList = dependenciesUpdated.map(
+ /**
+ *
+ * @param {any} dependency The dependency that has been updated
+ * @returns {string} The formatted dependency
+ */
+ (dependency) => ` - ${dependency.name}@${dependency.newVersion}`
+ );
+
+ return [changesetLink, ...updatedDepenenciesList].join("\n");
+ },
+ /**
+ *
+ * @param {{summary: string, id: string, commit: string, releases: {name: string}[]}} changeset The changeset that has been created
+ * @param {any} type The type of changeset
+ * @param {any} options The options passed to the changelog generator
+ * @returns {Promise} The release line for the changeset
+ */
+ getReleaseLine: async (changeset, type, options) => {
+ if (!options || !options.repo) {
+ throw new Error(
+ 'Please provide a repo to this changelog generator like this:\n"changelog": ["@changesets/changelog-github", { "repo": "org/repo" }]'
+ );
+ }
+
+ let prFromSummary;
+ let commitFromSummary;
+ /**
+ * @type {string[]}
+ */
+ let usersFromSummary = [];
+
+ const replacedChangelog = changeset.summary
+ .replace(/^\s*(?:pr|pull|pull\s+request):\s*#?(\d+)/im, (_, pr) => {
+ let num = Number(pr);
+ if (!isNaN(num)) prFromSummary = num;
+ return "";
+ })
+ .replace(/^\s*commit:\s*([^\s]+)/im, (_, commit) => {
+ commitFromSummary = commit;
+ return "";
+ })
+ .replace(/^\s*(?:author|user):\s*@?([^\s]+)/gim, (_, user) => {
+ usersFromSummary.push(user);
+ return "";
+ })
+ .trim();
+
+ const [firstLine, ...futureLines] = replacedChangelog
+ .split("\n")
+ .map((l) => l.trimRight());
+
+ const links = await (async () => {
+ if (prFromSummary !== undefined) {
+ let { links } = await getInfoFromPullRequest({
+ repo: options.repo,
+ pull: prFromSummary
+ });
+ if (commitFromSummary) {
+ links = {
+ ...links,
+ commit: `[\`${commitFromSummary}\`](https://github.com/${options.repo}/commit/${commitFromSummary})`
+ };
+ }
+ return links;
+ }
+ const commitToFetchFrom = commitFromSummary || changeset.commit;
+ if (commitToFetchFrom) {
+ let { links } = await getInfo({
+ repo: options.repo,
+ commit: commitToFetchFrom
+ });
+ return links;
+ }
+ return {
+ commit: null,
+ pull: null,
+ user: null
+ };
+ })();
+
+ const users =
+ usersFromSummary && usersFromSummary.length
+ ? usersFromSummary
+ .map(
+ (userFromSummary) =>
+ `[@${userFromSummary}](https://github.com/${userFromSummary})`
+ )
+ .join(", ")
+ : links.user;
+
+ const prefix = [
+ links.pull === null ? "" : `${links.pull}`,
+ links.commit === null ? "" : `${links.commit}`
+ ]
+ .join(" ")
+ .trim();
+
+ const suffix = users === null ? "" : ` Thanks ${users}!`;
+
+ /**
+ * @typedef {{[key: string]: string[] | {dirs: string[], current_changelog: string, feat: {summary: string}[], fix: {summary: string}[], highlight: {summary: string}[]}}} ChangesetMeta
+ */
+
+ /**
+ * @type { ChangesetMeta & { _handled: string[] } }}
+ */
+ let lines;
+ if (existsSync(join(rootDir, ".changeset", "_changelog.json"))) {
+ lines = JSON.parse(
+ readFileSync(join(rootDir, ".changeset", "_changelog.json"), "utf-8")
+ );
+ } else {
+ lines = {
+ _handled: []
+ };
+ }
+
+ if (lines._handled.includes(changeset.id)) {
+ return "done";
+ }
+ lines._handled.push(changeset.id);
+
+ changeset.releases.forEach((release) => {
+ if (!lines[release.name])
+ lines[release.name] = {
+ dirs: find_packages_dirs(release.name),
+ current_changelog: "",
+ feat: [],
+ fix: [],
+ highlight: []
+ };
+
+ const changelog_path = join(
+ //@ts-ignore
+ lines[release.name].dirs[1] || lines[release.name].dirs[0],
+ "CHANGELOG.md"
+ );
+
+ if (existsSync(changelog_path)) {
+ //@ts-ignore
+ lines[release.name].current_changelog = readFileSync(
+ changelog_path,
+ "utf-8"
+ )
+ .replace(`# ${release.name}`, "")
+ .trim();
+ }
+
+ const [, _type, summary] = changeset.summary
+ .trim()
+ .match(/^(feat|fix|highlight)\s*:\s*([^]*)/im) || [
+ ,
+ "feat",
+ changeset.summary
+ ];
+
+ let formatted_summary = "";
+
+ if (_type === "highlight") {
+ const [heading, ...rest] = summary.trim().split("\n");
+ const _heading = `${heading} ${prefix ? `(${prefix})` : ""}`;
+ const _rest = rest.concat(["", suffix]);
+
+ formatted_summary = `${_heading}\n${_rest.join("\n")}`;
+ } else {
+ formatted_summary = handle_line(summary, prefix, suffix);
+ }
+
+ //@ts-ignore
+ lines[release.name][_type].push({
+ summary: formatted_summary
+ });
+ });
+
+ writeFileSync(
+ join(rootDir, ".changeset", "_changelog.json"),
+ JSON.stringify(lines, null, 2)
+ );
+
+ return `\n\n-${prefix ? `${prefix} -` : ""} ${firstLine}\n${futureLines
+ .map((l) => ` ${l}`)
+ .join("\n")}`;
+ }
+};
+
+/**
+ * @param {string} str The changelog entry
+ * @param {string} prefix The prefix to add to the first line
+ * @param {string} suffix The suffix to add to the last line
+ * @returns {string} The formatted changelog entry
+ */
+function handle_line(str, prefix, suffix) {
+ const [_s, ...lines] = str.split("\n").filter(Boolean);
+
+ const desc = `${prefix ? `${prefix} -` : ""} ${_s.replace(
+ /[\s\.]$/,
+ ""
+ )}. ${suffix}`;
+
+ if (_s.length === 1) {
+ return desc;
+ }
+
+ return [desc, ...lines.map((l) => ` ${l}`)].join("/n");
+}
+
+module.exports = changelogFunctions;
diff --git a/.changeset/config.json b/.changeset/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..d2ba85f6bb23a7c7a64595f488aa35eed7441f7f
--- /dev/null
+++ b/.changeset/config.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
+ "changelog": ["./changeset.cjs", { "repo": "gradio-app/gradio" }],
+ "commit": false,
+ "fixed": [],
+ "linked": [],
+ "access": "public",
+ "baseBranch": "main",
+ "updateInternalDependencies": "patch",
+ "ignore": ["@gradio/spaces-test", "@gradio/cdn-test"]
+}
diff --git a/.changeset/every-bears-peel.md b/.changeset/every-bears-peel.md
new file mode 100644
index 0000000000000000000000000000000000000000..d2f60b1409fa570ca9db316b58c4f078a70d5c8a
--- /dev/null
+++ b/.changeset/every-bears-peel.md
@@ -0,0 +1,6 @@
+---
+"@gradio/audio": patch
+"gradio": patch
+---
+
+fix:Fix audio recording events not dispatching
diff --git a/.changeset/fix_changelogs.cjs b/.changeset/fix_changelogs.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..202ce30462a0e2fc9e868f56b1e5df73a465a803
--- /dev/null
+++ b/.changeset/fix_changelogs.cjs
@@ -0,0 +1,122 @@
+const { join } = require("path");
+const { readFileSync, existsSync, writeFileSync, unlinkSync } = require("fs");
+const { getPackagesSync } = require("@manypkg/get-packages");
+
+const RE_PKG_NAME = /^[\w-]+\b/;
+const pkg_meta = getPackagesSync(process.cwd());
+
+/**
+ * @typedef {{dirs: string[], highlight: {summary: string}[], feat: {summary: string}[], fix: {summary: string}[], current_changelog: string}} ChangesetMeta
+ */
+
+/**
+ * @typedef {{[key: string]: ChangesetMeta}} ChangesetMetaCollection
+ */
+
+function run() {
+ if (!existsSync(join(pkg_meta.rootDir, ".changeset", "_changelog.json"))) {
+ console.warn("No changesets to process");
+ return;
+ }
+
+ /**
+ * @type { ChangesetMetaCollection & { _handled: string[] } }}
+ */
+ const { _handled, ...packages } = JSON.parse(
+ readFileSync(
+ join(pkg_meta.rootDir, ".changeset", "_changelog.json"),
+ "utf-8"
+ )
+ );
+
+ /**
+ * @typedef { {packageJson: {name: string, version: string, python: boolean}, dir: string} } PackageMeta
+ */
+
+ /**
+ * @type { {[key:string]: PackageMeta} }
+ */
+ const all_packages = pkg_meta.packages.reduce((acc, pkg) => {
+ acc[pkg.packageJson.name] = /**@type {PackageMeta} */ (
+ /** @type {unknown} */ (pkg)
+ );
+ return acc;
+ }, /** @type {{[key:string] : PackageMeta}} */ ({}));
+
+ for (const pkg_name in packages) {
+ const { dirs, highlight, feat, fix, current_changelog } =
+ /**@type {ChangesetMeta} */ (packages[pkg_name]);
+
+ const { version, python } = all_packages[pkg_name].packageJson;
+
+ const highlights = highlight.map((h) => `${h.summary}`);
+ const features = feat.map((f) => `- ${f.summary}`);
+ const fixes = fix.map((f) => `- ${f.summary}`);
+
+ const release_notes = /** @type {[string[], string][]} */ ([
+ [highlights, "### Highlights"],
+ [features, "### Features"],
+ [fixes, "### Fixes"]
+ ])
+ .filter(([s], i) => s.length > 0)
+ .map(([lines, title]) => {
+ if (title === "### Highlights") {
+ return `${title}\n\n${lines.join("\n\n")}`;
+ }
+
+ return `${title}\n\n${lines.join("\n")}`;
+ })
+ .join("\n\n");
+
+ const new_changelog = `# ${pkg_name}
+
+## ${version}
+
+${release_notes}
+
+${current_changelog.replace(`# ${pkg_name}`, "").trim()}
+`.trim();
+
+ dirs.forEach((dir) => {
+ writeFileSync(join(dir, "CHANGELOG.md"), new_changelog);
+ });
+
+ if (python) {
+ bump_local_dependents(pkg_name, version);
+ }
+ }
+
+ unlinkSync(join(pkg_meta.rootDir, ".changeset", "_changelog.json"));
+
+ /**
+ * @param {string} pkg_to_bump The name of the package to bump
+ * @param {string} version The version to bump to
+ * @returns {void}
+ * */
+ function bump_local_dependents(pkg_to_bump, version) {
+ for (const pkg_name in all_packages) {
+ const {
+ dir,
+ packageJson: { python }
+ } = all_packages[pkg_name];
+
+ if (!python) continue;
+
+ const requirements_path = join(dir, "..", "requirements.txt");
+ const requirements = readFileSync(requirements_path, "utf-8").split("\n");
+
+ const pkg_index = requirements.findIndex((line) => {
+ const m = line.trim().match(RE_PKG_NAME);
+ if (!m) return false;
+ return m[0] === pkg_to_bump;
+ });
+
+ if (pkg_index !== -1) {
+ requirements[pkg_index] = `${pkg_to_bump}==${version}`;
+ writeFileSync(requirements_path, requirements.join("\n"));
+ }
+ }
+ }
+}
+
+run();
diff --git a/.config/.prettierignore b/.config/.prettierignore
new file mode 100644
index 0000000000000000000000000000000000000000..70ec7a1841d9e410073f242ce0ed0f4c69f1ff8e
--- /dev/null
+++ b/.config/.prettierignore
@@ -0,0 +1,30 @@
+**/js/app/public/**
+**/pnpm-workspace.yaml
+**/js/app/dist/**
+**/js/wasm/dist/**
+**/client/js/dist/**
+**/js/lite/dist/**
+**/pnpm-lock.yaml
+**/js/plot/src/Plot.svelte
+**/.svelte-kit/**
+**/demo/**
+**/gradio/**
+**/.pnpm-store/**
+**/.venv/**
+**/.github/**
+/guides/**
+**/.mypy_cache/**
+!test-strategy.md
+**/js/_space-test/**
+../js/app/src/lite/theme.css
+../js/storybook/theme.css
+**/gradio_cached_examples/**
+**/storybook-static/**
+**/.vscode/**
+sweep.yaml
+**/.vercel/**
+**/build/**
+**/*.md
+**/src/lib/json/**/*
+**/playwright/.cache/**/*
+**/theme/src/pollen.css
\ No newline at end of file
diff --git a/.config/.prettierrc.json b/.config/.prettierrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..0e8b0ad886052fcbf88e07df76b2f2ab0969e418
--- /dev/null
+++ b/.config/.prettierrc.json
@@ -0,0 +1,7 @@
+{
+ "useTabs": true,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "printWidth": 80,
+ "plugins": ["prettier-plugin-svelte"]
+}
diff --git a/.config/basevite.config.ts b/.config/basevite.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3bc5f18da0faa0b85c9ee6530322b01c79993249
--- /dev/null
+++ b/.config/basevite.config.ts
@@ -0,0 +1,90 @@
+import { defineConfig } from "vite";
+import { svelte } from "@sveltejs/vite-plugin-svelte";
+import sveltePreprocess from "svelte-preprocess";
+// @ts-ignore
+import custom_media from "postcss-custom-media";
+import global_data from "@csstools/postcss-global-data";
+// @ts-ignore
+import prefixer from "postcss-prefix-selector";
+import { readFileSync } from "fs";
+import { join } from "path";
+import { fileURLToPath } from "url";
+
+const __dirname = fileURLToPath(new URL(".", import.meta.url));
+const version_path = join(__dirname, "..", "gradio", "package.json");
+const theme_token_path = join(
+ __dirname,
+ "..",
+ "js",
+ "theme",
+ "src",
+ "tokens.css"
+);
+
+const version = JSON.parse(readFileSync(version_path, { encoding: "utf-8" }))
+ .version.trim()
+ .replace(/\./g, "-");
+
+//@ts-ignore
+export default defineConfig(({ mode }) => {
+ const production = mode === "production";
+
+ return {
+ server: {
+ port: 9876
+ },
+
+ build: {
+ sourcemap: false,
+ target: "esnext",
+ minify: production
+ },
+ define: {
+ BUILD_MODE: production ? JSON.stringify("prod") : JSON.stringify("dev"),
+ BACKEND_URL: production
+ ? JSON.stringify("")
+ : JSON.stringify("http://localhost:7860/"),
+ GRADIO_VERSION: JSON.stringify(version)
+ },
+ css: {
+ postcss: {
+ plugins: [
+ prefixer({
+ prefix: `.gradio-container-${version}`,
+ // @ts-ignore
+ transform(prefix, selector, prefixedSelector, fileName) {
+ if (selector.indexOf("gradio-container") > -1) {
+ return prefix;
+ } else if (
+ selector.indexOf(":root") > -1 ||
+ selector.indexOf("dark") > -1 ||
+ fileName.indexOf(".svelte") > -1
+ ) {
+ return selector;
+ }
+ return prefixedSelector;
+ }
+ }),
+ custom_media()
+ ]
+ }
+ },
+ plugins: [
+ svelte({
+ inspector: true,
+ compilerOptions: {
+ dev: !production
+ },
+ hot: !process.env.VITEST && !production,
+ preprocess: sveltePreprocess({
+ postcss: {
+ plugins: [
+ global_data({ files: [theme_token_path] }),
+ custom_media()
+ ]
+ }
+ })
+ })
+ ]
+ };
+});
diff --git a/.config/copy_frontend.py b/.config/copy_frontend.py
new file mode 100644
index 0000000000000000000000000000000000000000..4aeff7f87fb6658b5f52acb245d7a0e53558a051
--- /dev/null
+++ b/.config/copy_frontend.py
@@ -0,0 +1,59 @@
+from __future__ import annotations
+
+import shutil
+import pathlib
+from typing import Any
+
+from hatchling.builders.hooks.plugin.interface import BuildHookInterface
+
+
+def copy_js_code(root: str | pathlib.Path):
+ NOT_COMPONENT = [
+ "app",
+ "node_modules",
+ "storybook",
+ "playwright-report",
+ "workbench",
+ "tooltils",
+ ]
+ for entry in (pathlib.Path(root) / "js").iterdir():
+ if (
+ entry.is_dir()
+ and not str(entry.name).startswith("_")
+ and not str(entry.name) in NOT_COMPONENT
+ ):
+
+ def ignore(s, names):
+ ignored = []
+ for n in names:
+ if (
+ n.startswith("CHANGELOG")
+ or n.startswith("README.md")
+ or n.startswith("node_modules")
+ or ".test." in n
+ or ".stories." in n
+ or ".spec." in n
+ ):
+ ignored.append(n)
+ return ignored
+ shutil.copytree(
+ str(entry),
+ str(pathlib.Path("gradio") / "_frontend_code" / entry.name),
+ ignore=ignore,
+ dirs_exist_ok=True,
+ )
+ shutil.copytree(
+ str(pathlib.Path(root) / "client" / "js"),
+ str(pathlib.Path("gradio") / "_frontend_code" / "client"),
+ ignore=lambda d, names: ["node_modules"],
+ dirs_exist_ok=True,
+ )
+
+
+class BuildHook(BuildHookInterface):
+ def initialize(self, version: str, build_data: dict[str, Any]) -> None:
+ copy_js_code(self.root)
+
+
+if __name__ == "__main__":
+ copy_js_code(pathlib.Path("..").resolve())
diff --git a/.config/eslint.config.js b/.config/eslint.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..467f270e3c9fa4f78b0d3d7ed909dad48f61cf1b
--- /dev/null
+++ b/.config/eslint.config.js
@@ -0,0 +1,153 @@
+import globals from "globals";
+import ts_plugin from "@typescript-eslint/eslint-plugin";
+import js_plugin from "@eslint/js";
+
+import typescriptParser from "@typescript-eslint/parser";
+import sveltePlugin from "eslint-plugin-svelte";
+import svelteParser from "svelte-eslint-parser";
+
+const ts_rules_disabled = Object.fromEntries(
+ Object.keys(ts_plugin.rules).map((rule) => [
+ `@typescript-eslint/${rule}`,
+ "off"
+ ])
+);
+const js_rules_disabled = Object.fromEntries(
+ Object.keys(js_plugin.configs.all.rules).map((rule) => [rule, "off"])
+);
+
+const js_rules = {
+ ...js_rules_disabled,
+ "no-console": ["error", { allow: ["warn", "error", "debug", "info"] }],
+ "no-constant-condition": "error",
+ "no-dupe-args": "error",
+ "no-extra-boolean-cast": "error",
+ "no-unexpected-multiline": "error",
+ "no-unreachable": "error",
+ "valid-jsdoc": "error",
+ "array-callback-return": "error",
+ complexity: "error",
+ "no-else-return": "error",
+ "no-useless-return": "error",
+ "no-undef": "error",
+ "valid-jsdoc": [
+ "error",
+ {
+ requireReturn: false,
+ requireParamDescription: true,
+ requireReturnDescription: true,
+ requireReturnType: false,
+ requireParamType: false
+ }
+ ]
+};
+
+const ts_rules = {
+ ...ts_rules_disabled,
+ "@typescript-eslint/adjacent-overload-signatures": "error",
+ "@typescript-eslint/explicit-function-return-type": [
+ "error",
+ { allowExpressions: true }
+ ],
+ "@typescript-eslint/consistent-type-exports": "error",
+ "@typescript-eslint/ban-types": "error",
+ "@typescript-eslint/array-type": "error",
+ "@typescript-eslint/no-inferrable-types": "error"
+};
+
+const { browser, es2021, node } = globals;
+
+export default [
+ {
+ ignores: [
+ ".svelte-kit/**/*",
+ "**/node_modules/**",
+ "**/dist/**",
+ "**/.config/*",
+ "**/*.spec.ts",
+ "**/*.test.ts",
+ "**/*.node-test.ts",
+ "js/app/test/**/*",
+ "**/*vite.config.ts",
+ "**/_website/**/*",
+ "**/_spaces-test/**/*",
+ "**/preview/test/**/*"
+ ]
+ },
+ {
+ files: ["**/*.js", "**/*.cjs"],
+ languageOptions: {
+ globals: {
+ ...browser,
+ ...es2021,
+ ...node
+ }
+ },
+
+ plugins: {
+ "eslint:recommended": js_plugin
+ },
+ rules: js_rules
+ },
+
+ {
+ files: ["**/*.ts"],
+ languageOptions: {
+ parser: typescriptParser,
+ parserOptions: {
+ project: "./tsconfig.json",
+ extraFileExtensions: [".svelte"]
+ },
+ globals: {
+ ...browser,
+ ...es2021,
+ ...node
+ }
+ },
+
+ plugins: {
+ "@typescript-eslint": ts_plugin,
+ "eslint:recommended": js_plugin
+ },
+ rules: {
+ ...ts_rules,
+ ...js_rules,
+ "no-undef": "off"
+ }
+ },
+ {
+ files: ["**/client/js/**"],
+ languageOptions: {
+ parserOptions: {
+ project: "./client/js/tsconfig.json"
+ }
+ }
+ },
+ {
+ files: ["**/*.svelte"],
+ languageOptions: {
+ parser: svelteParser,
+ parserOptions: {
+ parser: typescriptParser,
+ project: "./tsconfig.json",
+ extraFileExtensions: [".svelte"]
+ },
+ globals: {
+ ...browser,
+ ...es2021
+ }
+ },
+ plugins: {
+ svelte: sveltePlugin,
+ "@typescript-eslint": ts_plugin,
+ "eslint:recommended": js_plugin
+ },
+ rules: {
+ ...ts_rules,
+ ...js_rules,
+ ...sveltePlugin.configs.recommended.rules,
+ "svelte/no-at-html-tags": "off",
+ "no-undef": "off"
+ }
+ }
+];
diff --git a/.config/playwright-ct.config.ts b/.config/playwright-ct.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3f89855797a04fe2a9cab4e781728fd02279e046
--- /dev/null
+++ b/.config/playwright-ct.config.ts
@@ -0,0 +1,41 @@
+import { defineConfig, devices } from "@playwright/experimental-ct-svelte";
+import config from "./basevite.config";
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: "../",
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: "./__snapshots__",
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: "html",
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: "on-first-retry",
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+ ctViteConfig: config({ mode: "development" })
+ },
+ testMatch: "*.component.spec.ts",
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: "chromium",
+ use: { ...devices["Desktop Chrome"] }
+ }
+ ]
+});
diff --git a/.config/playwright-setup.js b/.config/playwright-setup.js
new file mode 100644
index 0000000000000000000000000000000000000000..3fc61854f8a23e125a608c7aa7a190287d79c374
--- /dev/null
+++ b/.config/playwright-setup.js
@@ -0,0 +1,152 @@
+import { spawn } from "node:child_process";
+import { join, basename } from "path";
+import { fileURLToPath } from "url";
+import { readdirSync, writeFileSync } from "fs";
+import net from "net";
+
+import kl from "kleur";
+
+const __dirname = fileURLToPath(new URL(".", import.meta.url));
+const TEST_APP_PATH = join(__dirname, "./test.py");
+const TEST_FILES_PATH = join(__dirname, "..", "js", "app", "test");
+const ROOT = join(__dirname, "..");
+
+const test_files = readdirSync(TEST_FILES_PATH)
+ .filter(
+ (f) =>
+ f.endsWith("spec.ts") &&
+ !f.endsWith(".skip.spec.ts") &&
+ !f.endsWith(".component.spec.ts")
+ )
+ .map((f) => basename(f, ".spec.ts"));
+
+export default async function global_setup() {
+ const verbose = process.env.GRADIO_TEST_VERBOSE;
+
+ const port = await find_free_port(7860, 8860);
+ process.env.GRADIO_E2E_TEST_PORT = port;
+
+ process.stdout.write(kl.yellow("\nCreating test gradio app.\n\n"));
+
+ const test_app = make_app(test_files, port);
+ process.stdout.write(kl.yellow("App created. Starting test server.\n\n"));
+
+ process.stdout.write(kl.bgBlue(" =========================== \n"));
+ process.stdout.write(kl.bgBlue(" === PYTHON STARTUP LOGS === \n"));
+ process.stdout.write(kl.bgBlue(" =========================== \n\n"));
+
+ writeFileSync(TEST_APP_PATH, test_app);
+
+ const app = await spawn_gradio_app(TEST_APP_PATH, port, verbose);
+
+ process.stdout.write(
+ kl.green(`\n\nServer started. Running tests on port ${port}.\n`)
+ );
+
+ return () => {
+ process.stdout.write(kl.green(`\nTests complete, cleaning up!\n`));
+
+ kill_process(app);
+ };
+}
+const INFO_RE = /^INFO:/;
+
+function spawn_gradio_app(app, port, verbose) {
+ const PORT_RE = new RegExp(`:${port}`);
+
+ return new Promise((res, rej) => {
+ const _process = spawn(`python`, [app], {
+ shell: true,
+ stdio: "pipe",
+ cwd: ROOT,
+ env: {
+ ...process.env,
+ GRADIO_SERVER_PORT: `7879`,
+ PYTHONUNBUFFERED: "true",
+ GRADIO_ANALYTICS_ENABLED: "False"
+ }
+ });
+ _process.stdout.setEncoding("utf8");
+
+ function std_out(data) {
+ const _data = data.toString();
+ const is_info = INFO_RE.test(_data);
+
+ if (is_info) {
+ process.stdout.write(kl.yellow(_data));
+ }
+
+ if (!is_info) {
+ process.stdout.write(`${_data}\n`);
+ }
+
+ if (PORT_RE.test(_data)) {
+ process.stdout.write(kl.bgBlue("\n =========== END =========== "));
+
+ res(_process);
+
+ if (!verbose) {
+ _process.stdout.off("data", std_out);
+ _process.stderr.off("data", std_out);
+ }
+ }
+ }
+
+ _process.stdout.on("data", std_out);
+ _process.stderr.on("data", std_out);
+ _process.on("exit", () => kill_process(_process));
+ _process.on("close", () => kill_process(_process));
+ _process.on("disconnect", () => kill_process(_process));
+ });
+}
+
+function kill_process(process) {
+ process.kill("SIGKILL");
+}
+
+function make_app(demos, port) {
+ return `import gradio as gr
+import uvicorn
+from fastapi import FastAPI
+import gradio as gr
+${demos.map((d) => `from demo.${d}.run import demo as ${d}`).join("\n")}
+
+app = FastAPI()
+${demos
+ .map((d) => `app = gr.mount_gradio_app(app, ${d}, path="/${d}")`)
+ .join("\n")}
+
+config = uvicorn.Config(app, port=${port}, log_level="info")
+server = uvicorn.Server(config=config)
+server.run()`;
+}
+
+export async function find_free_port(start_port, end_port) {
+ for (let port = start_port; port < end_port; port++) {
+ if (await is_free_port(port)) {
+ return port;
+ }
+ }
+
+ throw new Error(
+ `Could not find free ports: there were not enough ports available.`
+ );
+}
+
+export function is_free_port(port) {
+ return new Promise((accept, reject) => {
+ const sock = net.createConnection(port, "127.0.0.1");
+ sock.once("connect", () => {
+ sock.end();
+ accept(false);
+ });
+ sock.once("error", (e) => {
+ sock.destroy();
+ if (e.code === "ECONNREFUSED") {
+ accept(true);
+ } else {
+ reject(e);
+ }
+ });
+ });
+}
diff --git a/.config/playwright.config.js b/.config/playwright.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..04b78a4a8e7db8c0a66645f9401c5f3c403a687e
--- /dev/null
+++ b/.config/playwright.config.js
@@ -0,0 +1,24 @@
+import { defineConfig } from "@playwright/test";
+
+export default defineConfig({
+ use: {
+ screenshot: "only-on-failure",
+ trace: "retain-on-failure",
+ permissions: ["clipboard-read", "clipboard-write", "microphone"],
+ bypassCSP: true,
+ launchOptions: {
+ args: [
+ "--disable-web-security",
+ "--use-fake-device-for-media-stream",
+ "--use-fake-ui-for-media-stream",
+ "--use-file-for-fake-audio-capture=../gradio/test_data/test_audio.wav"
+ ]
+ }
+ },
+ expect: { timeout: 60000 },
+ timeout: 90000,
+ testMatch: /.*.spec.ts/,
+ testDir: "..",
+ globalSetup: "./playwright-setup.js",
+ workers: process.env.CI ? 1 : undefined
+});
diff --git a/.config/playwright/index.html b/.config/playwright/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..229f296a9e5a3df9f93a2fe378fc31e3b4fff879
--- /dev/null
+++ b/.config/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/.config/playwright/index.ts b/.config/playwright/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ac6de14bf2ed6d010d48977f7e17bb756307d5ce
--- /dev/null
+++ b/.config/playwright/index.ts
@@ -0,0 +1,2 @@
+// Import styles, initialize component theme here.
+// import '../src/common.css';
diff --git a/.config/postcss.config.cjs b/.config/postcss.config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..81b1976568fb4a99716139d8c63d14a8f5d99390
--- /dev/null
+++ b/.config/postcss.config.cjs
@@ -0,0 +1,8 @@
+const tailwindcss = require("tailwindcss");
+const autoprefixer = require("autoprefixer");
+const nested = require("tailwindcss/nesting");
+const tw_config = require("./tailwind.config.cjs");
+
+module.exports = {
+ plugins: [nested, tailwindcss(tw_config), autoprefixer]
+};
diff --git a/.config/setup_vite_tests.ts b/.config/setup_vite_tests.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0917122266f78918d2d43103a2d060191f104c2a
--- /dev/null
+++ b/.config/setup_vite_tests.ts
@@ -0,0 +1,11 @@
+import type { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers";
+import matchers from "@testing-library/jest-dom/matchers";
+import { expect } from "vitest";
+
+declare module "vitest" {
+ interface Assertion
+ extends jest.Matchers,
+ TestingLibraryMatchers {}
+}
+
+expect.extend(matchers);
diff --git a/.config/tailwind.config.cjs b/.config/tailwind.config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..fe92c25a4ef936efc0d55db7bc77b6ecb8c3a1d0
--- /dev/null
+++ b/.config/tailwind.config.cjs
@@ -0,0 +1,12 @@
+module.exports = {
+ content: [
+ "./src/**/*.{html,js,svelte,ts}",
+ "**/@gradio/**/*.{html,js,svelte,ts}"
+ ],
+
+ theme: {
+ extend: {}
+ },
+
+ plugins: [require("@tailwindcss/forms")]
+};
diff --git a/.config/vitest.config.ts b/.config/vitest.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9de93ad0ec2eb93ff2a5b755d9c99ad9b837b4a9
--- /dev/null
+++ b/.config/vitest.config.ts
@@ -0,0 +1,3 @@
+import config from "../js/app/vite.config";
+
+export default config;
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000000000000000000000000000000000..6dafa31d21d36771530cc98a1a759ad2800a46c5
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,41 @@
+// See https://containers.dev
+{
+ "name": "Python 3",
+ "image": "mcr.microsoft.com/devcontainers/python:0-3.9",
+
+ // See https://containers.dev/features
+ "features": {
+ "ghcr.io/devcontainers/features/git:1": {},
+ "ghcr.io/devcontainers/features/node:1": {},
+ "ghcr.io/devcontainers-contrib/features/ffmpeg-apt-get:1": {}
+ },
+
+ "hostRequirements": {
+ "cpus": 4,
+ "memory": "8gb",
+ "storage": "32gb"
+ },
+
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-python.python",
+ "ms-python.vscode-pylance",
+ "ms-python.black-formatter",
+ "ms-toolsai.jupyter",
+ "esbenp.prettier-vscode",
+ "svelte.svelte-vscode",
+ "phoenisx.cssvar"
+ ],
+ "remote.autoForwardPorts": false
+ }
+ },
+
+ "forwardPorts": [7860, 9876],
+ "portsAttributes": {
+ "7860": { "label": "gradio port" },
+ "9876": { "label": "gradio dev port" }
+ },
+
+ "postCreateCommand": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && chmod +x scripts/install_gradio.sh scripts/install_test_requirements.sh scripts/build_frontend.sh && ./scripts/install_gradio.sh && ./scripts/install_test_requirements.sh && ./scripts/build_frontend.sh"
+}
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..916fc50c4d5d5b47fc23bd6b3137c74564926a15
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,40 @@
+# Python build
+.eggs/
+gradio.egg-info/*
+!gradio.egg-info/requires.txt
+!gradio.egg-info/PKG-INFO
+dist/
+*.pyc
+__pycache__/
+*.py[cod]
+*$py.class
+build/
+
+# JS build
+gradio/templates/frontend/static
+gradio/templates/frontend/cdn
+
+# Secrets
+.env
+
+# Gradio run artifacts
+*.db
+*.sqlite3
+gradio/launches.json
+
+# Tests
+.coverage
+coverage.xml
+test.txt
+
+# Demos
+demo/tmp.zip
+demo/flagged
+demo/files/*.avi
+demo/files/*.mp4
+
+# Etc
+.idea/*
+.DS_Store
+*.bak
+workspace.code-workspace
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..f4e045fdb9a018c79ddf8e8c52de8b01eecd38ce
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+
+root = true
+
+[{js/**,client/js/**}]
+end_of_line = lf
+insert_final_newline = true
+indent_style = tab
+tab_width = 2
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000000000000000000000000000000000..5acfdd111f027eb9964e437655316a6cb290d957
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,14 @@
+# https://github.com/gradio-app/gradio/pull/4487 - refactor components.py to separate files
+69f36f98535c904e7cac2b4942cecc747ed7443c
+# Format the codebase
+cc0cff893f9d7d472788adc2510c123967b384fe
+# Switch from black to ruff
+8a70e83db9c7751b46058cdd2514e6bddeef6210
+# format (#4810)
+7fa5e766ce0f89f1fb84c329e62c9df9c332120a
+# lint website
+4bf301324b3b180fa32166ff1774312b01334c88
+# format frontend with prettier
+980b9f60eb49ed81e4957debe7b23a559a4d4b51
+# Refactor component directories (#5074)
+1419538ea795caa391e3de809379f10639e9e764
diff --git a/.gitattributes b/.gitattributes
index a6344aac8c09253b3b630fb776ae94478aa0275b..9d0d253bc669a853ad06d6c9653444b03f89fe52 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -33,3 +33,20 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text
+demo/blocks_flipper/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/blocks_neural_instrument_coding/sax.wav filter=lfs diff=lfs merge=lfs -text
+demo/calculator/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/dataset/files/world.mp4 filter=lfs diff=lfs merge=lfs -text
+demo/fake_diffusion_with_gif/image.gif filter=lfs diff=lfs merge=lfs -text
+demo/hello_world_2/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/hello_world_4/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/image_mod/screenshot.png filter=lfs diff=lfs merge=lfs -text
+demo/kitchen_sink/files/world.mp4 filter=lfs diff=lfs merge=lfs -text
+demo/sales_projections/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/sepia_filter/screenshot.gif filter=lfs diff=lfs merge=lfs -text
+demo/unispeech-speaker-verification/samples/kirsten_dunst.wav filter=lfs diff=lfs merge=lfs -text
+demo/video_component/files/world.mp4 filter=lfs diff=lfs merge=lfs -text
+guides/assets/hf_demo.mp4 filter=lfs diff=lfs merge=lfs -text
+guides/cn/assets/hf_demo.mp4 filter=lfs diff=lfs merge=lfs -text
+js/app/test/files/file_test.ogg filter=lfs diff=lfs merge=lfs -text
+test/test_files/rotated_image.jpeg filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/ISSUE_TEMPLATE/bug_report_template.yml b/.github/ISSUE_TEMPLATE/bug_report_template.yml
new file mode 100644
index 0000000000000000000000000000000000000000..825410fa979a63389dfc7980cb7dc69cb1658074
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_template.yml
@@ -0,0 +1,69 @@
+name: "\U0001F41E Bug report"
+description: Report a bug on Gradio
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report! Before you get started, please [search to see](https://github.com/gradio-app/gradio/issues) if an issue already exists for the bug you encountered
+ - type: textarea
+ id: bug-description
+ attributes:
+ label: Describe the bug
+ description: Please provide a concise description of what the bug is, in clear English. If you intend to submit a PR for this issue, tell us in the description.
+ placeholder: Bug description
+ validations:
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Have you searched existing issues? 🔎
+ description: Please search to see if an issue already exists for the issue you encountered.
+ options:
+ - label: I have searched and found no existing issues
+ required: true
+ - type: textarea
+ id: reproduction
+ attributes:
+ label: Reproduction
+ description: Please provide a minimal example, with code, that can be run to reproduce the issue. Do NOT provide screenshots of code, or link to external repos or applications. Use ``` to format code blocks.
+ placeholder: Reproduction
+ value: |
+ ```python
+ import gradio as gr
+
+ ```
+ validations:
+ required: true
+ - type: textarea
+ id: screenshot
+ attributes:
+ label: Screenshot
+ description: If relevant, please include screenshot(s) of your Gradio app so that we can understand what the issue is.
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ description: "Please include the full stacktrace of the errors you get from Python or Javascript. If you are running in a colab notebooks, you can get the logs with by setting `debug=True`, i.e: `gradio.Interface.launch(debug=True)`"
+ render: shell
+ - type: textarea
+ id: system-info
+ attributes:
+ label: System Info
+ description: Please ensure you are running the latest version of Gradio. You can get the Gradio version and all its dependencies by running `gradio environment`
+ render: shell
+ validations:
+ required: true
+ - type: dropdown
+ id: severity
+ attributes:
+ label: Severity
+ description: Select the severity of this issue
+ options:
+ - I can work around it
+ - Blocking usage of gradio
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ 📌 Please ensure that you have filled all of the required sections above, and that the reproduction you have provided is [minimal, complete, and reproducible](https://stackoverflow.com/help/minimal-reproducible-example). Incomplete issues will be closed.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f7f293887d8b1e8e499fbd7da0943f0bcd389750
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: 💡 General questions
+ url: https://discord.com/invite/feTf9x3ZSB
+ about: Have general questions about how to use Gradio? Please ask in our community Discord for quicker responses
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..c51010af86e60376e2eddbfd091a92785aa1683f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,19 @@
+---
+name: ⚡ Feature request
+about: Suggest an improvement or new feature or a new Guide for Gradio
+title: ''
+labels: ''
+assignees: ''
+
+---
+- [ ] I have searched to see if a similar issue already exists.
+
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000000000000000000000000000000000..593027bdc8b84046bad647f14b18e3c7c385f9d8
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,18 @@
+## Description
+
+Please include a concise summary, in clear English, of the changes in this pull request. If it closes an issue, please mention it here.
+
+Closes: #(issue)
+
+## 🎯 PRs Should Target Issues
+
+Before your create a PR, please check to see if there is [an existing issue](https://github.com/gradio-app/gradio/issues) for this change. If not, please create an issue before you create this PR, unless the fix is very small.
+
+Not adhering to this guideline will result in the PR being closed.
+
+## Tests
+
+1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up [your Gradio environment locally](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) and run the tests: `bash scripts/run_all_tests.sh`
+
+2. You may need to run the linters: `bash scripts/format_backend.sh` and `bash scripts/format_frontend.sh`
+
diff --git a/.github/actions/install-all-deps/action.yml b/.github/actions/install-all-deps/action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..da8f17fe3c3e7de1a1db6a8f04dab560ce92fc72
--- /dev/null
+++ b/.github/actions/install-all-deps/action.yml
@@ -0,0 +1,60 @@
+name: 'install all deps'
+description: 'Install all deps'
+
+inputs:
+ always-install-pnpm:
+ description: 'Dictates whether or not we should install pnpm & dependencies, regardless of the cache'
+ default: 'false'
+ node_auth_token:
+ description: 'Node auth token'
+ default: ""
+ npm_token:
+ description: 'npm token'
+ default: ""
+ skip_build:
+ description: 'Skip build'
+ default: 'false'
+
+runs:
+ using: "composite"
+ steps:
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.8
+ cache: pip
+ cache-dependency-path: |
+ client/python/requirements.txt
+ requirements.txt
+ test/requirements.txt
+ - name: Create env
+ shell: bash
+ run: |
+ python -m pip install --upgrade virtualenv
+ python -m virtualenv venv
+ - uses: actions/cache@v4
+ id: cache
+ with:
+ path: |
+ venv/*
+ key: gradio-lib-ubuntu-latest-pip-${{ hashFiles('client/python/requirements.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test/requirements.txt') }}
+ - name: Install Gradio and Client Libraries Locally (Linux)
+ shell: bash
+ run: |
+ . venv/bin/activate
+ python -m pip install -e client/python
+ python -m pip install -e .
+ - name: Install ffmpeg
+ uses: FedericoCarboni/setup-ffmpeg@v2
+ - name: install-frontend
+ uses: "./.github/actions/install-frontend-deps"
+ with:
+ always-install-pnpm: ${{ inputs.always-install-pnpm }}
+ node_auth_token: ${{ inputs.node_auth_token }}
+ npm_token: ${{ inputs.npm_token }}
+ skip_build: ${{ inputs.skip_build }}
+ - name: generate json
+ shell: bash
+ run: |
+ . venv/bin/activate
+ python js/_website/generate_jsons/generate.py
diff --git a/.github/actions/install-frontend-deps/action.yml b/.github/actions/install-frontend-deps/action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4a591530bc7d98439ea77bad2166c9799d00587c
--- /dev/null
+++ b/.github/actions/install-frontend-deps/action.yml
@@ -0,0 +1,51 @@
+name: 'install frontend'
+description: 'Install frontend deps'
+
+inputs:
+ always-install-pnpm:
+ description: 'Dictates whether or not we should install pnpm & dependencies, regardless of the cache'
+ default: 'false'
+ node_auth_token:
+ description: 'Node auth token'
+ default: ""
+ npm_token:
+ description: 'npm token'
+ default: ""
+ skip_build:
+ description: 'Skip build'
+ default: 'false'
+
+runs:
+ using: "composite"
+ steps:
+ - uses: actions/cache@v4
+ id: frontend-cache
+ with:
+ path: |
+ gradio/templates/*
+ key: gradio-lib-front-end-${{ hashFiles('js/**', 'client/js/**')}}
+ - name: Install pnpm
+ if: steps.frontend-cache.outputs.cache-hit != 'true' || inputs.always-install-pnpm == 'true'
+ uses: pnpm/action-setup@v2
+ with:
+ version: 8.9
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: pnpm
+ cache-dependency-path: pnpm-lock.yaml
+ env:
+ NODE_AUTH_TOKEN: ${{ inputs.always-install-pnpm }}
+ NPM_TOKEN: ${{ inputs.always-install-pnpm }}
+ - name: Install deps
+ if: steps.frontend-cache.outputs.cache-hit != 'true' || inputs.always-install-pnpm == 'true'
+ shell: bash
+ run: pnpm i --frozen-lockfile --ignore-scripts
+ - name: Build Css
+ if: inputs.always-install-pnpm == 'true'
+ shell: bash
+ run: pnpm css
+ - name: Build frontend
+ if: inputs.skip_build == 'false' && steps.frontend-cache.outputs.cache-hit != 'true'
+ shell: bash
+ run: pnpm build
\ No newline at end of file
diff --git a/.github/stale b/.github/stale
new file mode 100644
index 0000000000000000000000000000000000000000..9d23fb5a9d8ba617e7d77a55f8ae5bfc1e46f8fc
--- /dev/null
+++ b/.github/stale
@@ -0,0 +1,17 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 30
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 7
+# Issues with these labels will never be considered stale
+exemptLabels:
+ - pinned
+ - security
+# Label to use when marking an issue as stale
+staleLabel: wontfix
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs. Thank you
+ for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cd8a273fb5835d1b272b2a63790eda63757d2cdc
--- /dev/null
+++ b/.github/workflows/backend.yml
@@ -0,0 +1,244 @@
+name: gradio-backend
+
+on:
+ push:
+ branches:
+ - "main"
+ pull_request:
+ types: [opened, synchronize, reopened, labeled, unlabeled]
+
+concurrency:
+ group: backend-${{ github.ref }}-${{ github.event_name == 'push' || github.event.inputs.fire != null }}
+ cancel-in-progress: true
+
+env:
+ NODE_OPTIONS: "--max-old-space-size=4096"
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
+
+jobs:
+ changes:
+ runs-on: ubuntu-latest
+ outputs:
+ python-client: ${{ steps.changes.outputs.python-client }}
+ gradio: ${{ steps.changes.outputs.gradio }}
+ test: ${{ steps.changes.outputs.test }}
+ workflows: ${{ steps.changes.outputs.workflows }}
+ scripts: ${{ steps.changes.outputs.scripts }}
+ client-scripts: ${{ steps.changes.outputs.client-scripts }}
+ steps:
+ - uses: actions/checkout@v3
+ - uses: dorny/paths-filter@v2
+ id: changes
+ with:
+ filters: |
+ python-client:
+ - 'client/python/**'
+ - 'gradio/**'
+ - 'requirements.txt'
+ gradio:
+ - 'client/python/**'
+ - 'gradio/**'
+ - 'requirements.txt'
+ test:
+ - 'test/**'
+ workflows:
+ - '.github/**'
+ scripts:
+ - 'scripts/**'
+ client-test:
+ needs: [changes]
+ if: needs.changes.outputs.python-client == 'true' || needs.changes.outputs.workflows == 'true'
+ strategy:
+ matrix:
+ os: ["ubuntu-latest", "windows-latest"]
+ test-type: ["not flaky", "flaky"]
+ python-version: ["3.8"]
+ exclude:
+ - os: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'windows-tests') && 'dummy' || 'windows-latest' }}
+ - test-type: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'flaky-tests') && 'dummy' || 'flaky' }}
+ runs-on: ${{ matrix.os }}
+ continue-on-error: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ cache: pip
+ cache-dependency-path: |
+ client/python/requirements.txt
+ requirements.txt
+ test/requirements.txt
+ - name: Create env
+ run: |
+ python -m pip install --upgrade virtualenv
+ python -m virtualenv venv
+ - uses: actions/cache@master
+ id: cache
+ with:
+ path: |
+ client/python/venv/*
+ key: python-client-${{ runner.os }}-pip-${{ hashFiles('client/python/requirements.txt') }}-${{ hashFiles('client/python/test/requirements.txt') }}
+ - uses: actions/cache@v4
+ id: frontend-cache
+ with:
+ path: |
+ gradio/templates/*
+ key: gradio-lib-front-end-${{ hashFiles('js/**', 'client/js/**')}}
+ - name: Install pnpm
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ uses: pnpm/action-setup@v2
+ with:
+ version: 8
+ - uses: actions/setup-node@v4
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ with:
+ node-version: 18
+ cache: pnpm
+ cache-dependency-path: pnpm-lock.yaml
+ - name: Build Frontend
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ run: |
+ pnpm i --frozen-lockfile --ignore-scripts
+ pnpm build
+ - name: Install Test Requirements (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ python -m pip install -r client/python/test/requirements.txt
+ - name: Install ffmpeg
+ uses: FedericoCarboni/setup-ffmpeg@v2
+ - name: Install Gradio and Client Libraries Locally (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ python -m pip install client/python
+ python -m pip install ".[oauth]"
+ - name: Lint (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ bash client/python/scripts/lint.sh
+ - name: Tests (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ python -m pytest -m "${{ matrix.test-type }}" client/python/
+ - name: Install Test Requirements (Windows)
+ if: runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ pip install -r client/python/test/requirements.txt
+ - name: Install Gradio and Client Libraries Locally (Windows)
+ if: runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ python -m pip install client/python
+ python -m pip install ".[oauth]"
+ - name: Tests (Windows)
+ if: runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ python -m pytest -m "${{ matrix.test-type }}" client/python/
+ test:
+ needs: [changes]
+ if: needs.changes.outputs.gradio == 'true' || needs.changes.outputs.workflows == 'true' || needs.changes.outputs.scripts == 'true' || needs.changes.outputs.test == 'true'
+ strategy:
+ matrix:
+ os: ["ubuntu-latest", "windows-latest"]
+ test-type: ["not flaky", "flaky"]
+ python-version: ["3.8"]
+ exclude:
+ - os: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'windows-tests') && 'dummy' || 'windows-latest' }}
+ - test-type: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'flaky-tests') && 'dummy' || 'flaky' }}
+ runs-on: ${{ matrix.os }}
+ continue-on-error: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ cache: pip
+ cache-dependency-path: |
+ client/python/requirements.txt
+ requirements.txt
+ test/requirements.txt
+ - name: Create env
+ run: |
+ python -m pip install --upgrade virtualenv
+ python -m virtualenv venv
+ - uses: actions/cache@v4
+ id: cache
+ with:
+ path: |
+ venv/*
+ key: gradio-lib-${{ runner.os }}-pip-${{ hashFiles('client/python/requirements.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test/requirements.txt') }}
+ - uses: actions/cache@v4
+ id: frontend-cache
+ with:
+ path: |
+ gradio/templates/*
+ gradio/node/*
+ key: gradio-lib-front-end-${{ hashFiles('js/**', 'client/js/**')}}
+ - name: Install pnpm
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ uses: pnpm/action-setup@v2
+ with:
+ version: 8
+ - uses: actions/setup-node@v4
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ with:
+ node-version: 18
+ cache: pnpm
+ cache-dependency-path: pnpm-lock.yaml
+ - name: Build frontend
+ if: steps.frontend-cache.outputs.cache-hit != 'true'
+ run: |
+ pnpm i --frozen-lockfile --ignore-scripts
+ pnpm build
+ - name: Install Gradio and Client Libraries Locally (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ python -m pip install client/python
+ python -m pip install ".[oauth]"
+ - name: Install Test Dependencies (Linux)
+ if: steps.cache.outputs.cache-hit != 'true' && runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ bash scripts/install_test_requirements.sh
+ - name: Install ffmpeg
+ uses: FedericoCarboni/setup-ffmpeg@v2
+ - name: Lint (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ bash scripts/lint_backend.sh
+ - name: Typecheck (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ bash scripts/type_check_backend.sh
+ - name: Run tests (Linux)
+ if: runner.os == 'Linux'
+ run: |
+ . venv/bin/activate
+ python -m pytest -m "${{ matrix.test-type }}" --ignore=client
+ - name: Install Gradio and Client Libraries Locally (Windows)
+ if: runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ python -m pip install client/python
+ python -m pip install ".[oauth]"
+ - name: Install Test Dependencies (Windows)
+ if: steps.cache.outputs.cache-hit != 'true' && runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ python -m pip install . -r test/requirements.txt
+ - name: Run tests (Windows)
+ if: runner.os == 'Windows'
+ run: |
+ venv\Scripts\activate
+ python -m pytest -m "${{ matrix.test-type }}" --ignore=client
+ echo "The exit code for pytest was $LASTEXITCODE"
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ee853e1d677700f33bfa62b1d1b35833f6ab3e89
--- /dev/null
+++ b/.github/workflows/build-pr.yml
@@ -0,0 +1,76 @@
+name: Build PR Artifacts
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ comment-spaces-start:
+ uses: "./.github/workflows/comment-queue.yml"
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ github.event.pull_request.number }}
+ message: spaces~pending~null
+ build_pr:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.9'
+ - name: Install pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ version: 8
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: pnpm
+ cache-dependency-path: pnpm-lock.yaml
+ - name: Install pip
+ run: python -m pip install build requests
+ - name: Get PR Number
+ id: get_pr_number
+ run: |
+ if ${{ github.event_name == 'pull_request' }}; then
+ echo "GRADIO_VERSION=$(python -c 'import requests;print(requests.get("https://pypi.org/pypi/gradio/json").json()["info"]["version"])')" >> $GITHUB_OUTPUT
+ python -c "import os;print(os.environ['GITHUB_REF'].split('/')[2])" > pr_number.txt
+ echo "PR_NUMBER=$(cat pr_number.txt)" >> $GITHUB_OUTPUT
+ else
+ echo "GRADIO_VERSION=$(python -c 'import json; print(json.load(open("gradio/package.json"))["version"])')" >> $GITHUB_OUTPUT
+ echo "PR_NUMBER='main'" >> $GITHUB_OUTPUT
+ fi
+ - name: Build pr package
+ run: |
+ python -c 'import json; j = json.load(open("gradio/package.json")); j["version"] = "${{ steps.get_pr_number.outputs.GRADIO_VERSION }}"; json.dump(j, open("gradio/package.json", "w"))'
+ pnpm i --frozen-lockfile --ignore-scripts
+ pnpm build
+ python3 -m build -w
+ env:
+ NODE_OPTIONS: --max_old_space_size=8192
+ - name: Upload wheel
+ uses: actions/upload-artifact@v4
+ with:
+ name: gradio-${{ steps.get_pr_number.outputs.GRADIO_VERSION }}-py3-none-any.whl
+ path: dist/gradio-${{ steps.get_pr_number.outputs.GRADIO_VERSION }}-py3-none-any.whl
+ - name: Set up Demos
+ run: |
+ python scripts/copy_demos.py https://gradio-builds.s3.amazonaws.com/${{ github.sha }}/gradio-${{ steps.get_pr_number.outputs.GRADIO_VERSION }}-py3-none-any.whl \
+ "gradio-client @ git+https://github.com/gradio-app/gradio@${{ github.sha }}#subdirectory=client/python"
+ - name: Upload all_demos
+ uses: actions/upload-artifact@v4
+ with:
+ name: all_demos
+ path: demo/all_demos
+ - name: Create metadata artifact
+ run: |
+ python -c "import json; json.dump({'gh_sha': '${{ github.sha }}', 'pr_number': ${{ steps.get_pr_number.outputs.pr_number }}, 'version': '${{ steps.get_pr_number.outputs.GRADIO_VERSION }}', 'wheel': 'gradio-${{ steps.get_pr_number.outputs.GRADIO_VERSION }}-py3-none-any.whl'}, open('metadata.json', 'w'))"
+ - name: Upload metadata
+ uses: actions/upload-artifact@v4
+ with:
+ name: metadata.json
+ path: metadata.json
\ No newline at end of file
diff --git a/.github/workflows/check-demo-notebooks.yml b/.github/workflows/check-demo-notebooks.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6d5c6e868664ff8492686dbbe60b741562733a28
--- /dev/null
+++ b/.github/workflows/check-demo-notebooks.yml
@@ -0,0 +1,50 @@
+# This workflow will check if the run.py files in every demo match the run.ipynb notebooks.
+
+name: Check Demos Match Notebooks
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+ paths:
+ - 'demo/**'
+
+jobs:
+ comment-notebook-start:
+ uses: "./.github/workflows/comment-queue.yml"
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ github.event.pull_request.number }}
+ message: notebooks~pending~null
+ check-notebooks:
+ name: Generate Notebooks and Check
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ ref: ${{ github.event.pull_request.head.ref }}
+ repository: ${{ github.event.pull_request.head.repo.full_name }}
+ - name: Generate Notebooks
+ run: |
+ pip install nbformat && cd demo && python generate_notebooks.py
+ - name: Print Git Status
+ run: echo $(git status) && echo $(git diff)
+ - name: Assert Notebooks Match
+ id: assertNotebooksMatch
+ run: git status | grep "nothing to commit, working tree clean"
+ - name: Get PR Number
+ if: always()
+ run: |
+ python -c "import os;print(os.environ['GITHUB_REF'].split('/')[2])" > pr_number.txt
+ echo "PR_NUMBER=$(cat pr_number.txt)" >> $GITHUB_ENV
+ - name: Upload PR Number
+ if: always()
+ run: |
+ python -c "import json; json.dump({'pr_number': ${{ env.PR_NUMBER }}}, open('metadata.json', 'w'))"
+ - name: Upload metadata
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: metadata.json
+ path: metadata.json
\ No newline at end of file
diff --git a/.github/workflows/comment-queue.yml b/.github/workflows/comment-queue.yml
new file mode 100644
index 0000000000000000000000000000000000000000..54d8f788224a0bf9419981bf70f4cf73695aee4c
--- /dev/null
+++ b/.github/workflows/comment-queue.yml
@@ -0,0 +1,36 @@
+name: Comment on pull request without race conditions
+
+on:
+ workflow_call:
+ inputs:
+ pr_number:
+ type: string
+ message:
+ required: true
+ type: string
+ tag:
+ required: false
+ type: string
+ default: "previews"
+ additional_text:
+ required: false
+ type: string
+ default: ""
+ secrets:
+ gh_token:
+ required: true
+
+jobs:
+ comment:
+ concurrency:
+ group: ${{inputs.pr_number || inputs.tag}}
+ runs-on: ubuntu-latest
+ steps:
+ - name: comment on pr
+ uses: "gradio-app/github/actions/comment-pr@main"
+ with:
+ gh_token: ${{ secrets.gh_token }}
+ tag: ${{ inputs.tag }}
+ pr_number: ${{ inputs.pr_number}}
+ message: ${{ inputs.message }}
+ additional_text: ${{ inputs.additional_text }}
diff --git a/.github/workflows/delete-stale-spaces.yml b/.github/workflows/delete-stale-spaces.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3b93398a69a93aadc315192a6d17c2c182df4311
--- /dev/null
+++ b/.github/workflows/delete-stale-spaces.yml
@@ -0,0 +1,35 @@
+name: Delete Stale Spaces
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+ workflow_dispatch:
+ inputs:
+ daysStale:
+ description: 'How stale a space needs to be to be deleted (days)'
+ required: true
+ default: '7'
+
+
+jobs:
+ delete-old-spaces:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.9'
+ - name: Install pip
+ run: python -m pip install pip wheel requests
+ - name: Install Hub Client Library
+ run: pip install huggingface-hub==0.9.1
+ - name: Set daysStale
+ env:
+ DEFAULT_DAYS_STALE: '7'
+ run: echo "DAYS_STALE=${{ github.event.inputs.daysStale || env.DEFAULT_DAYS_STALE }}" >> $GITHUB_ENV
+ - name: Find and delete stale spaces
+ run: |
+ python scripts/delete_old_spaces.py $DAYS_STALE \
+ gradio-pr-deploys \
+ ${{ secrets.SPACES_DEPLOY_TOKEN }}
diff --git a/.github/workflows/deploy-chromatic.yml b/.github/workflows/deploy-chromatic.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1842b64b92965fa19158957db405abff9255fbd0
--- /dev/null
+++ b/.github/workflows/deploy-chromatic.yml
@@ -0,0 +1,88 @@
+name: 'deploy to chromatic'
+
+on:
+ push:
+ paths:
+ - 'js/**'
+ - 'gradio/themes/**'
+ - '.github/workflows/deploy-chromatic.yml'
+ - '!js/_website/**'
+
+
+jobs:
+ get-current-pr:
+ runs-on: ubuntu-latest
+ outputs:
+ pr_found: ${{ steps.get-pr.outputs.pr_found }}
+ pr_number: ${{ steps.get-pr.outputs.number }}
+ pr_labels: ${{ steps.get-pr.outputs.pr_labels }}
+ steps:
+ - uses: 8BitJonny/gh-get-current-pr@2.2.0
+ id: get-pr
+ with:
+ filterOutDraft: true
+ comment-chromatic-start:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: get-current-pr
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-current-pr.outputs.pr_number }}
+ message: |
+ storybook~pending~null
+ visual~pending~0~0~null
+ chromatic-deployment:
+ needs: get-current-pr
+ runs-on: ubuntu-latest
+ outputs:
+ changes: ${{ steps.publish-chromatic.outputs.changeCount }}
+ errors: ${{ steps.publish-chromatic.outputs.errorCount }}
+ storybook_url: ${{ steps.publish-chromatic.outputs.storybookUrl }}
+ build_url: ${{ steps.publish-chromatic.outputs.buildUrl }}
+ if: ${{ github.repository == 'gradio-app/gradio' && !contains(needs.get-current-pr.outputs.pr_labels, 'no-visual-update') }}
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: install dependencies
+ uses: "./.github/actions/install-all-deps"
+ with:
+ always-install-pnpm: true
+ skip_build: 'true'
+ - name: build client
+ run: pnpm --filter @gradio/client build
+ - name: generate theme.css
+ run: |
+ . venv/bin/activate
+ python scripts/generate_theme.py --outfile js/storybook/theme.css
+ - name: build storybook
+ run: pnpm build-storybook --quiet
+ - name: publish to chromatic
+ id: publish-chromatic
+ uses: chromaui/action@v10
+ with:
+ projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ onlyChanged: true
+ exitOnceUploaded: true
+ comment-chromatic-end:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [chromatic-deployment, get-current-pr]
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-current-pr.outputs.pr_number }}
+ message: |
+ storybook~success~${{ needs.chromatic-deployment.outputs.storybook_url }}
+ visual~success~${{ needs.chromatic-deployment.outputs.changes }}~${{ needs.chromatic-deployment.outputs.errors }}~${{ needs.chromatic-deployment.outputs.build_url }}
+ comment-chromatic-fail:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [chromatic-deployment, get-current-pr]
+ if: always() && needs.chromatic-deployment.result == 'failure'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-current-pr.outputs.pr_number }}
+ message: |
+ storybook~failure~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
+ visual~failure~0~0~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
\ No newline at end of file
diff --git a/.github/workflows/deploy-pr-to-spaces.yml b/.github/workflows/deploy-pr-to-spaces.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1e336512e6dbb1d6a115ab9f431268f628f7af5d
--- /dev/null
+++ b/.github/workflows/deploy-pr-to-spaces.yml
@@ -0,0 +1,99 @@
+name: Deploy PR to Spaces
+
+on:
+ workflow_run:
+ workflows: [Build PR Artifacts]
+ types:
+ - completed
+
+jobs:
+ deploy-current-pr:
+ outputs:
+ pr_number: ${{ steps.set-outputs.outputs.pr_number }}
+ space_url: ${{ steps.upload-demo.outputs.SPACE_URL }}
+ sha: ${{ steps.set-outputs.outputs.gh_sha }}
+ gradio_version: ${{ steps.set-outputs.outputs.gradio_version }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.9'
+ - name: Install pip
+ run: python -m pip install build requests
+ - name: Download metadata
+ run: python scripts/download_artifacts.py ${{github.event.workflow_run.id }} metadata.json ${{ secrets.COMMENT_TOKEN }} --owner ${{ github.repository_owner }}
+ - run: unzip metadata.json.zip
+ - name: set outputs
+ id: set-outputs
+ run: |
+ echo "wheel_name=$(python -c 'import json; print(json.load(open("metadata.json"))["wheel"])')" >> $GITHUB_OUTPUT
+ echo "gh_sha=$(python -c 'import json; print(json.load(open("metadata.json"))["gh_sha"])')" >> $GITHUB_OUTPUT
+ echo "gradio_version=$(python -c 'import json; print(json.load(open("metadata.json"))["version"])')" >> $GITHUB_OUTPUT
+ echo "pr_number=$(python -c 'import json; print(json.load(open("metadata.json"))["pr_number"])')" >> $GITHUB_OUTPUT
+ - name: 'Download wheel'
+ run: python scripts/download_artifacts.py ${{ github.event.workflow_run.id }} ${{ steps.set-outputs.outputs.wheel_name }} ${{ secrets.COMMENT_TOKEN }} --owner ${{ github.repository_owner }}
+ - run: unzip ${{ steps.set-outputs.outputs.wheel_name }}.zip
+ - name: Upload wheel
+ run: |
+ export AWS_ACCESS_KEY_ID=${{ secrets.PR_DEPLOY_KEY }}
+ export AWS_SECRET_ACCESS_KEY=${{ secrets.PR_DEPLOY_SECRET }}
+ export AWS_DEFAULT_REGION=us-east-1
+ aws s3 cp ${{ steps.set-outputs.outputs.wheel_name }} s3://gradio-builds/${{ steps.set-outputs.outputs.gh_sha }}/
+ - name: Install Hub Client Library
+ run: pip install huggingface-hub
+ - name: 'Download all_demos'
+ run: python scripts/download_artifacts.py ${{ github.event.workflow_run.id }} all_demos ${{ secrets.COMMENT_TOKEN }} --owner ${{ github.repository_owner }}
+ - run: unzip all_demos.zip -d all_demos
+ - run: cp -R all_demos/* demo/all_demos
+ - name: Upload demo to spaces
+ if: github.event.workflow_run.event == 'pull_request'
+ id: upload-demo
+ run: |
+ python scripts/upload_demo_to_space.py all_demos \
+ gradio-pr-deploys/pr-${{ steps.set-outputs.outputs.pr_number }}-all-demos \
+ ${{ secrets.SPACES_DEPLOY_TOKEN }} \
+ --gradio-version ${{ steps.set-outputs.outputs.gradio_version }} > url.txt
+ echo "SPACE_URL=$(cat url.txt)" >> $GITHUB_OUTPUT
+ - name: Upload Website Demos
+ if: >
+ github.event.workflow_run.event == 'workflow_dispatch' &&
+ github.event.workflow_run.conclusion == 'success'
+ id: upload-website-demos
+ run: |
+ python scripts/upload_website_demos.py --AUTH_TOKEN ${{ secrets.WEBSITE_SPACES_DEPLOY_TOKEN }} \
+ --WHEEL_URL https://gradio-builds.s3.amazonaws.com/${{ steps.set-outputs.outputs.gh_sha }}/ \
+ --GRADIO_VERSION ${{ steps.set-outputs.outputs.gradio_version }}
+
+ comment-spaces-success:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [deploy-current-pr]
+ if: >
+ github.event.workflow_run.event == 'pull_request' &&
+ github.event.workflow_run.conclusion == 'success' &&
+ needs.deploy-current-pr.result == 'success'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.deploy-current-pr.outputs.pr_number }}
+ message: spaces~success~${{ needs.deploy-current-pr.outputs.space_url }}
+ additional_text: |
+ **Install Gradio from this PR**
+ ```bash
+ pip install https://gradio-builds.s3.amazonaws.com/${{ needs.deploy-current-pr.outputs.sha }}/gradio-${{ needs.deploy-current-pr.outputs.gradio_version }}-py3-none-any.whl
+ ```
+
+ **Install Gradio Python Client from this PR**
+ ```bash
+ pip install "gradio-client @ git+https://github.com/gradio-app/gradio@${{ needs.deploy-current-pr.outputs.sha }}#subdirectory=client/python"
+ ```
+ comment-spaces-failure:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [deploy-current-pr]
+ if: always() && needs.deploy-current-pr.result == 'failure'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.deploy-current-pr.outputs.pr_number }}
+ message: spaces~failure~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7485a3c3afc30d74f4806fc1537eadb84b5f4554
--- /dev/null
+++ b/.github/workflows/deploy-website.yml
@@ -0,0 +1,108 @@
+name: "deploy website"
+
+on:
+ workflow_call:
+ inputs:
+ branch_name:
+ description: "The branch name"
+ type: string
+ pr_number:
+ description: "The PR number"
+ type: string
+ secrets:
+ vercel_token:
+ description: "Vercel API token"
+ gh_token:
+ description: "Github token"
+ required: true
+ vercel_org_id:
+ description: "Vercel organization ID"
+ required: true
+ vercel_project_id:
+ description: "Vercel project ID"
+ required: true
+
+env:
+ VERCEL_ORG_ID: ${{ secrets.vercel_org_id }}
+ VERCEL_PROJECT_ID: ${{ secrets.vercel_project_id }}
+
+jobs:
+ comment-deploy-start:
+ uses: "./.github/workflows/comment-queue.yml"
+ secrets:
+ gh_token: ${{ secrets.gh_token }}
+ with:
+ pr_number: ${{ inputs.pr_number }}
+ message: website~pending~null
+ deploy:
+ name: "Deploy website"
+ runs-on: ubuntu-latest
+ outputs:
+ vercel_url: ${{ steps.output_url.outputs.vercel_url }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: install dependencies
+ uses: "./.github/actions/install-frontend-deps"
+ with:
+ always-install-pnpm: true
+ skip_build: true
+ - name: download artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: website-json-${{ inputs.pr_number }}
+ path: |
+ ./js/_website/src/lib/json
+ - name: echo artifact path
+ shell: bash
+ run: ls ./js/_website/src/lib/json
+ - name: Install Vercel CLI
+ shell: bash
+ run: pnpm install --global vercel@latest
+ # preview
+ - name: Pull Vercel Environment Information
+ shell: bash
+ if: github.event_name == 'pull_request'
+ run: vercel pull --yes --environment=preview --token=${{ secrets.vercel_token }}
+ - name: Build Project Artifacts
+ if: github.event_name == 'pull_request'
+ shell: bash
+ run: vercel build --token=${{ secrets.vercel_token }}
+ - name: Deploy Project Artifacts to Vercel
+ if: github.event_name == 'pull_request'
+ id: output_url
+ shell: bash
+ run: echo "vercel_url=$(vercel deploy --prebuilt --token=${{ secrets.vercel_token }})" >> $GITHUB_OUTPUT
+ # production
+ - name: Pull Vercel Environment Information
+ if: github.event_name == 'push' && inputs.branch_name == 'main'
+ shell: bash
+ run: vercel pull --yes --environment=production --token=${{ secrets.vercel_token }}
+ - name: Build Project Artifacts
+ if: github.event_name == 'push' && inputs.branch_name == 'main'
+ shell: bash
+ run: vercel build --prod --token=${{ secrets.vercel_token }}
+ - name: Deploy Project Artifacts to Vercel
+ if: github.event_name == 'push' && inputs.branch_name == 'main'
+ shell: bash
+ run: echo "VERCEL_URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.vercel_token }})" >> $GITHUB_ENV
+ - name: echo vercel url
+ shell: bash
+ run: echo $VERCEL_URL #add to comment
+ comment-deploy-success:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: deploy
+ if: needs.deploy.result == 'success'
+ secrets:
+ gh_token: ${{ secrets.gh_token }}
+ with:
+ pr_number: ${{ inputs.pr_number }}
+ message: website~success~${{needs.deploy.outputs.vercel_url}}
+ comment-deploy-failure:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: deploy
+ if: always() && needs.deploy.result == 'failure'
+ secrets:
+ gh_token: ${{ secrets.gh_token }}
+ with:
+ pr_number: ${{ inputs.pr_number }}
+ message: website~failure~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
\ No newline at end of file
diff --git a/.github/workflows/generate-changeset.yml b/.github/workflows/generate-changeset.yml
new file mode 100644
index 0000000000000000000000000000000000000000..50c4af6c644bcafc4cf46db2a5036f24c976d335
--- /dev/null
+++ b/.github/workflows/generate-changeset.yml
@@ -0,0 +1,88 @@
+name: Generate changeset
+on:
+ workflow_run:
+ workflows: ["trigger changeset generation"]
+ types:
+ - completed
+
+env:
+ CI: true
+ NODE_OPTIONS: "--max-old-space-size=4096"
+
+concurrency:
+ group: ${{ github.event.workflow_run.head_repository.full_name }}::${{ github.event.workflow_run.head_branch }}
+
+jobs:
+ get-pr:
+ runs-on: ubuntu-latest
+ if: github.event.workflow_run.conclusion == 'success'
+ outputs:
+ found_pr: ${{ steps.pr_details.outputs.found_pr }}
+ pr_number: ${{ steps.pr_details.outputs.pr_number }}
+ source_repo: ${{ steps.pr_details.outputs.source_repo }}
+ source_branch: ${{ steps.pr_details.outputs.source_branch }}
+ steps:
+ - name: get pr details
+ id: pr_details
+ uses: gradio-app/github/actions/find-pr@main
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ comment-changes-start:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: get-pr
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr.outputs.pr_number }}
+ message: changes~pending~null
+ version:
+ permissions: write-all
+ name: static checks
+ needs: get-pr
+ runs-on: ubuntu-22.04
+ if: needs.get-pr.outputs.found_pr == 'true'
+ outputs:
+ skipped: ${{ steps.version.outputs.skipped }}
+ comment_url: ${{ steps.version.outputs.comment_url }}
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ repository: ${{ needs.get-pr.outputs.source_repo }}
+ ref: ${{ needs.get-pr.outputs.source_branch }}
+ fetch-depth: 0
+ token: ${{ secrets.COMMENT_TOKEN }}
+ - name: generate changeset
+ id: version
+ uses: "gradio-app/github/actions/generate-changeset@main"
+ with:
+ github_token: ${{ secrets.COMMENT_TOKEN }}
+ main_pkg: gradio
+ pr_number: ${{ needs.get-pr.outputs.pr_number }}
+ branch_name: ${{ needs.get-pr.outputs.source_branch }}
+ comment-changes-skipped:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [get-pr, version]
+ if: needs.version.result == 'success' && needs.version.outputs.skipped == 'true'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr.outputs.pr_number }}
+ message: changes~warning~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
+ comment-changes-success:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [get-pr, version]
+ if: needs.version.result == 'success' && needs.version.outputs.skipped == 'false'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr.outputs.pr_number }}
+ message: changes~success~${{ needs.version.outputs.comment_url }}
+ comment-changes-failure:
+ uses: "./.github/workflows/comment-queue.yml"
+ needs: [get-pr, version]
+ if: always() && needs.version.result == 'failure'
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr.outputs.pr_number }}
+ message: changes~failure~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
\ No newline at end of file
diff --git a/.github/workflows/large-files.yml b/.github/workflows/large-files.yml
new file mode 100644
index 0000000000000000000000000000000000000000..50c6fb74b6d7d7638c41ba8da6c38070f2d68594
--- /dev/null
+++ b/.github/workflows/large-files.yml
@@ -0,0 +1,21 @@
+name: Check for large files
+
+on:
+ pull_request:
+
+jobs:
+ check-files:
+ runs-on: ubuntu-latest
+ if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ ref: ${{ github.event.pull_request.head.ref }}
+ repository: ${{ github.event.pull_request.head.repo.full_name }}
+ - name: Check for large files
+ uses: actionsdesk/lfs-warning@v3.2
+ with:
+ filesizelimit: 5MB
+
diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d29e9fd6b8d0848b941ce7dffdef50666f154bff
--- /dev/null
+++ b/.github/workflows/publish-npm.yml
@@ -0,0 +1,77 @@
+name: Changesets
+on:
+ push:
+ branches:
+ - main
+
+env:
+ CI: true
+ PNPM_CACHE_FOLDER: .pnpm-store
+ NODE_OPTIONS: "--max-old-space-size=4096"
+jobs:
+ version_or_publish:
+ runs-on: ubuntu-22.04
+ steps:
+ - name: checkout repo
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+ - name: install dependencies
+ uses: "./.github/actions/install-all-deps"
+ with:
+ always-install-pnpm: true
+ node_auth_token: ${{ secrets.NPM_TOKEN }}
+ npm_token: ${{ secrets.NPM_TOKEN }}
+ skip_build: 'true'
+ - name: Build packages
+ run: |
+ . venv/bin/activate
+ pip install build
+ pnpm --filter @gradio/client --filter @gradio/lite build
+ - name: create and publish versions
+ id: changesets
+ uses: changesets/action@v1
+ with:
+ version: pnpm ci:version
+ commit: "chore: update versions"
+ title: "chore: update versions"
+ publish: pnpm ci:publish
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GRADIO_PAT }}
+ - name: add label to skip chromatic build
+ if: ${{ steps.changesets.outputs.pullRequestNumber != '' && steps.changesets.outputs.pullRequestNumber != 'undefined' }}
+ run: gh pr edit "$PR_NUMBER" --add-label "no-visual-update"
+ env:
+ PR_NUMBER: ${{ steps.changesets.outputs.pullRequestNumber }}
+ GITHUB_TOKEN: ${{ secrets.GRADIO_PAT }}
+ - name: add label to run flaky tests
+ if: ${{ steps.changesets.outputs.pullRequestNumber != '' && steps.changesets.outputs.pullRequestNumber != 'undefined' }}
+ run: gh pr edit "$PR_NUMBER" --add-label "flaky-tests"
+ env:
+ PR_NUMBER: ${{ steps.changesets.outputs.pullRequestNumber }}
+ GITHUB_TOKEN: ${{ secrets.GRADIO_PAT }}
+ - name: add label to run backend tests on Windows
+ if: ${{ steps.changesets.outputs.pullRequestNumber != '' && steps.changesets.outputs.pullRequestNumber != 'undefined' }}
+ run: gh pr edit "$PR_NUMBER" --add-label "windows-tests"
+ env:
+ PR_NUMBER: ${{ steps.changesets.outputs.pullRequestNumber }}
+ GITHUB_TOKEN: ${{ secrets.GRADIO_PAT }}
+ - name: publish to pypi
+ if: steps.changesets.outputs.hasChangesets != 'true'
+ uses: "gradio-app/github/actions/publish-pypi@main"
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWSACCESSKEYID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWSSECRETKEY }}
+ AWS_DEFAULT_REGION: us-west-2
+ with:
+ user: __token__
+ passwords: |
+ gradio:${{ secrets.PYPI_API_TOKEN }}
+ gradio_client:${{ secrets.PYPI_GRADIO_CLIENT_TOKEN }}
+ - name: trigger spaces deploy workflow
+ env:
+ GITHUB_TOKEN: ${{ secrets.COMMENT_TOKEN }}
+ run: gh workflow run build-pr.yml
\ No newline at end of file
diff --git a/.github/workflows/report-notebook-status-pr.yml b/.github/workflows/report-notebook-status-pr.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d943420e442aaa47833ee5530377bac02b7a489f
--- /dev/null
+++ b/.github/workflows/report-notebook-status-pr.yml
@@ -0,0 +1,47 @@
+on:
+ workflow_run:
+ workflows: [Check Demos Match Notebooks]
+ types: [completed]
+
+jobs:
+ get-pr-number:
+ runs-on: ubuntu-latest
+ outputs:
+ pr_number: ${{ steps.pr_number.outputs.pr_number }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.9'
+ - name: Install pip
+ run: python -m pip install requests
+ - name: Download metadata
+ run: python scripts/download_artifacts.py ${{github.event.workflow_run.id }} metadata.json ${{ secrets.COMMENT_TOKEN }} --owner ${{ github.repository_owner }}
+ - run: unzip metadata.json.zip
+ - name: Pipe metadata to env
+ id: pr_number
+ run: echo "pr_number=$(python -c 'import json; print(json.load(open("metadata.json"))["pr_number"])')" >> $GITHUB_OUTPUT
+ comment-success:
+ uses: "./.github/workflows/comment-queue.yml"
+ if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.name == 'Check Demos Match Notebooks'}}
+ needs: get-pr-number
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr-number.outputs.pr_number }}
+ message: notebooks~success~null
+ comment-failure:
+ uses: "./.github/workflows/comment-queue.yml"
+ if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.name == 'Check Demos Match Notebooks'}}
+ needs: get-pr-number
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ with:
+ pr_number: ${{ needs.get-pr-number.outputs.pr_number }}
+ message: notebooks~failure~https://github.com/gradio-app/gradio/actions/runs/${{github.run_id}}/
+ additional_text: |
+ The demo notebooks don't match the run.py files. Please run this command from the root of the repo and then commit the changes:
+ ```bash
+ pip install nbformat && cd demo && python generate_notebooks.py
+ ```
\ No newline at end of file
diff --git a/.github/workflows/trigger-changeset.yml b/.github/workflows/trigger-changeset.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cc6e20d9962b43ada7113702be3e37e17cbab60a
--- /dev/null
+++ b/.github/workflows/trigger-changeset.yml
@@ -0,0 +1,19 @@
+name: trigger changeset generation
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, edited, labeled, unlabeled]
+ branches:
+ - main
+ issue_comment:
+ types: [edited]
+
+jobs:
+ version:
+ permissions: write-all
+ name: static checks
+ runs-on: ubuntu-22.04
+ if: github.event.sender.login != 'gradio-pr-bot'
+ steps:
+ - run: echo ${{ github.event_name }}
+ - run: echo ${{ github.event.sender.login }}
+ - run: echo "Triggering changeset generation"
diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3cf5ce416a4e369890f81a9015421f6ad2012d68
--- /dev/null
+++ b/.github/workflows/ui.yml
@@ -0,0 +1,103 @@
+name: gradio-ui
+
+on:
+ push:
+ branches:
+ - "main"
+ pull_request:
+
+env:
+ CI: true
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
+ NODE_OPTIONS: "--max-old-space-size=4096"
+ VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
+ VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
+concurrency:
+ group: deploy-${{ github.ref }}-${{ github.event_name == 'push' || github.event.inputs.fire != null }}
+ cancel-in-progress: true
+
+jobs:
+ quick-checks:
+ name: static checks
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+ - name: install dependencies
+ uses: "./.github/actions/install-frontend-deps"
+ with:
+ always-install-pnpm: true
+ - name: build client
+ run: pnpm --filter @gradio/client build
+ - name: build the wasm module
+ run: pnpm --filter @gradio/wasm build
+ - name: format check
+ run: pnpm format:check
+ - name: lint
+ run: pnpm lint
+ - name: typecheck
+ run: pnpm ts:check
+ - name: unit tests
+ run: pnpm test:run
+ functional-test:
+ runs-on: ubuntu-latest
+ outputs:
+ source_branch: ${{ steps.pr_details.outputs.source_branch }}
+ pr_number: ${{ steps.pr_details.outputs.pr_number }}
+ steps:
+ - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
+ - name: install dependencies
+ id: install_deps
+ uses: "./.github/actions/install-all-deps"
+ with:
+ always-install-pnpm: true
+ - name: get pr details
+ id: pr_details
+ uses: gradio-app/github/actions/find-pr@main
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ - name: deploy json to aws
+ if: steps.pr_details.outputs.source_branch == 'changeset-release/main'
+ run: |
+ export AWS_ACCESS_KEY_ID=${{ secrets.AWSACCESSKEYID }}
+ export AWS_SECRET_ACCESS_KEY=${{ secrets.AWSSECRETKEY }}
+ export AWS_DEFAULT_REGION=us-west-2
+ version=$(jq -r .version js/_website/src/lib/json/version.json)
+ aws s3 cp ./js/_website/src/lib/json/ s3://gradio-docs-json/$version/ --recursive
+ - name: install outbreak_forecast dependencies
+ run: |
+ . venv/bin/activate
+ python -m pip install -r demo/outbreak_forecast/requirements.txt
+ - run: pnpm exec playwright install chromium
+ - name: run browser tests
+ run: |
+ . venv/bin/activate
+ CI=1 pnpm test:browser
+ - name: upload screenshots
+ uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-screenshots
+ path: |
+ ./test-results
+ - name: run browser component tests
+ run: |
+ . venv/bin/activate
+ pnpm run test:ct
+ - name: save artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: website-json-${{ steps.pr_details.outputs.pr_number }}
+ path: |
+ ./js/_website/src/lib/json
+ deploy_to_vercel:
+ uses: "./.github/workflows/deploy-website.yml"
+ needs: functional-test
+ if: always()
+ secrets:
+ gh_token: ${{ secrets.COMMENT_TOKEN }}
+ vercel_token: ${{ secrets.VERCEL_TOKEN }}
+ vercel_org_id: ${{ secrets.VERCEL_ORG_ID }}
+ vercel_project_id: ${{ secrets.VERCEL_PROJECT_ID }}
+ with:
+ branch_name: ${{ needs.functional-test.outputs.source_branch }}
+ pr_number: ${{ needs.functional-test.outputs.pr_number }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c79420e85a6811dfe07e8a5a7b6c3f6230d3b832
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,80 @@
+# Python build
+.eggs/
+gradio.egg-info
+dist/
+*.pyc
+__pycache__/
+*.py[cod]
+*$py.class
+build/
+__tmp/*
+*.pyi
+py.typed
+
+# JS build
+gradio/templates/*
+gradio/node/*
+gradio/_frontend_code/*
+js/gradio-preview/test/*
+
+# Secrets
+.env
+
+# Gradio run artifacts
+*.db
+*.sqlite3
+gradio/launches.json
+flagged/
+gradio_cached_examples/
+tmp.zip
+
+# Tests
+.coverage
+coverage.xml
+test.txt
+**/snapshots/**/*.png
+playwright-report/
+
+# Demos
+demo/tmp.zip
+demo/files/*.avi
+demo/files/*.mp4
+demo/all_demos/demos/*
+demo/all_demos/requirements.txt
+demo/*/config.json
+demo/annotatedimage_component/*.png
+
+# Etc
+.idea/*
+.DS_Store
+*.bak
+workspace.code-workspace
+*.h5
+
+# dev containers
+.pnpm-store/
+
+# log files
+.pnpm-debug.log
+
+# Local virtualenv for devs
+.venv*
+
+# FRP
+gradio/frpc_*
+.vercel
+
+# js
+node_modules
+public/build/
+test-results
+client/js/test.js
+.config/test.py
+
+# storybook
+storybook-static
+build-storybook.log
+js/storybook/theme.css
+
+# playwright
+.config/playwright/.cache
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94e184c9c9c254edd18b91f54903b6c97e544d4
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,9 @@
+{
+ "recommendations": [
+ "dbaeumer.vscode-eslint",
+ "phoenisx.cssvar",
+ "esbenp.prettier-vscode",
+ "svelte.svelte-vscode",
+ "charliermarsh.ruff"
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..73595981aea90ef5f62289b210c9a564b49deb08
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,23 @@
+{
+ "python.formatting.provider": "none",
+ "cssvar.files": ["./js/node_modules/pollen-css/pollen.css"],
+ "cssvar.ignore": [],
+ "cssvar.disableSort": true,
+ "cssvar.extensions": ["js", "css", "html", "jsx", "tsx", "svelte"],
+ "python.analysis.extraPaths": ["./gradio/themes/utils"],
+ "svelte.plugin.svelte.format.enable": true,
+ "svelte.plugin.svelte.diagnostics.enable": false,
+ "svelte.enable-ts-plugin": true,
+ "prettier.configPath": ".config/.prettierrc.json",
+ "prettier.ignorePath": ".config/.prettierignore",
+ "python.analysis.typeCheckingMode": "basic",
+ "python.testing.pytestArgs": ["."],
+ "python.testing.unittestEnabled": false,
+ "python.testing.pytestEnabled": true,
+ "eslint.validate": ["javascript", "typescript", "html", "markdown", "svelte"],
+ "eslint.experimental.useFlatConfig": true,
+ "eslint.options": {
+ "overrideConfigFile": "./.config/eslint.config.js"
+ },
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..4b993d7053b6a09c0974557e458ced890771d62a
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4904 @@
+# gradio
+
+## 4.16.0
+
+### Features
+
+- [#7124](https://github.com/gradio-app/gradio/pull/7124) [`21a16c6`](https://github.com/gradio-app/gradio/commit/21a16c60e8f34b870bd2aae9af07713eb1307252) - add params to `gr.Interface` and `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7139](https://github.com/gradio-app/gradio/pull/7139) [`6abad53`](https://github.com/gradio-app/gradio/commit/6abad536778517a2ab9f5fc75d52afc576f01218) - Added polars dataframe support with demo. Thanks [@cswamy](https://github.com/cswamy)!
+- [#7084](https://github.com/gradio-app/gradio/pull/7084) [`94aa271`](https://github.com/gradio-app/gradio/commit/94aa271ab11fc3426a7e143ebaa757eb30c9911d) - Improve rapid generation performance via UI throttling. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#7104](https://github.com/gradio-app/gradio/pull/7104) [`bc2cdc1`](https://github.com/gradio-app/gradio/commit/bc2cdc1df95b38025486cf76df4a494b66d98585) - Allow download button for interactive Audio and Video components. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7109](https://github.com/gradio-app/gradio/pull/7109) [`125a832`](https://github.com/gradio-app/gradio/commit/125a832ab7ee2b5affa574e8b32c88f430cc6663) - generate docs when running `gradio cc build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7148](https://github.com/gradio-app/gradio/pull/7148) [`c60ad4d`](https://github.com/gradio-app/gradio/commit/c60ad4d34ab5b56a89bf6796822977e51e7a4a32) - Use Gallery as input component. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7049](https://github.com/gradio-app/gradio/pull/7049) [`1718c4a`](https://github.com/gradio-app/gradio/commit/1718c4aeb23a88ef02b17b30a1d1cb72e413e04a) - add STL 3D model support. Thanks [@Mon-ius](https://github.com/Mon-ius)!
+- [#7159](https://github.com/gradio-app/gradio/pull/7159) [`6ee22dc`](https://github.com/gradio-app/gradio/commit/6ee22dc6a8f6419e127a0f650e58c87a31bc59c9) - Ensure `gradio cc publish` uploads the documentation space, if it exists. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7034](https://github.com/gradio-app/gradio/pull/7034) [`82fe73d`](https://github.com/gradio-app/gradio/commit/82fe73d04297ac4e2c3ef42edc62bab4300bf915) - Redirect with query params after oauth. Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#7063](https://github.com/gradio-app/gradio/pull/7063) [`2cdcf4a`](https://github.com/gradio-app/gradio/commit/2cdcf4a890202a55673588c16f27b327d27915b6) - Single oauth button. Thanks [@Wauplin](https://github.com/Wauplin)!
+
+### Fixes
+
+- [#7126](https://github.com/gradio-app/gradio/pull/7126) [`5727b92`](https://github.com/gradio-app/gradio/commit/5727b92abc8a00a675bfc0a921b38de771af947b) - Allow buttons to take null value. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7112](https://github.com/gradio-app/gradio/pull/7112) [`217bfe3`](https://github.com/gradio-app/gradio/commit/217bfe39ca6a0de885824f16be4a707e7f032d57) - Support audio data in `np.int8` format in the `gr.Audio` component. Thanks [@Ram-Pasupula](https://github.com/Ram-Pasupula)!
+- [#7029](https://github.com/gradio-app/gradio/pull/7029) [`ac73555`](https://github.com/gradio-app/gradio/commit/ac735551bb2ccc288b2bbf10b008b6c3d9e65132) - Run before_fn and after_fn for each generator iteration. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7131](https://github.com/gradio-app/gradio/pull/7131) [`7d53aa1`](https://github.com/gradio-app/gradio/commit/7d53aa13a304d056d1973b8e86c6f89ff84cbd28) - Miscellaneous doc fixes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7138](https://github.com/gradio-app/gradio/pull/7138) [`ca8753b`](https://github.com/gradio-app/gradio/commit/ca8753bb3d829d0077f758ba8d0ddc866ff74d3d) - Fixes: Chatbot crashes when given empty url following http:// or https://. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#7115](https://github.com/gradio-app/gradio/pull/7115) [`cb90b3d`](https://github.com/gradio-app/gradio/commit/cb90b3d5d6a291270e047e10f9173cbc03678e1c) - Programmatically determine max wheel version to push to spaces. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7107](https://github.com/gradio-app/gradio/pull/7107) [`80f8fbf`](https://github.com/gradio-app/gradio/commit/80f8fbf0e8900627b9c2575bbd7c68fad8108544) - Add logic to handle non-interactive or hidden tabs. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7142](https://github.com/gradio-app/gradio/pull/7142) [`b961652`](https://github.com/gradio-app/gradio/commit/b9616528ab099aab0adc7027bce4655111f7366c) - Remove kwargs from template components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7125](https://github.com/gradio-app/gradio/pull/7125) [`45f725f`](https://github.com/gradio-app/gradio/commit/45f725f8d0dc7813b3d2e768ca9582d6ad878d6f) - un-disable output components after exception is raised. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7081](https://github.com/gradio-app/gradio/pull/7081) [`44c53d9`](https://github.com/gradio-app/gradio/commit/44c53d9bde7cab605b7dbd16331683d13cae029e) - Fix dropdown refocusing due to ` ` element. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7130](https://github.com/gradio-app/gradio/pull/7130) [`e7ab406`](https://github.com/gradio-app/gradio/commit/e7ab4063eb2624820b9f1076960e9596791d9427) - Fix ParamViewer css. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7113](https://github.com/gradio-app/gradio/pull/7113) [`28e8a8a`](https://github.com/gradio-app/gradio/commit/28e8a8a3ec8acd653182577273be4244a4817082) - Reduce CPU usage of dev mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7082](https://github.com/gradio-app/gradio/pull/7082) [`c35fac0`](https://github.com/gradio-app/gradio/commit/c35fac049a44b14719509443c68690e7f23ce70d) - Ensure device selection works in Audio when streaming. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7045](https://github.com/gradio-app/gradio/pull/7045) [`13cb6af`](https://github.com/gradio-app/gradio/commit/13cb6af8b23be063d85b2c632f36afa37d874e5d) - Ensure microphone devices list updates. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7150](https://github.com/gradio-app/gradio/pull/7150) [`be56c76`](https://github.com/gradio-app/gradio/commit/be56c76c7b5d2814ea8239c7dbeddc4b1d3701c4) - Lite: Add the `home_dir` to `sys.path`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#7133](https://github.com/gradio-app/gradio/pull/7133) [`8c355a4`](https://github.com/gradio-app/gradio/commit/8c355a47844296e3aab250fe61e2ecc706122e78) - Add ruff mock for Lite. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6826](https://github.com/gradio-app/gradio/pull/6826) [`e8b2d8b`](https://github.com/gradio-app/gradio/commit/e8b2d8b2f81b7c4b2d107765f06eaf09a030f1df) - Add sample rate config option to `gr.Audio()`. Thanks [@tsukumijima](https://github.com/tsukumijima)!
+
+## 4.15.0
+
+### Highlights
+
+#### Custom component documentation generator ([#7030](https://github.com/gradio-app/gradio/pull/7030) [`3a944ed`](https://github.com/gradio-app/gradio/commit/3a944ed9f162a224d26959a9c556346a9d205311))
+
+If your custom component has type hints and docstrings for both parameters and return values, you can now automatically generate a documentation page and README.md with no additional effort. Simply run the following command:
+
+```sh
+gradio cc docs
+```
+
+This will generate a Gradio app that you can upload to spaces providing rich documentation for potential users. The documentation page includes:
+
+- Installation instructions.
+- A live embedded demo and working code snippet, pulled from your demo app.
+- An API reference for initialising the component, with types, default values and descriptions.
+- An explanation of how the component affects the user's predict function inputs and outputs.
+- Any additional interfaces or classes that are necessary to understand the API reference.
+- Optional links to GitHub, PyPi, and Hugging Face Spaces.
+
+A README will also be generated detailing the same information but in a format that is optimised for viewing on GitHub or PyPi!
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+### Features
+
+- [#7075](https://github.com/gradio-app/gradio/pull/7075) [`1fc8a94`](https://github.com/gradio-app/gradio/commit/1fc8a941384775f587a6ef30365960f43353cb0d) - fix lint. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7069](https://github.com/gradio-app/gradio/pull/7069) [`07d520c`](https://github.com/gradio-app/gradio/commit/07d520c7a2590eb5544bd0b17f82ea31ecf43e00) - fix versions. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7058](https://github.com/gradio-app/gradio/pull/7058) [`3642b7a`](https://github.com/gradio-app/gradio/commit/3642b7ac93128793b75b94f8d785457869a4447e) - publish: simplify twine_files code. Thanks [@akx](https://github.com/akx)!
+- [#7054](https://github.com/gradio-app/gradio/pull/7054) [`64c65d8`](https://github.com/gradio-app/gradio/commit/64c65d821983961111297a969946d87e2fc4105d) - Add encoding to open/writing files on the deploy_discord function. Thanks [@WilliamHarer](https://github.com/WilliamHarer)!
+- [#7024](https://github.com/gradio-app/gradio/pull/7024) [`f2d69fc`](https://github.com/gradio-app/gradio/commit/f2d69fc7d0c1c3457112e702b53e38a0255fc1b7) - Fix gallery thumbnail design regression. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7018](https://github.com/gradio-app/gradio/pull/7018) [`ec28b4e`](https://github.com/gradio-app/gradio/commit/ec28b4e7c47a9233d9e3a725cc9fe8f9044dfa94) - Add `visible` and `interactive` params to `gr.Tab()`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7060](https://github.com/gradio-app/gradio/pull/7060) [`aaecfe5`](https://github.com/gradio-app/gradio/commit/aaecfe54d913c1c4713e23233f32ae1e4239730e) - Themes: fix bogus header image URL. Thanks [@akx](https://github.com/akx)!
+
+### Fixes
+
+- [#7050](https://github.com/gradio-app/gradio/pull/7050) [`a336508`](https://github.com/gradio-app/gradio/commit/a3365086468568db871940fa2807454ac047cadd) - Fix bug preventing layout components to be used as custom components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7055](https://github.com/gradio-app/gradio/pull/7055) [`3c3cf86`](https://github.com/gradio-app/gradio/commit/3c3cf8618a8cad1ef66a7f96664923d2c9f5e0e2) - Fix UI freeze on rapid generators. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#7046](https://github.com/gradio-app/gradio/pull/7046) [`9201f86`](https://github.com/gradio-app/gradio/commit/9201f86450c377f78a77ac003a5d5ff009a8894c) - Raise error in build step if custom component package is not installed. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6933](https://github.com/gradio-app/gradio/pull/6933) [`9cefd2e`](https://github.com/gradio-app/gradio/commit/9cefd2e90a1d0cc4d3e4e953fc5b9b1a7afb68dd) - Refactor examples so they accept data in the same format as is returned by function, rename `.as_example()` to `.process_example()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6980](https://github.com/gradio-app/gradio/pull/6980) [`523b6bc`](https://github.com/gradio-app/gradio/commit/523b6bc534e221b028a3ea3f274c7466fe242d5a) - `gr.update(value=[])` for `gr.File()` clears it. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#7038](https://github.com/gradio-app/gradio/pull/7038) [`6be3c2c`](https://github.com/gradio-app/gradio/commit/6be3c2c47a616c904c8497d1fbef7a851c54d488) - Fix Chatbot custom component template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6982](https://github.com/gradio-app/gradio/pull/6982) [`3f139c7`](https://github.com/gradio-app/gradio/commit/3f139c7c995f749562bb007d2a567bb167669de9) - Fix File drag and drop for specific file_types. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.14.0
+
+### Features
+
+- [#6994](https://github.com/gradio-app/gradio/pull/6994) [`623bc1a`](https://github.com/gradio-app/gradio/commit/623bc1aeb19945c1f3c68ea66fa669d1169483a3) - Switch default order for sources for `gr.Video` so that upload is the default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6965](https://github.com/gradio-app/gradio/pull/6965) [`5d00dd3`](https://github.com/gradio-app/gradio/commit/5d00dd37ca14bbfef2ceac550b29dbe05ba8cab0) - Make Wasm-compatible. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6945](https://github.com/gradio-app/gradio/pull/6945) [`ccf317f`](https://github.com/gradio-app/gradio/commit/ccf317fc9797675a748b50118aa59a7e4b129d9d) - Add `additional_inputs`, `additional_inputs_accordion` parameters to `gr.Interface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6963](https://github.com/gradio-app/gradio/pull/6963) [`8dfabee`](https://github.com/gradio-app/gradio/commit/8dfabee00495ccbbd6743da07fa06c75cac3fb5f) - fixed typo. Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+
+### Fixes
+
+- [#6969](https://github.com/gradio-app/gradio/pull/6969) [`793bf8f`](https://github.com/gradio-app/gradio/commit/793bf8f7b1943f265c5d016c1a0c682ee549232a) - Display pending file in ` ` while waiting for upload request. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6885](https://github.com/gradio-app/gradio/pull/6885) [`640b7fe`](https://github.com/gradio-app/gradio/commit/640b7fe05276e11720b4341cadf088491395e53d) - Fix issue with Webcam Recording. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6967](https://github.com/gradio-app/gradio/pull/6967) [`5e00162`](https://github.com/gradio-app/gradio/commit/5e0016267f1d683e2daab82ee4a33d2f09513a34) - Make Wasm-compatible. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6983](https://github.com/gradio-app/gradio/pull/6983) [`6e285be`](https://github.com/gradio-app/gradio/commit/6e285be8edeacf8730bac10b7ecd3fd5e309a950) - Fix the reloader. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6958](https://github.com/gradio-app/gradio/pull/6958) [`0f0498b`](https://github.com/gradio-app/gradio/commit/0f0498bf97a036efe47d01b47c4b26000d8d1df3) - Ensure Chatbot theme text size is set correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.13.0
+
+### Features
+
+- [#6133](https://github.com/gradio-app/gradio/pull/6133) [`f742d0e`](https://github.com/gradio-app/gradio/commit/f742d0e861c8e25c5d77d9102c9d50f94b0d3383) - Lite: Support AnnotatedImage on Wasm. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6778](https://github.com/gradio-app/gradio/pull/6778) [`8a093e2`](https://github.com/gradio-app/gradio/commit/8a093e23d7993a044e5e0ff73f93a74cb75dad56) - Add a dev instruction for lite in SharedWorker mode. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6931](https://github.com/gradio-app/gradio/pull/6931) [`6c863af`](https://github.com/gradio-app/gradio/commit/6c863af92fa9ceb5c638857eb22cc5ddb718d549) - Fix functional tests. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6897](https://github.com/gradio-app/gradio/pull/6897) [`fb9c6ca`](https://github.com/gradio-app/gradio/commit/fb9c6cacd7ca4598c000f1f97d7d39a8c4463519) - Lite: Chatbot. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6900](https://github.com/gradio-app/gradio/pull/6900) [`4511d57`](https://github.com/gradio-app/gradio/commit/4511d57c46bf82c48e8e575040ff7dab528b8d51) - Fix the aria-label attrs in `gr.Chatbot()`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6820](https://github.com/gradio-app/gradio/pull/6820) [`649cd4d`](https://github.com/gradio-app/gradio/commit/649cd4d68041d11fcbe31f8efa455345ac49fc74) - Use `EventSource_factory` in `open_stream()` for Wasm. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6916](https://github.com/gradio-app/gradio/pull/6916) [`02c2442`](https://github.com/gradio-app/gradio/commit/02c24422174065b79bfccb258cdfefc6b2b69dc6) - Fix docstring of deprecated parameter concurrency_count. Thanks [@ronensc](https://github.com/ronensc)!
+- [#6884](https://github.com/gradio-app/gradio/pull/6884) [`24a5836`](https://github.com/gradio-app/gradio/commit/24a583688046867ca8b8b02959c441818bdb34a2) - Component Server fix. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6887](https://github.com/gradio-app/gradio/pull/6887) [`8333db8`](https://github.com/gradio-app/gradio/commit/8333db83ac6e2c8511c104534c48137576d0bcd7) - Fix the Wasm worker to initialize the app directories. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#6932](https://github.com/gradio-app/gradio/pull/6932) [`e671e54`](https://github.com/gradio-app/gradio/commit/e671e5415fecae52328e426ee2e9f3c09f410606) - Allow `gr.ClearButton` and `gr.DuplicateButton` to be made hidden (and otherwise updated). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6942](https://github.com/gradio-app/gradio/pull/6942) [`b1b78c2`](https://github.com/gradio-app/gradio/commit/b1b78c2168e24fb65251a9b9b6cbc9382179a8ca) - Fix `.select` for `gr.Image`, `gr.CheckboxGroup`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6899](https://github.com/gradio-app/gradio/pull/6899) [`bd11d6e`](https://github.com/gradio-app/gradio/commit/bd11d6e570755405eac637f1ef71b8d7be09ff67) - Remove the styles on the audio elements in the Chatbot component. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6871](https://github.com/gradio-app/gradio/pull/6871) [`d361a0f`](https://github.com/gradio-app/gradio/commit/d361a0f179752d9e849ec420fc67c8b4060fc154) - Ensure camera settings only update when necessary in Model3D. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6938](https://github.com/gradio-app/gradio/pull/6938) [`459c5dc`](https://github.com/gradio-app/gradio/commit/459c5dc989849b1f0134467d260710fe891045d6) - replacing distutils.StrictVersion dependency for Python 3.12. Thanks [@velaia](https://github.com/velaia)!
+- [#6956](https://github.com/gradio-app/gradio/pull/6956) [`7bab755`](https://github.com/gradio-app/gradio/commit/7bab755f7c4cf38102c87d825066ff49b518222e) - Fixed (this this). Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+- [#6874](https://github.com/gradio-app/gradio/pull/6874) [`31c2316`](https://github.com/gradio-app/gradio/commit/31c23166f0113ab6506575f345c31c952e57e137) - fix issue 6873: File with file_count='directory' bug. Thanks [@joshwilson-dev](https://github.com/joshwilson-dev)!
+- [#6940](https://github.com/gradio-app/gradio/pull/6940) [`c00da89`](https://github.com/gradio-app/gradio/commit/c00da89c3ec6aa9ce43b25f12fde575d681d6870) - Fix returning copies of a component instance from a prediction function. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.12.0
+
+### Features
+
+- [#6839](https://github.com/gradio-app/gradio/pull/6839) [`e974cf0`](https://github.com/gradio-app/gradio/commit/e974cf045c82ce8d79efdda36b9dbf6ea557baa4) - Custom JS Guide. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6854](https://github.com/gradio-app/gradio/pull/6854) [`e528f98`](https://github.com/gradio-app/gradio/commit/e528f98b88f4322f61d315e1770fce0448ca5e26) - chore(deps): update dependency mrmime to v2. Thanks [@renovate](https://github.com/apps/renovate)!
+
+### Fixes
+
+- [#6863](https://github.com/gradio-app/gradio/pull/6863) [`d406855`](https://github.com/gradio-app/gradio/commit/d4068557953746662235d595ec435c42ceb24414) - Fix JS Client when app is running behind a proxy. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6846](https://github.com/gradio-app/gradio/pull/6846) [`48d6534`](https://github.com/gradio-app/gradio/commit/48d6534b40f80e7e70a4061f97d9f2e23ba77fe1) - Add `show_api` parameter to events, and fix `gr.load()`. Also makes some minor improvements to the "view API" page when running on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6865](https://github.com/gradio-app/gradio/pull/6865) [`15c97c6`](https://github.com/gradio-app/gradio/commit/15c97c6d346c475141d20615b5a865e9c44bdc76) - Fix webcam when `streaming=True`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6767](https://github.com/gradio-app/gradio/pull/6767) [`7bb561a`](https://github.com/gradio-app/gradio/commit/7bb561a294ca41d1044927cb34d8645c4175cae0) - Rewriting parts of the README and getting started guides for 4.0. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.11.0
+
+### Features
+
+- [#6842](https://github.com/gradio-app/gradio/pull/6842) [`846d52d`](https://github.com/gradio-app/gradio/commit/846d52d1c92d429077382ce494eea27fd062d9f6) - Fix md highlight. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6831](https://github.com/gradio-app/gradio/pull/6831) [`f3abde8`](https://github.com/gradio-app/gradio/commit/f3abde80884d96ad69b825020c46486d9dd5cac5) - Add an option to enable header links for markdown. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6814](https://github.com/gradio-app/gradio/pull/6814) [`828fb9e`](https://github.com/gradio-app/gradio/commit/828fb9e6ce15b6ea08318675a2361117596a1b5d) - Refactor queue so that there are separate queues for each concurrency id. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6809](https://github.com/gradio-app/gradio/pull/6809) [`1401d99`](https://github.com/gradio-app/gradio/commit/1401d99ade46d87da75b5f5808a3354c49f1d1ea) - Fix `ImageEditor` interaction story. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6803](https://github.com/gradio-app/gradio/pull/6803) [`77c9003`](https://github.com/gradio-app/gradio/commit/77c900311e2ba37b8f849ce088ceb48aa196af18) - Fixes issue 5781: Enables specifying a caching directory for Examples. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6823](https://github.com/gradio-app/gradio/pull/6823) [`67a2b7f`](https://github.com/gradio-app/gradio/commit/67a2b7f12cb06355fcc41e40d47e8b2ad211d7d1) - Fixed duplicate word ("this this"). Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+- [#6833](https://github.com/gradio-app/gradio/pull/6833) [`1b9d423`](https://github.com/gradio-app/gradio/commit/1b9d4234d6c25ef250d882c7b90e1f4039ed2d76) - Prevent file traversals. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6829](https://github.com/gradio-app/gradio/pull/6829) [`50496f9`](https://github.com/gradio-app/gradio/commit/50496f967f8209032b753912a4379eb9cea66627) - Adjust rounding logic when precision is `None` in `gr.Number()`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6766](https://github.com/gradio-app/gradio/pull/6766) [`73268ee`](https://github.com/gradio-app/gradio/commit/73268ee2e39f23ebdd1e927cb49b8d79c4b9a144) - Improve source selection UX. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.10.0
+
+### Features
+
+- [#6798](https://github.com/gradio-app/gradio/pull/6798) [`245d58e`](https://github.com/gradio-app/gradio/commit/245d58eff788e8d44a59d37a2d9b26d0f08a62b4) - Improve how server/js client handle unexpected errors. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6794](https://github.com/gradio-app/gradio/pull/6794) [`7ba8c5d`](https://github.com/gradio-app/gradio/commit/7ba8c5da45b004edd12c0460be9222f5b5f5f055) - Fix SSRF vulnerability on `/file=` route. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6799](https://github.com/gradio-app/gradio/pull/6799) [`c352811`](https://github.com/gradio-app/gradio/commit/c352811f76d4126613ece0a584f8c552fdd8d1f6) - Adds docstrings for `gr.WaveformOptions`, `gr.Brush`, and `gr.Eraser`, fixes examples for `ImageEditor`, and allows individual images to be used as the initial `value` for `ImageEditor`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6808](https://github.com/gradio-app/gradio/pull/6808) [`6b130e2`](https://github.com/gradio-app/gradio/commit/6b130e26b9a6061e7984923b355a04a5484a1c96) - Ensure LoginButton `value` text is displayed. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6810](https://github.com/gradio-app/gradio/pull/6810) [`526fb6c`](https://github.com/gradio-app/gradio/commit/526fb6c446468f1567d614c83266bb5f5797ce9c) - Fix `gr.load()` so that it works with the SSE v1 protocol. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.9.1
+
+### Features
+
+- [#6781](https://github.com/gradio-app/gradio/pull/6781) [`a807ede`](https://github.com/gradio-app/gradio/commit/a807ede818e0690949aca41020e75a96f0110ece) - Fix backend tests on Windows. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6525](https://github.com/gradio-app/gradio/pull/6525) [`5d51fbc`](https://github.com/gradio-app/gradio/commit/5d51fbce7826da840a2fd4940feb5d9ad6f1bc5a) - Fixes Drag and Drop for Upload. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6780](https://github.com/gradio-app/gradio/pull/6780) [`51e241a`](https://github.com/gradio-app/gradio/commit/51e241addd20dad9a0cdf3e72f747cab112815d1) - Fix flaky CI tests (again 😓 ). Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6693](https://github.com/gradio-app/gradio/pull/6693) [`34f9431`](https://github.com/gradio-app/gradio/commit/34f943101bf7dd6b8a8974a6131c1ed7c4a0dac0) - Python client properly handles hearbeat and log messages. Also handles responses longer than 65k. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 4.9.0
+
+### Features
+
+- [#6726](https://github.com/gradio-app/gradio/pull/6726) [`21cfb0a`](https://github.com/gradio-app/gradio/commit/21cfb0acc309bb1a392f4d8a8e42f6be864c5978) - Remove the styles from the Image/Video primitive components and Fix the container styles. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6398](https://github.com/gradio-app/gradio/pull/6398) [`67ddd40`](https://github.com/gradio-app/gradio/commit/67ddd40b4b70d3a37cb1637c33620f8d197dbee0) - Lite v4. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6399](https://github.com/gradio-app/gradio/pull/6399) [`053bec9`](https://github.com/gradio-app/gradio/commit/053bec98be1127e083414024e02cf0bebb0b5142) - Improve CSS token documentation in Storybook. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6745](https://github.com/gradio-app/gradio/pull/6745) [`3240d04`](https://github.com/gradio-app/gradio/commit/3240d042e907a3f2f679c2310c0dc6a688d2c07e) - Add `editable` parameter to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6616](https://github.com/gradio-app/gradio/pull/6616) [`9a0bd27`](https://github.com/gradio-app/gradio/commit/9a0bd27502894e2488b4732be081cb2027aa636e) - Add support for OAuth tokens. Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#6738](https://github.com/gradio-app/gradio/pull/6738) [`f3c4d78`](https://github.com/gradio-app/gradio/commit/f3c4d78b710854b94d9a15db78178e504a02c680) - reload on css changes + fix css specificity. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6671](https://github.com/gradio-app/gradio/pull/6671) [`299f5e2`](https://github.com/gradio-app/gradio/commit/299f5e238bb6fb3f51376ef8b73fc44351859bbe) - Update HF token used in CI tests. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6680](https://github.com/gradio-app/gradio/pull/6680) [`cfd5700`](https://github.com/gradio-app/gradio/commit/cfd57005bce715271c3073ecd322890b8d30f594) - Cause `gr.ClearButton` to reset the value of `gr.State`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6603](https://github.com/gradio-app/gradio/pull/6603) [`6b1401c`](https://github.com/gradio-app/gradio/commit/6b1401c514c2ec012b0a50c72a6ec81cb673bf1d) - chore(deps): update dependency marked to v11. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#6666](https://github.com/gradio-app/gradio/pull/6666) [`30c9fbb`](https://github.com/gradio-app/gradio/commit/30c9fbb5c74f0dc879e85dbdb6778c0782aeff38) - Set gradio api server from env. Thanks [@aisensiy](https://github.com/aisensiy)!
+- [#6677](https://github.com/gradio-app/gradio/pull/6677) [`51b54b3`](https://github.com/gradio-app/gradio/commit/51b54b3411934ce46a27e7d525dd90b43c9fc016) - Tweak to our bug issue template. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6598](https://github.com/gradio-app/gradio/pull/6598) [`7cbf96e`](https://github.com/gradio-app/gradio/commit/7cbf96e0bdd12db7ecac7bf99694df0a912e5864) - Issue 5245: consolidate usage of requests and httpx. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6704](https://github.com/gradio-app/gradio/pull/6704) [`24e0481`](https://github.com/gradio-app/gradio/commit/24e048196e8f7bd309ef5c597d4ffc6ca4ed55d0) - Hotfix: update `huggingface_hub` dependency version. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6432](https://github.com/gradio-app/gradio/pull/6432) [`bdf81fe`](https://github.com/gradio-app/gradio/commit/bdf81fead86e1d5a29e6b036f1fff677f6480e6b) - Lite: Set the home dir path per appId at each runtime. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6569](https://github.com/gradio-app/gradio/pull/6569) [`4d1cbbc`](https://github.com/gradio-app/gradio/commit/4d1cbbcf30833ef1de2d2d2710c7492a379a9a00) - Allow passing height and width as string in `Blocks.svelte`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6416](https://github.com/gradio-app/gradio/pull/6416) [`5177132`](https://github.com/gradio-app/gradio/commit/5177132d718c77f6d47869b4334afae6380394cb) - Lite: Fix the `isMessagePort()` type guard in js/wasm/src/worker-proxy.ts. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6543](https://github.com/gradio-app/gradio/pull/6543) [`8a70e83`](https://github.com/gradio-app/gradio/commit/8a70e83db9c7751b46058cdd2514e6bddeef6210) - switch from black to ruff formatter. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+### Fixes
+
+- [#6709](https://github.com/gradio-app/gradio/pull/6709) [`6a9151d`](https://github.com/gradio-app/gradio/commit/6a9151d5c9432c724098da7d88a539aaaf5ffe88) - Remove progress animation on streaming. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6660](https://github.com/gradio-app/gradio/pull/6660) [`5238053`](https://github.com/gradio-app/gradio/commit/523805360bbf292d9d82443b1f521528beba68bb) - Fix reload mode warning about not being able to find the app. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6672](https://github.com/gradio-app/gradio/pull/6672) [`1234c37`](https://github.com/gradio-app/gradio/commit/1234c3732b52327a00b917af2ef75821771e2c92) - use gr.Error for audio length errors. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6676](https://github.com/gradio-app/gradio/pull/6676) [`fe40308`](https://github.com/gradio-app/gradio/commit/fe40308894efb2c6ff18e5e328163f6641b7476c) - Rotate Images to Upright Position in preprocess. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6487](https://github.com/gradio-app/gradio/pull/6487) [`9a5811d`](https://github.com/gradio-app/gradio/commit/9a5811df9218b622af59ba243a937a9c36ba00f9) - Fix the download button of the `gr.Gallery()` component to work. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6689](https://github.com/gradio-app/gradio/pull/6689) [`c9673ca`](https://github.com/gradio-app/gradio/commit/c9673cacd6470296ee01d7717e2080986e750572) - Fix directory-only glob for FileExplorer. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6639](https://github.com/gradio-app/gradio/pull/6639) [`9a6ff70`](https://github.com/gradio-app/gradio/commit/9a6ff704cd8429289c5376d3af5e4b8492df4773) - Fix issue with `head` param when adding more than one script tag. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6556](https://github.com/gradio-app/gradio/pull/6556) [`d76bcaa`](https://github.com/gradio-app/gradio/commit/d76bcaaaf0734aaf49a680f94ea9d4d22a602e70) - Fix api event drops. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6754](https://github.com/gradio-app/gradio/pull/6754) [`a1b966e`](https://github.com/gradio-app/gradio/commit/a1b966edf761a20ef30e688b1ea1641a5ef1c860) - Fixed an issue where files could not be filed. Thanks [@duolabmeng6](https://github.com/duolabmeng6)!
+- [#6694](https://github.com/gradio-app/gradio/pull/6694) [`dfc61ec`](https://github.com/gradio-app/gradio/commit/dfc61ec4d09da72ddd6e7ab726820529621dbd38) - Fix dropdown blur bug when values are provided as tuples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6691](https://github.com/gradio-app/gradio/pull/6691) [`128ab5d`](https://github.com/gradio-app/gradio/commit/128ab5d65b51390e706a515a1708fe6c88659209) - Ensure checked files persist after FileExplorer rerenders. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6698](https://github.com/gradio-app/gradio/pull/6698) [`798eca5`](https://github.com/gradio-app/gradio/commit/798eca524d44289c536c47eec7c4fdce9fe81905) - Fit video media within Video component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6759](https://github.com/gradio-app/gradio/pull/6759) [`28a7aa9`](https://github.com/gradio-app/gradio/commit/28a7aa917f6a0d57af2c18261d1c01ff76423030) - Mount on a FastAPI app with lifespan manager. Thanks [@Xmaster6y](https://github.com/Xmaster6y)!
+
+## 4.8.0
+
+### Features
+
+- [#6624](https://github.com/gradio-app/gradio/pull/6624) [`1751f14`](https://github.com/gradio-app/gradio/commit/1751f14c1b26c72c0fcc6ba4c69c060c7a199e5d) - Remove 2 slider demos from docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6622](https://github.com/gradio-app/gradio/pull/6622) [`4396f3f`](https://github.com/gradio-app/gradio/commit/4396f3f8f0984d7fcd7e1b88a793af86c7d4e5bb) - Fix encoding issue #6364 of reload mode. Thanks [@curiousRay](https://github.com/curiousRay)!
+- [#5885](https://github.com/gradio-app/gradio/pull/5885) [`9919b8a`](https://github.com/gradio-app/gradio/commit/9919b8ab43bee3d1d7cc65fd641fc8bc9725e102) - Fix the docstring decoration. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6565](https://github.com/gradio-app/gradio/pull/6565) [`9bf1ad4`](https://github.com/gradio-app/gradio/commit/9bf1ad43eac543c9991e59f37e1910f217f8d739) - Fix uploaded file wasn't moved to custom temp dir at different disks. Thanks [@dodysw](https://github.com/dodysw)!
+- [#6584](https://github.com/gradio-app/gradio/pull/6584) [`9bcb1da`](https://github.com/gradio-app/gradio/commit/9bcb1da189a9738d023ef6daad8c6c827e3f6371) - Feat: make UploadButton accept icon. Thanks [@Justin-Xiang](https://github.com/Justin-Xiang)!
+- [#6512](https://github.com/gradio-app/gradio/pull/6512) [`4f040c7`](https://github.com/gradio-app/gradio/commit/4f040c752bb3b0586a4e16eca25a1e5f596eee48) - Update zh-CN.json. Thanks [@cibimo](https://github.com/cibimo)!
+
+### Fixes
+
+- [#6607](https://github.com/gradio-app/gradio/pull/6607) [`13ace03`](https://github.com/gradio-app/gradio/commit/13ace035ed58f14f8f5ce584d94b81c56f83b5d4) - Update file_explorer.py - Fixing error if nothing selected in file_count=single mode (return None rather). Thanks [@v-chabaux](https://github.com/v-chabaux)!
+- [#6574](https://github.com/gradio-app/gradio/pull/6574) [`2b625ad`](https://github.com/gradio-app/gradio/commit/2b625ad9403c3449b34a8a3da68ae48c4347c2db) - Ensure Chatbot messages are properly aligned when `rtl` is true. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6635](https://github.com/gradio-app/gradio/pull/6635) [`b639e04`](https://github.com/gradio-app/gradio/commit/b639e040741e6c0d9104271c81415d7befbd8cf3) - Quick Image + Text Component Fixes. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6572](https://github.com/gradio-app/gradio/pull/6572) [`206af31`](https://github.com/gradio-app/gradio/commit/206af31d7c1a31013364a44e9b40cf8df304ba50) - Improve like/dislike functionality. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6566](https://github.com/gradio-app/gradio/pull/6566) [`d548202`](https://github.com/gradio-app/gradio/commit/d548202d2b5bd8a99e3ebc5bf56820b0282ce0f5) - Improve video trimming and error handling. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6653](https://github.com/gradio-app/gradio/pull/6653) [`d92c819`](https://github.com/gradio-app/gradio/commit/d92c8194191d0e3530d6780a72d6f5c4c545e175) - Add concurrency_limit to ChatInterface, add IDE support for concurrency_limit. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6551](https://github.com/gradio-app/gradio/pull/6551) [`8fc562a`](https://github.com/gradio-app/gradio/commit/8fc562a8abc0932fc312ac33bcc015f6cf2700f6) - Add `show_recording_waveform` to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6550](https://github.com/gradio-app/gradio/pull/6550) [`3156598`](https://github.com/gradio-app/gradio/commit/315659817e5e67a04a1375d35ea6fa58d20622d2) - Make FileExplorer work on python 3.8 and 3.9. Also make it update on changes to root, glob, or glob_dir. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6602](https://github.com/gradio-app/gradio/pull/6602) [`b8034a1`](https://github.com/gradio-app/gradio/commit/b8034a1e72c3aac649ee0ad9178ffdbaaa60fc61) - Fix: Gradio Client work with private Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.7.1
+
+### Features
+
+- [#6537](https://github.com/gradio-app/gradio/pull/6537) [`6d3fecfa4`](https://github.com/gradio-app/gradio/commit/6d3fecfa42dde1c70a60c397434c88db77289be6) - chore(deps): update all non-major dependencies. Thanks [@renovate](https://github.com/apps/renovate)!
+
+### Fixes
+
+- [#6530](https://github.com/gradio-app/gradio/pull/6530) [`13ef0f0ca`](https://github.com/gradio-app/gradio/commit/13ef0f0caa13e5a1cea70d572684122419419599) - Quick fix: Make component interactive when it is in focus. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.6.0
+
+### Features
+
+- [#6532](https://github.com/gradio-app/gradio/pull/6532) [`96290d304`](https://github.com/gradio-app/gradio/commit/96290d304a61064b52c10a54b2feeb09ca007542) - tweak deps. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6511](https://github.com/gradio-app/gradio/pull/6511) [`71f1a1f99`](https://github.com/gradio-app/gradio/commit/71f1a1f9931489d465c2c1302a5c8d768a3cd23a) - Mark `FileData.orig_name` optional on the frontend aligning the type definition on the Python side. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6520](https://github.com/gradio-app/gradio/pull/6520) [`f94db6b73`](https://github.com/gradio-app/gradio/commit/f94db6b7319be902428887867500311a6a32a165) - File table style with accessible file name texts. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6523](https://github.com/gradio-app/gradio/pull/6523) [`63f466882`](https://github.com/gradio-app/gradio/commit/63f466882104453b56a7f52c6bea5b5d497ec698) - Fix typo in base.py. Thanks [@eltociear](https://github.com/eltociear)!
+- [#6296](https://github.com/gradio-app/gradio/pull/6296) [`46f13f496`](https://github.com/gradio-app/gradio/commit/46f13f4968c8177e318c9d75f2eed1ed55c2c042) - chore(deps): update all non-major dependencies. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#6517](https://github.com/gradio-app/gradio/pull/6517) [`901f3eebd`](https://github.com/gradio-app/gradio/commit/901f3eebda0a67fa8f3050d80f7f7b5800c7f566) - Allow reselecting the original option in `gr.Dropdown` after value has changed programmatically. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6538](https://github.com/gradio-app/gradio/pull/6538) [`147926196`](https://github.com/gradio-app/gradio/commit/147926196a074d3fe62e59b5a80997e133c0f707) - Some tweaks to `ImageEditor`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6518](https://github.com/gradio-app/gradio/pull/6518) [`d4e3a5189`](https://github.com/gradio-app/gradio/commit/d4e3a518905620c184a0315ff3bdfbf5e7945bd6) - Allows setting parameters of `gr.ChatInterface`'s `Accordion`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6528](https://github.com/gradio-app/gradio/pull/6528) [`f53b01cbf`](https://github.com/gradio-app/gradio/commit/f53b01cbfbfccec66e0cda1d428ef72f05a3dfc0) - Fix Theme Dropdown in deployed theme space. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6546](https://github.com/gradio-app/gradio/pull/6546) [`a424fdbb2`](https://github.com/gradio-app/gradio/commit/a424fdbb2389219661b9a73197f4cc095a08cfe9) - Ensure audio waveform `autoplay` updates. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6536](https://github.com/gradio-app/gradio/pull/6536) [`1bbd6cab3`](https://github.com/gradio-app/gradio/commit/1bbd6cab3f0abe183b514b82061f0937c8480966) - Fix undefined `data` TypeError in Blocks. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6500](https://github.com/gradio-app/gradio/pull/6500) [`830b6c0e6`](https://github.com/gradio-app/gradio/commit/830b6c0e6e52c4fa33fddfa4d3f6162e29801f74) - Process and convert .svg files in `Image`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.5.0
+
+### Highlights
+
+#### New `ImageEditor` component ([#6169](https://github.com/gradio-app/gradio/pull/6169) [`9caddc17b`](https://github.com/gradio-app/gradio/commit/9caddc17b1dea8da1af8ba724c6a5eab04ce0ed8))
+
+A brand new component, completely separate from `Image` that provides simple editing capabilities.
+
+- Set background images from file uploads, webcam, or just paste!
+- Crop images with an improved cropping UI. App authors can event set specific crop size, or crop ratios (`1:1`, etc)
+- Paint on top of any image (or no image) and erase any mistakes!
+- The ImageEditor supports layers, confining draw and erase actions to that layer.
+- More flexible access to data. The image component returns a composite image representing the final state of the canvas as well as providing the background and all layers as individual images.
+- Fully customisable. All features can be enabled and disabled. Even the brush color swatches can be customised.
+
+
+
+```py
+
+def fn(im):
+ im["composite"] # the full canvas
+ im["background"] # the background image
+ im["layers"] # a list of individual layers
+
+
+im = gr.ImageEditor(
+ # decide which sources you'd like to accept
+ sources=["upload", "webcam", "clipboard"],
+ # set a cropsize constraint, can either be a ratio or a concrete [width, height]
+ crop_size="1:1",
+ # enable crop (or disable it)
+ transforms=["crop"],
+ # customise the brush
+ brush=Brush(
+ default_size="25", # or leave it as 'auto'
+ color_mode="fixed", # 'fixed' hides the user swatches and colorpicker, 'defaults' shows it
+ default_color="hotpink", # html names are supported
+ colors=[
+ "rgba(0, 150, 150, 1)", # rgb(a)
+ "#fff", # hex rgb
+ "hsl(360, 120, 120)" # in fact any valid colorstring
+ ]
+ ),
+ brush=Eraser(default_size="25")
+)
+
+```
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+### Fixes
+
+- [#6497](https://github.com/gradio-app/gradio/pull/6497) [`1baed201b`](https://github.com/gradio-app/gradio/commit/1baed201b12ecb5791146aed9a86b576c3595130) - Fix SourceFileReloader to watch the module with a qualified name to avoid importing a module with the same name from a different path. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6502](https://github.com/gradio-app/gradio/pull/6502) [`070f71c93`](https://github.com/gradio-app/gradio/commit/070f71c933d846ce8e2fe11cdd9bc0f3f897f29f) - Ensure image editor crop and draw cursor works as expected when the scroll position changes. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.4.1
+
+### Features
+
+- [#6467](https://github.com/gradio-app/gradio/pull/6467) [`739e3a5a0`](https://github.com/gradio-app/gradio/commit/739e3a5a09771a4a386cab0c6605156cf9fda7f6) - Fix dev mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 4.4.0
+
+### Features
+
+- [#6428](https://github.com/gradio-app/gradio/pull/6428) [`ac4ca59c9`](https://github.com/gradio-app/gradio/commit/ac4ca59c929bbe0bdf92155766883797d4e01ea0) - Extract video filenames correctly from URLs. Thanks [@112292454](https://github.com/112292454)!
+- [#6461](https://github.com/gradio-app/gradio/pull/6461) [`6b53330a5`](https://github.com/gradio-app/gradio/commit/6b53330a5be53579d9128aea4858713082ce302d) - UploadButton tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6439](https://github.com/gradio-app/gradio/pull/6439) [`a1e3c61f4`](https://github.com/gradio-app/gradio/commit/a1e3c61f41b16166656b46254a201b37abcf20a8) - Allow setting a `default_concurrency_limit` other than 1. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6455](https://github.com/gradio-app/gradio/pull/6455) [`179f5bcde`](https://github.com/gradio-app/gradio/commit/179f5bcde16539bb9e828685d95dcd2167d3a215) - Add py.typed to gradio backend. Thanks [@aleneum](https://github.com/aleneum)!
+- [#6436](https://github.com/gradio-app/gradio/pull/6436) [`58e3ca826`](https://github.com/gradio-app/gradio/commit/58e3ca8260a6635e10e7a7f141221c4f746e9386) - Custom Component CLI Improvements. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6462](https://github.com/gradio-app/gradio/pull/6462) [`2761b6d19`](https://github.com/gradio-app/gradio/commit/2761b6d197acc1c6a2fd9534e7633b463bd3f1e0) - Catch ValueError, KeyError when saving PIL Image. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6423](https://github.com/gradio-app/gradio/pull/6423) [`62d35c3d1`](https://github.com/gradio-app/gradio/commit/62d35c3d1b3e9d6e39bddbb32ff6b6cf9f1f7f72) - Issue 2085: Transformers object detection pipeline added. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6456](https://github.com/gradio-app/gradio/pull/6456) [`3953a1467`](https://github.com/gradio-app/gradio/commit/3953a146750b09161b50d972590cae8bf980990c) - Preserve original image extension in backend processing. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6427](https://github.com/gradio-app/gradio/pull/6427) [`e0fc14659`](https://github.com/gradio-app/gradio/commit/e0fc146598ba9b081bc5fa9616d0a41c2aba2427) - Allow google analytics to work on Spaces (and other iframe situations). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6419](https://github.com/gradio-app/gradio/pull/6419) [`1959471a8`](https://github.com/gradio-app/gradio/commit/1959471a8d939275c7b9184913a5a6f92e567604) - Add download tests for audio/video. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6424](https://github.com/gradio-app/gradio/pull/6424) [`2727f45fb`](https://github.com/gradio-app/gradio/commit/2727f45fb0c9c3116a7e1a3f88cb3a401c4c7e93) - Do not show warnings when renaming api_names. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6437](https://github.com/gradio-app/gradio/pull/6437) [`727ae2597`](https://github.com/gradio-app/gradio/commit/727ae2597603f026d74d5acafac8709326300836) - chore: rename api_key to hf_token. Thanks [@NickCrews](https://github.com/NickCrews)!
+
+### Fixes
+
+- [#6441](https://github.com/gradio-app/gradio/pull/6441) [`2f805a7dd`](https://github.com/gradio-app/gradio/commit/2f805a7dd3d2b64b098f659dadd5d01258290521) - Small but important bugfixes for gr.Image: The upload event was not triggering at all. The paste-from-clipboard was not triggering an upload event. The clear button was not triggering a change event. The change event was triggering infinitely. Uploaded images were not preserving their original names. Uploading a new image should clear out the previous image. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6454](https://github.com/gradio-app/gradio/pull/6454) [`2777f326e`](https://github.com/gradio-app/gradio/commit/2777f326e595541fbec8ce14f56340b9e740f1da) - Ensure Audio ouput events are dispatched. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6254](https://github.com/gradio-app/gradio/pull/6254) [`f816136a0`](https://github.com/gradio-app/gradio/commit/f816136a039fa6011be9c4fb14f573e4050a681a) - Add volume control to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6457](https://github.com/gradio-app/gradio/pull/6457) [`d00fcf89d`](https://github.com/gradio-app/gradio/commit/d00fcf89d1c3ecbc910e81bb1311479ec2b73e4e) - Gradio custom component dev mode now detects changes to Example.svelte file. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6418](https://github.com/gradio-app/gradio/pull/6418) [`bce6ca109`](https://github.com/gradio-app/gradio/commit/bce6ca109feadd6ba94a69843689cefc381dd054) - Send more than one heartbeat message. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6425](https://github.com/gradio-app/gradio/pull/6425) [`b3ba17dd1`](https://github.com/gradio-app/gradio/commit/b3ba17dd1167d254756d93f1fb01e8be071819b6) - Update the selected indices in `Dropdown` when value changes programmatically. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.3.0
+
+### Features
+
+- [#6395](https://github.com/gradio-app/gradio/pull/6395) [`8ef48f852`](https://github.com/gradio-app/gradio/commit/8ef48f85241a0f06f4bcdaa0a2010917b3a536be) - Async functions and async generator functions with the `every` option to work. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6403](https://github.com/gradio-app/gradio/pull/6403) [`9cfeb4f17`](https://github.com/gradio-app/gradio/commit/9cfeb4f17e76efad7772e0cbe53dfb3e8310f565) - Remove websockets dependency. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6406](https://github.com/gradio-app/gradio/pull/6406) [`0401c77f3`](https://github.com/gradio-app/gradio/commit/0401c77f3d35763b79e040dbe876e69083defd36) - Move ffmpeg to `Video` deps. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6099](https://github.com/gradio-app/gradio/pull/6099) [`d84209703`](https://github.com/gradio-app/gradio/commit/d84209703b7a0728cdb49221e543500ddb6a8d33) - Lite: SharedWorker mode. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#6412](https://github.com/gradio-app/gradio/pull/6412) [`649f3ceb6`](https://github.com/gradio-app/gradio/commit/649f3ceb6c784c82fa88bdb7f04535f6419b14dd) - Added docs on gr.Examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6378](https://github.com/gradio-app/gradio/pull/6378) [`d31d8c6ad`](https://github.com/gradio-app/gradio/commit/d31d8c6ad888aa4f094820d07288e9d0e2778521) - Allows `sources` to be a string for `gr.Image`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6382](https://github.com/gradio-app/gradio/pull/6382) [`2090aad73`](https://github.com/gradio-app/gradio/commit/2090aad731b186ef0a3f63ec2b4d1a6e3acb1754) - Move wavesurfer dep to js/audio. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6383](https://github.com/gradio-app/gradio/pull/6383) [`324867f63`](https://github.com/gradio-app/gradio/commit/324867f63c920113d89a565892aa596cf8b1e486) - Fix event target. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6405](https://github.com/gradio-app/gradio/pull/6405) [`03491ef49`](https://github.com/gradio-app/gradio/commit/03491ef49708753fc51566c3dc17df09ae98fb98) - Fix docstrings and default value for `api_name`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6386](https://github.com/gradio-app/gradio/pull/6386) [`e76a9e8fc`](https://github.com/gradio-app/gradio/commit/e76a9e8fcbbfc393298de2aa539f2b152c0d6400) - Fix Chatbot Pending Message Issues. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6414](https://github.com/gradio-app/gradio/pull/6414) [`da1e31832`](https://github.com/gradio-app/gradio/commit/da1e31832f85ec76540e474ae35badfde8a18b6f) - Fix Model3D download button and other issues. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6379](https://github.com/gradio-app/gradio/pull/6379) [`de998b281`](https://github.com/gradio-app/gradio/commit/de998b28127ecef10c403890ff08674f527a3708) - Processes `avatar_images` for `gr.Chatbot` and `icon` for `gr.Button` correctly, so that respective files are moved to cache. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.2.0
+
+### Features
+
+- [#6333](https://github.com/gradio-app/gradio/pull/6333) [`42f76aeeb`](https://github.com/gradio-app/gradio/commit/42f76aeeb7b7263abccc038b699fb7fae7fe2313) - Add AsyncGenerator to the check-list of `dependencies.types.generator`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6347](https://github.com/gradio-app/gradio/pull/6347) [`d64787b88`](https://github.com/gradio-app/gradio/commit/d64787b885a26ecb6771bfdd20aac33c8a90afe6) - Fix `colorFrom` in theme space readmes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6363](https://github.com/gradio-app/gradio/pull/6363) [`4d3aad33a`](https://github.com/gradio-app/gradio/commit/4d3aad33a0b66639dbbb2928f305a79fb7789b2d) - Fix image upload. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6356](https://github.com/gradio-app/gradio/pull/6356) [`854b482f5`](https://github.com/gradio-app/gradio/commit/854b482f598e0dc47673846631643c079576da9c) - Redesign file upload. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6343](https://github.com/gradio-app/gradio/pull/6343) [`37dd335e5`](https://github.com/gradio-app/gradio/commit/37dd335e5f04a8e689dd7f23ae24ad1934ea08d8) - Fix audio streaming output issues in 4.0. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6307](https://github.com/gradio-app/gradio/pull/6307) [`f1409f95e`](https://github.com/gradio-app/gradio/commit/f1409f95ed39c5565bed6a601e41f94e30196a57) - Provide status updates on file uploads. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#6368](https://github.com/gradio-app/gradio/pull/6368) [`8a3f45c26`](https://github.com/gradio-app/gradio/commit/8a3f45c2612a36112d797465e14cd6f1801ccbd9) - Fix component update bug. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6322](https://github.com/gradio-app/gradio/pull/6322) [`6204ccac5`](https://github.com/gradio-app/gradio/commit/6204ccac5967763e0ebde550d04d12584243a120) - Fixes `gr.load()` so it works properly with Images and Examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6323](https://github.com/gradio-app/gradio/pull/6323) [`55fda81fa`](https://github.com/gradio-app/gradio/commit/55fda81fa5918b48952729232d6e2fc55af9351d) - Textbox and Code Component Blur/Focus Fixes. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.1.2
+
+### Features
+
+- [#6318](https://github.com/gradio-app/gradio/pull/6318) [`d3b53a457`](https://github.com/gradio-app/gradio/commit/d3b53a4577ea05cd27e37ce7fec952028c18ed45) - Fix for stylized DataFrame. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6326](https://github.com/gradio-app/gradio/pull/6326) [`ed546f2e1`](https://github.com/gradio-app/gradio/commit/ed546f2e13915849b0306d017c40933b856bb792) - Fix Model3D template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#6310](https://github.com/gradio-app/gradio/pull/6310) [`dfdaf1092`](https://github.com/gradio-app/gradio/commit/dfdaf109263b7b88c125558028ee9609f817fd10) - Fix data model for `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6316](https://github.com/gradio-app/gradio/pull/6316) [`4b1011bab`](https://github.com/gradio-app/gradio/commit/4b1011bab03c0b6a09329e0beb9c1b17b2189878) - Maintain text selection in `Chatbot` button elements. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6327](https://github.com/gradio-app/gradio/pull/6327) [`bca6c2c80`](https://github.com/gradio-app/gradio/commit/bca6c2c80f7e5062427019de45c282238388af95) - Restore query parameters in request. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6317](https://github.com/gradio-app/gradio/pull/6317) [`19af2806a`](https://github.com/gradio-app/gradio/commit/19af2806a58419cc551d2d1d6d8987df0db91ccb) - Add autoplay to `waveform_settings`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6294](https://github.com/gradio-app/gradio/pull/6294) [`7ab73df48`](https://github.com/gradio-app/gradio/commit/7ab73df48ea9dc876c1eaedfb424fcead6326dc9) - fix regarding callable function error. Thanks [@SrijanSahaySrivastava](https://github.com/SrijanSahaySrivastava)!
+- [#6279](https://github.com/gradio-app/gradio/pull/6279) [`3cdeabc68`](https://github.com/gradio-app/gradio/commit/3cdeabc6843000310e1a9e1d17190ecbf3bbc780) - Ensure source selection does not get hidden in overflow. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6311](https://github.com/gradio-app/gradio/pull/6311) [`176c4d140`](https://github.com/gradio-app/gradio/commit/176c4d140000b1be698b6caf0d0efd26a5c7897d) - Temporary fix to be able to load themes from Hub. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6314](https://github.com/gradio-app/gradio/pull/6314) [`fad92c29d`](https://github.com/gradio-app/gradio/commit/fad92c29dc1f5cd84341aae417c495b33e01245f) - Improve default source behaviour in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6320](https://github.com/gradio-app/gradio/pull/6320) [`570866a3b`](https://github.com/gradio-app/gradio/commit/570866a3bd95a45a197afec38b982bbc6c7cd0a0) - Hide show API link when in gradio lite. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6309](https://github.com/gradio-app/gradio/pull/6309) [`c56128781`](https://github.com/gradio-app/gradio/commit/c561287812797aa1b6b464b0e76419350570ba83) - Fix updating choices in `gr.Dropdown` and updates related to other components. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.1.1
+
+### Fixes
+
+- [#6288](https://github.com/gradio-app/gradio/pull/6288) [`92278729e`](https://github.com/gradio-app/gradio/commit/92278729ee008126af15ffe6be399236211b2f34) - Gallery preview fix and optionally skip download of urls in postprcess. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6289](https://github.com/gradio-app/gradio/pull/6289) [`5668036ee`](https://github.com/gradio-app/gradio/commit/5668036eef89051c1dbc5a74dc20988a3012ccbd) - Fix file upload on windows. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6290](https://github.com/gradio-app/gradio/pull/6290) [`e8216be94`](https://github.com/gradio-app/gradio/commit/e8216be948f76ce064595183d11e9148badf9421) - ensure `gr.Dataframe` updates as expected. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.1.0
+
+### Features
+
+- [#6261](https://github.com/gradio-app/gradio/pull/6261) [`8bbeca0e7`](https://github.com/gradio-app/gradio/commit/8bbeca0e772a5a2853d02a058b35abb2c15ffaf1) - Improve Embed and CDN handling and fix a couple of related bugs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6241](https://github.com/gradio-app/gradio/pull/6241) [`61c155e9b`](https://github.com/gradio-app/gradio/commit/61c155e9ba0f8f7ebd5a2a71687597dafb842219) - Remove session if browser closed on mobile. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6227](https://github.com/gradio-app/gradio/pull/6227) [`4840b4bc2`](https://github.com/gradio-app/gradio/commit/4840b4bc297703d317cad9c0f566e857a20b9375) - Add that api routes are automatically named to CHANGELOG. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6240](https://github.com/gradio-app/gradio/pull/6240) [`dd901c1b0`](https://github.com/gradio-app/gradio/commit/dd901c1b0af73a78fca8b6875b2bb00f84071ac8) - Model3D panning, improved UX. Thanks [@dylanebert](https://github.com/dylanebert)!
+- [#6272](https://github.com/gradio-app/gradio/pull/6272) [`12d8e90a1`](https://github.com/gradio-app/gradio/commit/12d8e90a1646374b46eb8258be7356c868d1cca3) - Fixes input `Image` component with `streaming=True`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6268](https://github.com/gradio-app/gradio/pull/6268) [`de36820ef`](https://github.com/gradio-app/gradio/commit/de36820ef51097b47937b41fb76e4038aaa369cb) - Fix various issues with demos on website. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6232](https://github.com/gradio-app/gradio/pull/6232) [`ac4f2bcde`](https://github.com/gradio-app/gradio/commit/ac4f2bcded61672bfe1d54c279d527de2eabdb7a) - Remove **kwargs from queue. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6255](https://github.com/gradio-app/gradio/pull/6255) [`e3ede2ff7`](https://github.com/gradio-app/gradio/commit/e3ede2ff7d4a36fb21bb0b146b8d5ad239c0e086) - Ensure Model 3D updates when attributes change. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#6266](https://github.com/gradio-app/gradio/pull/6266) [`e32bac894`](https://github.com/gradio-app/gradio/commit/e32bac8944c85e0ec4831963299889d6bbfa0351) - Fix updating interactive prop. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6213](https://github.com/gradio-app/gradio/pull/6213) [`27194a987`](https://github.com/gradio-app/gradio/commit/27194a987fa7ba1234b5fc0ce8bf7fabef7033a9) - Ensure the statustracker for `gr.Image` displays in static mode. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6234](https://github.com/gradio-app/gradio/pull/6234) [`aaa55ce85`](https://github.com/gradio-app/gradio/commit/aaa55ce85e12f95aba9299445e9c5e59824da18e) - Video/Audio fixes. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6236](https://github.com/gradio-app/gradio/pull/6236) [`6bce259c5`](https://github.com/gradio-app/gradio/commit/6bce259c5db7b21b327c2067e74ea20417bc89ec) - Ensure `gr.CheckboxGroup` updates as expected. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6262](https://github.com/gradio-app/gradio/pull/6262) [`afb72bd19`](https://github.com/gradio-app/gradio/commit/afb72bd1970e6c43ddba0638fe9861330bdabb64) - Fix bug where radio.select passes the previous value to the function instead of the selected value. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6231](https://github.com/gradio-app/gradio/pull/6231) [`3e31c1752`](https://github.com/gradio-app/gradio/commit/3e31c1752e0e5bf90339b816f9895529d9368bbd) - Add likeable to config for Chatbot. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6249](https://github.com/gradio-app/gradio/pull/6249) [`2cffcf3c3`](https://github.com/gradio-app/gradio/commit/2cffcf3c39acd782f314f8a406100ae22e0809b7) - ensure radios have different names. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6229](https://github.com/gradio-app/gradio/pull/6229) [`5cddd6588`](https://github.com/gradio-app/gradio/commit/5cddd658809d147fafef5e9502ccfab5bd105aa6) - Fixes: Initial message is overwrtitten in chat interface. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6277](https://github.com/gradio-app/gradio/pull/6277) [`5fe091367`](https://github.com/gradio-app/gradio/commit/5fe091367fbe0eecdd504aa734ca1c70b0621f52) - handle selected_index prop change for gallery. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6211](https://github.com/gradio-app/gradio/pull/6211) [`a4a931dd3`](https://github.com/gradio-app/gradio/commit/a4a931dd39a48bceac50486558b049ca7b874195) - fix`FileExplorer` preprocess. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5876](https://github.com/gradio-app/gradio/pull/5876) [`d7a1a6559`](https://github.com/gradio-app/gradio/commit/d7a1a6559005e6a1e0be03a3bd5212d1bc60d1ee) - Fix file overflow and add keyboard navigation to `FileExplorer`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.0.2
+
+### Fixes
+
+- [#6191](https://github.com/gradio-app/gradio/pull/6191) [`b555bc09f`](https://github.com/gradio-app/gradio/commit/b555bc09ffe8e58b10da6227e2f11a0c084aa71d) - fix cdn build. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.0.1
+
+### Features
+
+- [#6137](https://github.com/gradio-app/gradio/pull/6137) [`2ba14b284`](https://github.com/gradio-app/gradio/commit/2ba14b284f908aa13859f4337167a157075a68eb) - JS Param. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6181](https://github.com/gradio-app/gradio/pull/6181) [`62ec2075c`](https://github.com/gradio-app/gradio/commit/62ec2075ccad8025a7721a08d0f29eb5a4f87fad) - modify preprocess to use pydantic models. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.0.0
+
+### Highlights
+
+4.0 is a big release, so here are the main highlights:
+
+**1. Custom Components**:
+We've introduced the ability to create and publish you own custom `gradio` components. A custom Gradio component is a combination of Python and JavaScript (specifically, Svelte) that you can write to fully customize a Gradio component. A custom component can be used just like a regular Gradio component (with `gr.Interface`, `gr.Blocks`, etc.) and can be published so that other users can use it within their apps. To get started with Custom Components, [read our quickstart guide here](https://www.gradio.app/guides/five-minute-guide).
+
+
+
+**2. Redesigned Media Components and Accessibility**:
+
+We redesigned our media components (`gr.Audio`, `gr.Image`, and `gr.Video`) from scratch and improved accessibilty across the board. All components are now keyboard navigable and include better colors to be usable by a wider audience.
+
+
+
+**3. Server Side Events**:
+
+Gradio's built-in queuing system is now the default for every Gradio app. We now use Server Side Events instead of Websockets for the queue. SSE means everything is served over HTTP and has better device support and better scaling than websockets.
+
+
+
+**4. Custom Share Servers**:
+
+Gradio share links can now run on custom domains. You can now set up your own server to serve Gradio share links. To get started, [read our guide here](https://github.com/huggingface/frp/).
+
+
+
+5. We now support adding arbitrary JS to your apps using the `js` parameter in Blocks, and arbitrary modifications to the of your app using the `head` parameter in Blocks
+
+6. We no longer expose a user's working directory by default when you release a Gradio app. There are some other improvements around security as well.
+
+7. Previously, a Gradio app's API endpoints were exposed, allowing you to bypass the queue. As a Gradio developer, you needed to set `api_open=False` to prevent this misuse. We've now made this the default.
+
+8. You can now control whether a user should be able to trigger the same event multiple times (by using the `trigger_mode` parameter of each event)
+
+9. You now have fine-grained control over how many times each event can be running concurrently in the backend (using the `concurrency_limit` parameter of each event)
+
+10. We no longer serialize images into base64 before sending them to the server or on the way back. This should make any Gradio app that includes `gr.Image` components much faster.
+
+
+### Breaking Changes
+
+Gradio 4.0 is a new major version, and includes breaking changes from 3.x. Here's a list of all the breaking changes, along with migration steps where appropriate.
+
+**Components**:
+
+* Removes `**kwarg` from every component, meaning that components cannot accept arbitrary (unused) parameters. Previously, warnings would be thrown.
+* Removes deprecated parameters. For example, `plain` is no longer an alias for `secondary` for the `variant` argument in the `gr.Button` class
+* Removes the deprecated `Carousel` class and `StatusTracker` class and `Box` layout class
+* Removes the deprecated `Variable` alias for `State`
+* Removes the deprecated `.style()` methods from component classes
+* Removes the deprecated `.update()` method from component classes
+* Removes `get_interpretation_neighbors()` and `get_interpretation_scores()` from component classes
+* Removes `deprecation.py` -- this was designed for internal usage so unlikely to break gradio apps
+* Moves save to cache methods from component methods to standalone functions in processing_utils
+* Renames `source` param in `gr.Audio` and `gr.Video` to `sources`
+* Removes `show_edit_button` param from `gr.Audio`
+* The `tool=` argument in `gr.Image()` has been removed. As of `gradio==4.5.0`, we have a new `gr.ImageEditor` component that takes its place. The `ImageEditor` component is a streamlined component that allows you to do basic manipulation of images. It supports setting a background image (which can be uploaded, pasted, or recorded through a webcam), as well the ability to "edit" the background image by using a brush to create strokes and an eraser to erase strokes in layers on top of the background image. See the **Migrating to Gradio 4.0** section below.
+
+**Other changes related to the `gradio` library**:
+
+* Removes the deprecated `status_tracker` parameter from events
+* Removes the deprecated `HuggingFaceDatasetJSONSaver` class
+* Now `Blocks.load()` can only be use an is instance method to attach an event that runs when the page loads. To use the class method, use `gr.load()` instead
+* Similarly, `Interface.load()` has been removed
+* If you are runnin Gradio 4.x, you can not `gr.load` a Space that is running Gradio 3.x. However, you can still use the client libraries (see changes to the client libraries below).
+* Removes deprecated parameters, such as `enable_queue` from `launch()`
+* Many of the positional arguments in launch() are now keyword only, and show_tips has been removed
+* Changes the format of flagged data to json instead of filepath for media and chatbot
+* Removes `gr.Series` and `gr.Parallel`
+* All API endpoints are named by deafult. If `api_name=None`, the api name is the name of the python function.
+
+
+**Changes related to the Client libraries**:
+
+* When using the gradio Client libraries in 3.x with any component that returned JSON data (including `gr.Chatbot`, `gr.Label`, and `gr.JSON`), the data would get saved to a file and the filepath would be returned. Similarly, you would have to pass input JSON as a filepath. Now, the JSON data is passed and returned directly, making it easier to work with these components using the clients.
+
+### Migrating to Gradio 4.0
+
+Here are some concrete tips to help migrate to Gradio 4.0:
+
+#### **Using `allowed_paths`**
+
+Since the working directory is now not served by default, if you reference local files within your CSS or in a `gr.HTML` component using the `/file=` route, you will need to explicitly allow access to those files (or their parent directories) using the `allowed_paths` parameter in `launch()`
+
+For example, if your code looks like this:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML(" ")
+
+demo.launch()
+```
+
+In order for the HTML component to be able to serve `image.png`, you will need to add `image.png` in `allowed_paths` like this:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML(" ")
+
+demo.launch(allowed_paths=["image.png"])
+```
+
+or if you want to expose all files in your working directory as was the case in Gradio 3.x (not recommended if you plan to share your app with others), you could do:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML(" ")
+
+demo.launch(allowed_paths=["."])
+```
+
+
+#### **Using `concurrency_limit` instead of `concurrency_count`**
+
+Previously, in Gradio 3.x, there was a single global `concurrency_count` parameter that controlled how many threads could execute tasks from the queue simultaneously. By default `concurrency_count` was 1, which meant that only a single event could be executed at a time (to avoid OOM errors when working with prediction functions that utilized a large amount of memory or GPU usage). You could bypass the queue by setting `queue=False`.
+
+In Gradio 4.0, the `concurrency_count` parameter has been removed. You can still control the number of total threads by using the `max_threads` parameter. The default value of this parameter is `40`, but you don't have worry (as much) about OOM errors, because even though there are 40 threads, we use a single-worker-single-event model, which means each worker thread only executes a specific function. So effectively, each function has its own "concurrency count" of 1. If you'd like to change this behavior, you can do so by setting a parameter `concurrency_limit`, which is now a parameter of *each event*, not a global parameter. By default this is `1` for each event, but you can set it to a higher value, or to `None` if you'd like to allow an arbitrary number of executions of this event simultaneously. Events can also be grouped together using the `concurrency_id` parameter so that they share the same limit, and by default, events that call the same function share the same `concurrency_id`.
+
+Lastly, it should be noted that the default value of the `concurrency_limit` of all events in a Blocks (which is normally 1) can be changed using the `default_concurrency_limit` parameter in `Blocks.queue()`. You can set this to a higher integer or to `None`. This in turn sets the `concurrency_limit` of all events that don't have an explicit `conurrency_limit` specified.
+
+To summarize migration:
+
+* For events that execute quickly or don't use much CPU or GPU resources, you should set `concurrency_limit=None` in Gradio 4.0. (Previously you would set `queue=False`.)
+* For events that take significant resources (like the prediction function of your machine learning model), and you only want 1 execution of this function at a time, you don't have to set any parameters.
+* For events that take significant resources (like the prediction function of your machine learning model), and you only want `X` executions of this function at a time, you should set `concurrency_limit=X` parameter in the event trigger.(Previously you would set a global `concurrency_count=X`.)
+
+
+**The new `ImageEditor` component**
+
+In Gradio 4.0, the `tool=` argument in `gr.Image()` was removed. It has been replaced, as of Gradio 4.5.0, with a new `gr.ImageEditor()` component. The `ImageEditor` component is a streamlined component that allows you to do basic manipulation of images. It supports setting a background image (which can be uploaded, pasted, or recorded through a webcam), as well the ability to "edit" the background by using a brush to create strokes and an eraser to erase strokes in layers on top of the background image.
+
+The `ImageEditor` component is much more performant and also offers much more flexibility to customize the component, particularly through the new `brush` and `eraser` arguments, which take `Brush` and `Eraser` objects respectively.
+
+Here are some examples of how you might migrate from `Image(tool=...)` to `gr.ImageEditor()`.
+
+* To create a sketchpad input that supports writing black strokes on a white background, you might have previously written:
+
+```py
+gr.Image(source="canvas", tools="sketch")
+```
+
+Now, you should write:
+
+```py
+gr.ImageEditor(sources=(), brush=gr.Brush(colors=["#000000"]))
+```
+
+Note: you can supply a list of supported stroke colors in `gr.Brush`, as well as control whether users can choose their own colors by setting the `color_mode` parameter of `gr.Brush` to be either `"fixed"` or `"defaults"`.
+
+* If you want to create a sketchpad where users can draw in any color, simply omit the `brush` parameter. In other words, where previously, you would do:
+
+```py
+gr.Image(source="canvas", tools="color-sketch")
+```
+
+Now, you should write:
+
+```py
+gr.ImageEditor(sources=())
+```
+
+
+* If you want to allow users to choose a background image and then draw on the image, previously, you would do:
+
+```py
+gr.Image(source="upload", tools="color-sketch")
+```
+
+Now, this is the default behavior of the `ImageEditor` component, so you should just write:
+
+```py
+gr.ImageEditor()
+```
+
+Unlike the `Image` component, which passes the input image as a single value into the prediction function, the `ImageEditor` passes a dictionary consisting of three key-value pairs:
+
+* the key `"background"`, whose value is the background image
+* the key `"layers"`, which consists of a list of values, with the strokes in each layer corresponding to one list element.
+* the key `"composite"`, whose value is to the complete image consisting of background image and all of the strokes.
+
+The type of each value can be set by the `type` parameter (`"filepath"`, `"pil"`, or `"numpy"`, with the default being `"numpy"`), just like in the `Image` component.
+
+Please see the documentation of the `gr.ImageEditor` component for more details: https://www.gradio.app/docs/imageeditor
+
+### Features
+
+- [#6184](https://github.com/gradio-app/gradio/pull/6184) [`86edc0199`](https://github.com/gradio-app/gradio/commit/86edc01995d9f888bac093c44c3d4535fe6483b3) - Remove gr.mix. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6177](https://github.com/gradio-app/gradio/pull/6177) [`59f5a4e30`](https://github.com/gradio-app/gradio/commit/59f5a4e30ed9da1c6d6f6ab0886285150b3e89ec) - Part I: Remove serializes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Don't serve files in working directory by default. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Small change to make `api_open=False` by default. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Add json schema unit tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Remove duplicate `elem_ids` from components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6182](https://github.com/gradio-app/gradio/pull/6182) [`911829ac2`](https://github.com/gradio-app/gradio/commit/911829ac278080fc81155d4b75502692e72fd3de) - Allow data at queue join. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Moves `gradio_cached_folder` inside the gradio temp direcotry. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Fix constructor_args. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Remove interpretation for good. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Improve Audio Component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - pass props to example components and to example outputs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Clean root url. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Adds the ability to build the frontend and backend of custom components in preparation for publishing to pypi using `gradio_component build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Fix selectable prop in the backend. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Set api=False for cancel events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Improve Video Component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Try to trigger a major beta release. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6172](https://github.com/gradio-app/gradio/pull/6172) [`79c8156eb`](https://github.com/gradio-app/gradio/commit/79c8156ebbf35369dc9cfb1522f88df3cd49c89c) - Queue concurrency count. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Publish all components to npm. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Open source FRP server and allow `gradio` to connect to custom share servers. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - File upload optimization. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Custom components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Removes deprecated arguments and parameters from v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Use async version of shutil in upload route. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Set cache dir for some component tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Proposal: sample demo for custom components should be a `gr.Interface`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - fix cc build. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - --overwrite deletes previous content. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6171](https://github.com/gradio-app/gradio/pull/6171) [`28322422c`](https://github.com/gradio-app/gradio/commit/28322422cb9d8d3e471e439ad602959662e79312) - strip dangling svelte imports. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Swap websockets for SSE. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6153](https://github.com/gradio-app/gradio/pull/6153) [`1162ed621`](https://github.com/gradio-app/gradio/commit/1162ed6217fe58d66a1923834c390150599ad81f) - Remove `show_edit_button` param in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6124](https://github.com/gradio-app/gradio/pull/6124) [`a7435ba9e`](https://github.com/gradio-app/gradio/commit/a7435ba9e6f8b88a838e80893eb8fedf60ccda67) - Fix static issues with Lite on v4. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6143](https://github.com/gradio-app/gradio/pull/6143) [`e4f7b4b40`](https://github.com/gradio-app/gradio/commit/e4f7b4b409323b01aa01b39e15ce6139e29aa073) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6136](https://github.com/gradio-app/gradio/pull/6136) [`667802a6c`](https://github.com/gradio-app/gradio/commit/667802a6cdbfb2ce454a3be5a78e0990b194548a) - JS Component Documentation. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6142](https://github.com/gradio-app/gradio/pull/6142) [`103416d17`](https://github.com/gradio-app/gradio/commit/103416d17f021c82f5ff0583dcc2d80906ad279e) - JS READMEs and Storybook on Docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6149](https://github.com/gradio-app/gradio/pull/6149) [`90318b1dd`](https://github.com/gradio-app/gradio/commit/90318b1dd118ae08a695a50e7c556226234ab6dc) - swap `mode` on the frontned to `interactive` to match the backend. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6128](https://github.com/gradio-app/gradio/pull/6128) [`9c3bf3175`](https://github.com/gradio-app/gradio/commit/9c3bf31751a414093d103e5a115772f3ef1a67aa) - Don't serve files in working directory by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6138](https://github.com/gradio-app/gradio/pull/6138) [`d2dfc1b9a`](https://github.com/gradio-app/gradio/commit/d2dfc1b9a9bd4940f70b62066b1aeaa905b9c7a9) - Small change to make `api_open=False` by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6152](https://github.com/gradio-app/gradio/pull/6152) [`982bff2fd`](https://github.com/gradio-app/gradio/commit/982bff2fdd938b798c400fb90d1cf0caf7278894) - Remove duplicate `elem_ids` from components. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6155](https://github.com/gradio-app/gradio/pull/6155) [`f71ea09ae`](https://github.com/gradio-app/gradio/commit/f71ea09ae796b85e9fe35956d426f0a19ee48f85) - Moves `gradio_cached_folder` inside the gradio temp direcotry. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6154](https://github.com/gradio-app/gradio/pull/6154) [`a8ef6d5dc`](https://github.com/gradio-app/gradio/commit/a8ef6d5dc97b35cc1da589d1a653209a3c327d98) - Remove interpretation for good. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6135](https://github.com/gradio-app/gradio/pull/6135) [`bce37ac74`](https://github.com/gradio-app/gradio/commit/bce37ac744496537e71546d2bb889bf248dcf5d3) - Fix selectable prop in the backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6118](https://github.com/gradio-app/gradio/pull/6118) [`88bccfdba`](https://github.com/gradio-app/gradio/commit/88bccfdba3df2df4b2747ea5d649ed528047cf50) - Improve Video Component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6126](https://github.com/gradio-app/gradio/pull/6126) [`865a22d5c`](https://github.com/gradio-app/gradio/commit/865a22d5c60fd97aeca968e55580b403743a23ec) - Refactor `Blocks.load()` so that it is in the same style as the other listeners. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6098](https://github.com/gradio-app/gradio/pull/6098) [`c3bc515bf`](https://github.com/gradio-app/gradio/commit/c3bc515bf7d430427182143f7fb047bb4b9f4e5e) - Gradio custom component publish. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6157](https://github.com/gradio-app/gradio/pull/6157) [`db143bdd1`](https://github.com/gradio-app/gradio/commit/db143bdd13b830f3bfd513bbfbc0cd1403522b84) - Make output components not editable if they are being updated. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6091](https://github.com/gradio-app/gradio/pull/6091) [`d5d29c947`](https://github.com/gradio-app/gradio/commit/d5d29c947467e54a8514790894ffffba1c796772) - Open source FRP server and allow `gradio` to connect to custom share servers. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6129](https://github.com/gradio-app/gradio/pull/6129) [`0d261c6ec`](https://github.com/gradio-app/gradio/commit/0d261c6ec1e783e284336023885f67b2ce04084c) - Fix fallback demo app template code. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6140](https://github.com/gradio-app/gradio/pull/6140) [`71bf2702c`](https://github.com/gradio-app/gradio/commit/71bf2702cd5b810c89e2e53452532650acdcfb87) - Fix video. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6069](https://github.com/gradio-app/gradio/pull/6069) [`bf127e124`](https://github.com/gradio-app/gradio/commit/bf127e1241a41401e144874ea468dff8474eb505) - Swap websockets for SSE. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6082](https://github.com/gradio-app/gradio/pull/6082) [`037e5af33`](https://github.com/gradio-app/gradio/commit/037e5af3363c5b321b95efc955ee8d6ec0f4504e) - WIP: Fix docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6071](https://github.com/gradio-app/gradio/pull/6071) [`f08da1a6f`](https://github.com/gradio-app/gradio/commit/f08da1a6f288f6ab8ec40534d5a9e2c64bed4b3b) - Fixes markdown rendering in examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5970](https://github.com/gradio-app/gradio/pull/5970) [`0c571c044`](https://github.com/gradio-app/gradio/commit/0c571c044035989d6fe33fc01fee63d1780635cb) - Add json schema unit tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6016](https://github.com/gradio-app/gradio/pull/6016) [`83e947676`](https://github.com/gradio-app/gradio/commit/83e947676d327ca2ab6ae2a2d710c78961c771a0) - Format js in v4 branch. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6093](https://github.com/gradio-app/gradio/pull/6093) [`fadc057bb`](https://github.com/gradio-app/gradio/commit/fadc057bb7016f90dd94049c79fc10d38150c561) - V4: Fix constructor_args. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5966](https://github.com/gradio-app/gradio/pull/5966) [`9cad2127b`](https://github.com/gradio-app/gradio/commit/9cad2127b965023687470b3abfe620e188a9da6e) - Improve Audio Component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6014](https://github.com/gradio-app/gradio/pull/6014) [`cad537aac`](https://github.com/gradio-app/gradio/commit/cad537aac57998560c9f44a37499be734de66349) - pass props to example components and to example outputs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5955](https://github.com/gradio-app/gradio/pull/5955) [`825c9cddc`](https://github.com/gradio-app/gradio/commit/825c9cddc83a09457d8c85ebeecb4bc705572d82) - Fix dev mode model3D. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6107](https://github.com/gradio-app/gradio/pull/6107) [`9a40de7bf`](https://github.com/gradio-app/gradio/commit/9a40de7bff5844c8a135e73c7d175eb02b63a966) - Fix: Move to cache in init postprocess + Fallback Fixes. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6018](https://github.com/gradio-app/gradio/pull/6018) [`184834d02`](https://github.com/gradio-app/gradio/commit/184834d02d448bff387eeb3aef64d9517962f146) - Add a cli command to list available templates. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6092](https://github.com/gradio-app/gradio/pull/6092) [`11d67ae75`](https://github.com/gradio-app/gradio/commit/11d67ae7529e0838565e4131b185c413489c5aa6) - Add a stand-alone install command and tidy-up the fallback template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6026](https://github.com/gradio-app/gradio/pull/6026) [`338969af2`](https://github.com/gradio-app/gradio/commit/338969af290de032f9cdc204dab8a50be3bf3cc5) - V4: Single-file implementation of form components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6114](https://github.com/gradio-app/gradio/pull/6114) [`39227b6fa`](https://github.com/gradio-app/gradio/commit/39227b6fac274d5f5b301bc14039571c1bfe510c) - Try to trigger a major beta release. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6060](https://github.com/gradio-app/gradio/pull/6060) [`447dfe06b`](https://github.com/gradio-app/gradio/commit/447dfe06bf19324d88696eb646fd1c5f1c4e86ed) - Clean up backend of `File` and `UploadButton` and change the return type of `preprocess()` from TemporaryFIle to string filepath. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6073](https://github.com/gradio-app/gradio/pull/6073) [`abff6fb75`](https://github.com/gradio-app/gradio/commit/abff6fb758bd310053a23c938bf1dd8fbdc5d333) - Fix remaining xfail tests in backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6089](https://github.com/gradio-app/gradio/pull/6089) [`cd8146ba0`](https://github.com/gradio-app/gradio/commit/cd8146ba053fbcb56cf5052e658e4570d457fb8a) - Update logos for v4. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5961](https://github.com/gradio-app/gradio/pull/5961) [`be2ed5e13`](https://github.com/gradio-app/gradio/commit/be2ed5e13222cbe5013b63b36685987518034a76) - File upload optimization. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5968](https://github.com/gradio-app/gradio/pull/5968) [`6b0bb5e6a`](https://github.com/gradio-app/gradio/commit/6b0bb5e6a252ce8c4ef38455a9f56f1dcda56ab0) - Removes deprecated arguments and parameters from v4. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6027](https://github.com/gradio-app/gradio/pull/6027) [`de18102b8`](https://github.com/gradio-app/gradio/commit/de18102b8ca38c1d6d6edfa8c0571b81089166bb) - V4: Fix component update bug. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5996](https://github.com/gradio-app/gradio/pull/5996) [`9cf40f76f`](https://github.com/gradio-app/gradio/commit/9cf40f76fed1c0f84b5a5336a9b0100f8a9b4ee3) - V4: Simple dropdown. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5990](https://github.com/gradio-app/gradio/pull/5990) [`85056de5c`](https://github.com/gradio-app/gradio/commit/85056de5cd4e90a10cbfcefab74037dbc622b26b) - V4: Simple textbox. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6044](https://github.com/gradio-app/gradio/pull/6044) [`9053c95a1`](https://github.com/gradio-app/gradio/commit/9053c95a10de12aef572018ee37c71106d2da675) - Simplify File Component. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6077](https://github.com/gradio-app/gradio/pull/6077) [`35a227fbf`](https://github.com/gradio-app/gradio/commit/35a227fbfb0b0eb11806c0382c5f6910dc9777cf) - Proposal: sample demo for custom components should be a `gr.Interface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6079](https://github.com/gradio-app/gradio/pull/6079) [`3b2d9eaa3`](https://github.com/gradio-app/gradio/commit/3b2d9eaa3e84de3e4a0799e4585a94510d665f26) - fix cc build. Thanks [@pngwn](https://github.com/pngwn)!
+
+
+### Fixes
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Pending events behavior. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Reinstate types that were removed in error in #5832. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Fixes: slider bar are too thin on FireFox. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6146](https://github.com/gradio-app/gradio/pull/6146) [`40a171ea6`](https://github.com/gradio-app/gradio/commit/40a171ea60c74afa9519d6cb159def16ce68e1ca) - Fix image double change bug. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6148](https://github.com/gradio-app/gradio/pull/6148) [`0000a1916`](https://github.com/gradio-app/gradio/commit/0000a191688c5480c977c80acdd0c9023865d57e) - fix dropdown arrow size. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6067](https://github.com/gradio-app/gradio/pull/6067) [`bf38e5f06`](https://github.com/gradio-app/gradio/commit/bf38e5f06a7039be913614901c308794fea83ae0) - remove dupe component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6065](https://github.com/gradio-app/gradio/pull/6065) [`7d07001e8`](https://github.com/gradio-app/gradio/commit/7d07001e8e7ca9cbd2251632667b3a043de49f49) - fix storybook. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5826](https://github.com/gradio-app/gradio/pull/5826) [`ce036c5d4`](https://github.com/gradio-app/gradio/commit/ce036c5d47e741e29812654bcc641ea6be876504) - Pending events behavior. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6046](https://github.com/gradio-app/gradio/pull/6046) [`dbb7de5e0`](https://github.com/gradio-app/gradio/commit/dbb7de5e02c53fee05889d696d764d212cb96c74) - fix tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6042](https://github.com/gradio-app/gradio/pull/6042) [`e27997fe6`](https://github.com/gradio-app/gradio/commit/e27997fe6c2bcfebc7015fc26100cee9625eb13a) - Fix `root` when user is unauthenticated so that login page appears correctly. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6076](https://github.com/gradio-app/gradio/pull/6076) [`f3f98f923`](https://github.com/gradio-app/gradio/commit/f3f98f923c9db506284b8440e18a3ac7ddd8398b) - Lite error handler. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5984](https://github.com/gradio-app/gradio/pull/5984) [`66549d8d2`](https://github.com/gradio-app/gradio/commit/66549d8d256b1845c8c5efa0384695b36cb46eab) - Fixes: slider bar are too thin on FireFox. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+
+## 3.45.0-beta.13
+
+### Features
+
+- [#5964](https://github.com/gradio-app/gradio/pull/5964) [`5fbda0bd2`](https://github.com/gradio-app/gradio/commit/5fbda0bd2b2bbb2282249b8875d54acf87cd7e84) - Wasm release. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.45.0-beta.12
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Some misc fixes. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5960](https://github.com/gradio-app/gradio/pull/5960) [`319c30f3f`](https://github.com/gradio-app/gradio/commit/319c30f3fccf23bfe1da6c9b132a6a99d59652f7) - rererefactor frontend files. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Add host to dev mode for vite. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`d2314e53b`](https://github.com/gradio-app/gradio/commit/d2314e53bc088ff6f307a122a9a01bafcdcff5c2) - BugFix: Make FileExplorer Component Templateable. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Use tags to identify custom component dirs and ignore uninstalled components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5956](https://github.com/gradio-app/gradio/pull/5956) [`f769876e0`](https://github.com/gradio-app/gradio/commit/f769876e0fa62336425c4e8ada5e09f38353ff01) - Apply formatter (and small refactoring) to the Lite-related frontend code. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5938](https://github.com/gradio-app/gradio/pull/5938) [`13ed8a485`](https://github.com/gradio-app/gradio/commit/13ed8a485d5e31d7d75af87fe8654b661edcca93) - V4: Use beta release versions for '@gradio' packages. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Adds the ability to build the frontend and backend of custom components in preparation for publishing to pypi using `gradio_component build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Fix deployed demos on v4 branch. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Set api=False for cancel events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Use full path to executables in CLI. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5949](https://github.com/gradio-app/gradio/pull/5949) [`1c390f101`](https://github.com/gradio-app/gradio/commit/1c390f10199142a41722ba493a0c86b58245da15) - Merge main again. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Simplify how files are handled in components in 4.0. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Name Endpoints if api_name is None. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5937](https://github.com/gradio-app/gradio/pull/5937) [`dcf13d750`](https://github.com/gradio-app/gradio/commit/dcf13d750b1465f905e062a1368ba754446cc23f) - V4: Update Component pyi file. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Rename gradio_component to gradio component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Use async version of shutil in upload route. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Set cache dir for some component tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5894](https://github.com/gradio-app/gradio/pull/5894) [`fee3d527e`](https://github.com/gradio-app/gradio/commit/fee3d527e83a615109cf937f6ca0a37662af2bb6) - Adds `column_widths` to `gr.Dataframe` and hide overflowing text when `wrap=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Better logs in dev mode. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5946](https://github.com/gradio-app/gradio/pull/5946) [`d0cc6b136`](https://github.com/gradio-app/gradio/commit/d0cc6b136fd59121f74d0c5a1a4b51740ffaa838) - fixup. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5944](https://github.com/gradio-app/gradio/pull/5944) [`465f58957`](https://github.com/gradio-app/gradio/commit/465f58957f70c7cf3e894beef8a117b28339e3c1) - Show empty JSON icon when `value` is `null`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Reinstate types that were removed in error in #5832. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.48.0
+
+### Features
+
+- [#5627](https://github.com/gradio-app/gradio/pull/5627) [`b67115e8e`](https://github.com/gradio-app/gradio/commit/b67115e8e6e489fffd5271ea830211863241ddc5) - Lite: Make the Examples component display media files using pseudo HTTP requests to the Wasm server. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5821](https://github.com/gradio-app/gradio/pull/5821) [`1aa186220`](https://github.com/gradio-app/gradio/commit/1aa186220dfa8ee3621b818c4cdf4d7b9d690b40) - Lite: Fix Examples.create() to be a normal func so it can be called in the Wasm env. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5886](https://github.com/gradio-app/gradio/pull/5886) [`121f25b2d`](https://github.com/gradio-app/gradio/commit/121f25b2d50a33e1e06721b79e20b4f5651987ba) - Lite: Fix is_self_host() to detect `127.0.0.1` as localhost as well. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5915](https://github.com/gradio-app/gradio/pull/5915) [`e24163e15`](https://github.com/gradio-app/gradio/commit/e24163e15afdfc51ec8cb00a0dc46c2318b245be) - Added dimensionality check to avoid bad array dimensions. Thanks [@THEGAMECHANGER416](https://github.com/THEGAMECHANGER416)!
+- [#5835](https://github.com/gradio-app/gradio/pull/5835) [`46334780d`](https://github.com/gradio-app/gradio/commit/46334780dbbb7e83f31971d45a7047ee156a0578) - Mention that audio is normalized when converting to wav in docs. Thanks [@aileenvl](https://github.com/aileenvl)!
+- [#5877](https://github.com/gradio-app/gradio/pull/5877) [`a55b80942`](https://github.com/gradio-app/gradio/commit/a55b8094231ae462ac53f52bbdb460c1286ffabb) - Add styling (e.g. font colors and background colors) support to `gr.DataFrame` through the `pd.Styler` object. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5819](https://github.com/gradio-app/gradio/pull/5819) [`5f1cbc436`](https://github.com/gradio-app/gradio/commit/5f1cbc4363b09302334e9bc864587f8ef398550d) - Add support for gr.Request to gr.ChatInterface. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5901](https://github.com/gradio-app/gradio/pull/5901) [`c4e3a9274`](https://github.com/gradio-app/gradio/commit/c4e3a92743a3b41edad8b45c5d5b0ccbc2674a30) - Fix curly brackets in docstrings. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5934](https://github.com/gradio-app/gradio/pull/5934) [`8d909624f`](https://github.com/gradio-app/gradio/commit/8d909624f61a49536e3c0f71cb2d9efe91216219) - Fix styling issues with Audio, Image and Video components. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5864](https://github.com/gradio-app/gradio/pull/5864) [`e70805d54`](https://github.com/gradio-app/gradio/commit/e70805d54cc792452545f5d8eccc1aa0212a4695) - Change `BlockLabel` element to use ``. Thanks [@aileenvl](https://github.com/aileenvl)!
+- [#5862](https://github.com/gradio-app/gradio/pull/5862) [`c07207e0b`](https://github.com/gradio-app/gradio/commit/c07207e0bc98cc32b6db629c432fadf877e451ff) - Remove deprecated `.update()` usage from Interface internals. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5905](https://github.com/gradio-app/gradio/pull/5905) [`b450cef15`](https://github.com/gradio-app/gradio/commit/b450cef15685c934ba7c4e4d57cbed233e925fb1) - Fix type the docstring of the Code component. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5840](https://github.com/gradio-app/gradio/pull/5840) [`4e62b8493`](https://github.com/gradio-app/gradio/commit/4e62b8493dfce50bafafe49f1a5deb929d822103) - Ensure websocket polyfill doesn't load if there is already a `global.Webocket` property set. Thanks [@Jay2theWhy](https://github.com/Jay2theWhy)!
+- [#5839](https://github.com/gradio-app/gradio/pull/5839) [`b83064da0`](https://github.com/gradio-app/gradio/commit/b83064da0005ca055fc15ee478cf064bf91702a4) - Fix error when scrolling dropdown with scrollbar. Thanks [@Kit-p](https://github.com/Kit-p)!
+- [#5822](https://github.com/gradio-app/gradio/pull/5822) [`7b63db271`](https://github.com/gradio-app/gradio/commit/7b63db27161ab538f20cf8523fc04c9c3b604a98) - Convert async methods in the Examples class into normal sync methods. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5904](https://github.com/gradio-app/gradio/pull/5904) [`891d42e9b`](https://github.com/gradio-app/gradio/commit/891d42e9baa7ab85ede2a5eadb56c274b0ed2785) - Define Font.__repr__() to be printed in the doc in a readable format. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5811](https://github.com/gradio-app/gradio/pull/5811) [`1d5b15a2d`](https://github.com/gradio-app/gradio/commit/1d5b15a2d24387154f2cfb40a36de25b331471d3) - Assert refactor in external.py. Thanks [@harry-urek](https://github.com/harry-urek)!
+- [#5827](https://github.com/gradio-app/gradio/pull/5827) [`48e09ee88`](https://github.com/gradio-app/gradio/commit/48e09ee88799efa38a5cc9b1b61e462f72ec6093) - Quick fix: Chatbot change event. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5890](https://github.com/gradio-app/gradio/pull/5890) [`c4ba832b3`](https://github.com/gradio-app/gradio/commit/c4ba832b318dad5e8bf565cfa0daf93ca188498f) - Remove deprecation warning from `gr.update` and clean up associated code. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5897](https://github.com/gradio-app/gradio/pull/5897) [`0592c301d`](https://github.com/gradio-app/gradio/commit/0592c301df9cd949b52159c85b7042f38d113e86) - Fix Dataframe `line_breaks`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5878](https://github.com/gradio-app/gradio/pull/5878) [`fbce277e5`](https://github.com/gradio-app/gradio/commit/fbce277e50c5885371fd49c68adf8565c25c1d39) - Keep Markdown rendered lists within dataframe cells. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5930](https://github.com/gradio-app/gradio/pull/5930) [`361823896`](https://github.com/gradio-app/gradio/commit/3618238960d54df65c34895f4eb69d08acc3f9b6) - Fix dataframe `line_breaks`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 3.47.1
+
+### Fixes
+
+- [#5816](https://github.com/gradio-app/gradio/pull/5816) [`796145e2c`](https://github.com/gradio-app/gradio/commit/796145e2c48c4087bec17f8ec0be4ceee47170cb) - Fix calls to the component server so that `gr.FileExplorer` works on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.47.0
+
+### Highlights
+
+#### new `FileExplorer` component ([#5672](https://github.com/gradio-app/gradio/pull/5672) [`e4a307ed6`](https://github.com/gradio-app/gradio/commit/e4a307ed6cde3bbdf4ff2f17655739addeec941e))
+
+Thanks to a new capability that allows components to communicate directly with the server _without_ passing data via the value, we have created a new `FileExplorer` component.
+
+This component allows you to populate the explorer by passing a glob, but only provides the selected file(s) in your prediction function.
+
+Users can then navigate the virtual filesystem and select files which will be accessible in your predict function. This component will allow developers to build more complex spaces, with more flexible input options.
+
+![output](https://github.com/pngwn/MDsveX/assets/12937446/ef108f0b-0e84-4292-9984-9dc66b3e144d)
+
+For more information check the [`FileExplorer` documentation](https://gradio.app/docs/fileexplorer).
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5780](https://github.com/gradio-app/gradio/pull/5780) [`ed0f9a21b`](https://github.com/gradio-app/gradio/commit/ed0f9a21b04ad6b941b63d2ce45100dbd1abd5c5) - Adds `change()` event to `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5783](https://github.com/gradio-app/gradio/pull/5783) [`4567788bd`](https://github.com/gradio-app/gradio/commit/4567788bd1fc25df9322902ba748012e392b520a) - Adds the ability to set the `selected_index` in a `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5787](https://github.com/gradio-app/gradio/pull/5787) [`caeee8bf7`](https://github.com/gradio-app/gradio/commit/caeee8bf7821fd5fe2f936ed82483bed00f613ec) - ensure the client does not depend on `window` when running in a node environment. Thanks [@gibiee](https://github.com/gibiee)!
+
+### Fixes
+
+- [#5798](https://github.com/gradio-app/gradio/pull/5798) [`a0d3cc45c`](https://github.com/gradio-app/gradio/commit/a0d3cc45c6db48dc0db423c229b8fb285623cdc4) - Fix `gr.SelectData` so that the target attribute is correctly attached, and the filedata is included in the data attribute with `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5795](https://github.com/gradio-app/gradio/pull/5795) [`957ba5cfd`](https://github.com/gradio-app/gradio/commit/957ba5cfde18e09caedf31236a2064923cd7b282) - Prevent bokeh from injecting bokeh js multiple times. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5790](https://github.com/gradio-app/gradio/pull/5790) [`37e70842d`](https://github.com/gradio-app/gradio/commit/37e70842d59f5aed6fab0086b1abf4b8d991f1c9) - added try except block in `state.py`. Thanks [@SrijanSahaySrivastava](https://github.com/SrijanSahaySrivastava)!
+- [#5794](https://github.com/gradio-app/gradio/pull/5794) [`f096c3ae1`](https://github.com/gradio-app/gradio/commit/f096c3ae168c0df00f90fe131c1e48c572e0574b) - Throw helpful error when media devices are not found. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5776](https://github.com/gradio-app/gradio/pull/5776) [`c0fef4454`](https://github.com/gradio-app/gradio/commit/c0fef44541bfa61568bdcfcdfc7d7d79869ab1df) - Revert replica proxy logic and instead implement using the `root` variable. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.46.1
+
+### Features
+
+- [#5124](https://github.com/gradio-app/gradio/pull/5124) [`6e56a0d9b`](https://github.com/gradio-app/gradio/commit/6e56a0d9b0c863e76c69e1183d9d40196922b4cd) - Lite: Websocket queueing. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5775](https://github.com/gradio-app/gradio/pull/5775) [`e2874bc3c`](https://github.com/gradio-app/gradio/commit/e2874bc3cb1397574f77dbd7f0408ed4e6792970) - fix pending chatbot message styling and ensure messages with value `None` don't render. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 3.46.0
+
+### Features
+
+- [#5699](https://github.com/gradio-app/gradio/pull/5699) [`8f0fed857`](https://github.com/gradio-app/gradio/commit/8f0fed857d156830626eb48b469d54d211a582d2) - Improve chatbot accessibility and UX. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5569](https://github.com/gradio-app/gradio/pull/5569) [`2a5b9e03b`](https://github.com/gradio-app/gradio/commit/2a5b9e03b15ea324d641fe6982f26d81b1ca7210) - Added support for pandas `Styler` object to `gr.DataFrame` (initially just sets the `display_value`). Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5735](https://github.com/gradio-app/gradio/pull/5735) [`abb5e9df4`](https://github.com/gradio-app/gradio/commit/abb5e9df47989b2c56c2c312d74944678f9f2d4e) - Ensure images with no caption download in gallery. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5754](https://github.com/gradio-app/gradio/pull/5754) [`502054848`](https://github.com/gradio-app/gradio/commit/502054848fdbe39fc03ec42445242b4e49b7affc) - Fix Gallery `columns` and `rows` params. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5755](https://github.com/gradio-app/gradio/pull/5755) [`e842a561a`](https://github.com/gradio-app/gradio/commit/e842a561af4394f8109291ee5725bcf74743e816) - Fix new line issue in chatbot. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5731](https://github.com/gradio-app/gradio/pull/5731) [`c9af4f794`](https://github.com/gradio-app/gradio/commit/c9af4f794060e218193935d7213f0991a374f502) - Added timeout and error handling for frpc tunnel. Thanks [@cansik](https://github.com/cansik)!
+- [#5766](https://github.com/gradio-app/gradio/pull/5766) [`ef96d3512`](https://github.com/gradio-app/gradio/commit/ef96d351229272738fc3c9680f7111f159590341) - Don't raise warnings when returning an updated component in a dictionary. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5767](https://github.com/gradio-app/gradio/pull/5767) [`caf6d9c0e`](https://github.com/gradio-app/gradio/commit/caf6d9c0e1f5b867cc20f2b4f6abb5ef47503a5f) - Set share=True for all Gradio apps in Colab by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.45.2
+
+### Features
+
+- [#5722](https://github.com/gradio-app/gradio/pull/5722) [`dba651904`](https://github.com/gradio-app/gradio/commit/dba651904c97dcddcaae2691540ac430d3eefd18) - Fix for deepcopy errors when running the replica-related logic on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5721](https://github.com/gradio-app/gradio/pull/5721) [`84e03fe50`](https://github.com/gradio-app/gradio/commit/84e03fe506e08f1f81bac6d504c9fba7924f2d93) - Adds copy buttons to website, and better descriptions to API Docs. Thanks [@aliabd](https://github.com/aliabd)!
+
+### Fixes
+
+- [#5714](https://github.com/gradio-app/gradio/pull/5714) [`a0fc5a296`](https://github.com/gradio-app/gradio/commit/a0fc5a29678baa2d9ba997a2124cadebecfb2c36) - Make Tab and Tabs updatable. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5713](https://github.com/gradio-app/gradio/pull/5713) [`c10dabd6b`](https://github.com/gradio-app/gradio/commit/c10dabd6b18b49259441eb5f956a19046f466339) - Fixes gr.select() Method Issues with Dataframe Cells. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5693](https://github.com/gradio-app/gradio/pull/5693) [`c2b31c396`](https://github.com/gradio-app/gradio/commit/c2b31c396f6d260cdf93377b715aee7ff162df75) - Context-based Progress tracker. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5705](https://github.com/gradio-app/gradio/pull/5705) [`78e7cf516`](https://github.com/gradio-app/gradio/commit/78e7cf5163e8d205e8999428fce4c02dbdece25f) - ensure internal data has updated before dispatching `success` or `then` events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5668](https://github.com/gradio-app/gradio/pull/5668) [`d626c21e9`](https://github.com/gradio-app/gradio/commit/d626c21e91df026b04fdb3ee5c7dba74a261cfd3) - Fully resolve generated filepaths when running on Hugging Face Spaces with multiple replicas. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5711](https://github.com/gradio-app/gradio/pull/5711) [`aefb556ac`](https://github.com/gradio-app/gradio/commit/aefb556ac6dbadc320c618b11bb48371ef19dd61) - prevent internal log_message error from `/api/predict`. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5726](https://github.com/gradio-app/gradio/pull/5726) [`96c4b97c7`](https://github.com/gradio-app/gradio/commit/96c4b97c742311e90a87d8e8ee562c6ad765e9f0) - Adjust translation. Thanks [@ylhsieh](https://github.com/ylhsieh)!
+- [#5732](https://github.com/gradio-app/gradio/pull/5732) [`3a48490bc`](https://github.com/gradio-app/gradio/commit/3a48490bc5e4136ec9bc0354b0d6fb6c04280505) - Add a bare `Component` type to the acceptable type list of `gr.load()`'s `inputs` and `outputs`. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 3.45.1
+
+### Fixes
+
+- [#5701](https://github.com/gradio-app/gradio/pull/5701) [`ee8eec1e5`](https://github.com/gradio-app/gradio/commit/ee8eec1e5e544a0127e0aa68c2522a7085b8ada5) - Fix for regression in rendering empty Markdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.45.0
+
+### Features
+
+- [#5675](https://github.com/gradio-app/gradio/pull/5675) [`b619e6f6e`](https://github.com/gradio-app/gradio/commit/b619e6f6e4ca55334fb86da53790e45a8f978566) - Reorganize Docs Navbar and Fill in Gaps. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5669](https://github.com/gradio-app/gradio/pull/5669) [`c5e969559`](https://github.com/gradio-app/gradio/commit/c5e969559612f956afcdb0c6f7b22ab8275bc49a) - Fix small issues in docs and guides. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5682](https://github.com/gradio-app/gradio/pull/5682) [`c57f1b75e`](https://github.com/gradio-app/gradio/commit/c57f1b75e272c76b0af4d6bd0c7f44743ff34f26) - Fix functional tests. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5681](https://github.com/gradio-app/gradio/pull/5681) [`40de3d217`](https://github.com/gradio-app/gradio/commit/40de3d2178b61ebe424b6f6228f94c0c6f679bea) - add query parameters to the `gr.Request` object through the `query_params` attribute. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5653](https://github.com/gradio-app/gradio/pull/5653) [`ea0e00b20`](https://github.com/gradio-app/gradio/commit/ea0e00b207b4b90a10e9d054c4202d4e705a29ba) - Prevent Clients from accessing API endpoints that set `api_name=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5639](https://github.com/gradio-app/gradio/pull/5639) [`e1874aff8`](https://github.com/gradio-app/gradio/commit/e1874aff814d13b23f3e59ef239cc13e18ad3fa7) - Add `gr.on` listener method. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5652](https://github.com/gradio-app/gradio/pull/5652) [`2e25d4305`](https://github.com/gradio-app/gradio/commit/2e25d430582264945ae3316acd04c4453a25ce38) - Pause autoscrolling if a user scrolls up in a `gr.Textbox` and resume autoscrolling if they go all the way down. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5642](https://github.com/gradio-app/gradio/pull/5642) [`21c7225bd`](https://github.com/gradio-app/gradio/commit/21c7225bda057117a9d3311854323520218720b5) - Improve plot rendering. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5677](https://github.com/gradio-app/gradio/pull/5677) [`9f9af327c`](https://github.com/gradio-app/gradio/commit/9f9af327c9115356433ec837f349d6286730fb97) - [Refactoring] Convert async functions that don't contain `await` statements to normal functions. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5660](https://github.com/gradio-app/gradio/pull/5660) [`d76555a12`](https://github.com/gradio-app/gradio/commit/d76555a122b545f0df7c9e7c1ca7bd2a6e262c86) - Fix secondary hue bug in gr.themes.builder(). Thanks [@hellofreckles](https://github.com/hellofreckles)!
+- [#5697](https://github.com/gradio-app/gradio/pull/5697) [`f4e4f82b5`](https://github.com/gradio-app/gradio/commit/f4e4f82b58a65efca9030a7e8e7c5ace60d8cc10) - Increase Slider clickable area. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5671](https://github.com/gradio-app/gradio/pull/5671) [`6a36c3b78`](https://github.com/gradio-app/gradio/commit/6a36c3b786700600d3826ce1e0629cc5308ddd47) - chore(deps): update dependency @types/prismjs to v1.26.1. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5240](https://github.com/gradio-app/gradio/pull/5240) [`da05e59a5`](https://github.com/gradio-app/gradio/commit/da05e59a53bbad15e5755a47f46685da18e1031e) - Cleanup of .update and .get_config per component. Thanks [@aliabid94](https://github.com/aliabid94)!/n get_config is removed, the config used is simply any attribute that is in the Block that shares a name with one of the constructor paramaters./n update is not removed for backwards compatibility, but deprecated. Instead return the component itself. Created a updateable decorator that simply checks to see if we're in an update, and if so, skips the constructor and wraps the args and kwargs in an update dictionary. easy peasy.
+- [#5635](https://github.com/gradio-app/gradio/pull/5635) [`38fafb9e2`](https://github.com/gradio-app/gradio/commit/38fafb9e2a5509b444942e1d5dd48dffa20066f4) - Fix typos in Gallery docs. Thanks [@atesgoral](https://github.com/atesgoral)!
+- [#5590](https://github.com/gradio-app/gradio/pull/5590) [`d1ad1f671`](https://github.com/gradio-app/gradio/commit/d1ad1f671caef9f226eb3965f39164c256d8615c) - Attach `elem_classes` selectors to layout elements, and an id to the Tab button (for targeting via CSS/JS). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5554](https://github.com/gradio-app/gradio/pull/5554) [`75ddeb390`](https://github.com/gradio-app/gradio/commit/75ddeb390d665d4484667390a97442081b49a423) - Accessibility Improvements. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5598](https://github.com/gradio-app/gradio/pull/5598) [`6b1714386`](https://github.com/gradio-app/gradio/commit/6b17143868bdd2c1400af1199a01c1c0d5c27477) - Upgrade Pyodide to 0.24.0 and install the native orjson package. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5625](https://github.com/gradio-app/gradio/pull/5625) [`9ccc4794a`](https://github.com/gradio-app/gradio/commit/9ccc4794a72ce8319417119f6c370e7af3ffca6d) - Use ContextVar instead of threading.local(). Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5602](https://github.com/gradio-app/gradio/pull/5602) [`54d21d3f1`](https://github.com/gradio-app/gradio/commit/54d21d3f18f2ddd4e796d149a0b41461f49c711b) - Ensure `HighlightedText` with `merge_elements` loads without a value. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5636](https://github.com/gradio-app/gradio/pull/5636) [`fb5964fb8`](https://github.com/gradio-app/gradio/commit/fb5964fb88082e7b956853b543c468116811cab9) - Fix bug in example cache loading event. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5633](https://github.com/gradio-app/gradio/pull/5633) [`341402337`](https://github.com/gradio-app/gradio/commit/34140233794c29d4722020e13c2d045da642dfae) - Allow Gradio apps containing `gr.Radio()`, `gr.Checkboxgroup()`, or `gr.Dropdown()` to be loaded with `gr.load()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5616](https://github.com/gradio-app/gradio/pull/5616) [`7c34b434a`](https://github.com/gradio-app/gradio/commit/7c34b434aae0eb85f112a1dc8d66cefc7e2296b2) - Fix width and height issues that would cut off content in `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5604](https://github.com/gradio-app/gradio/pull/5604) [`faad01f8e`](https://github.com/gradio-app/gradio/commit/faad01f8e10ef6d18249b1a4587477c59b74adb2) - Add `render_markdown` parameter to chatbot. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5593](https://github.com/gradio-app/gradio/pull/5593) [`88d43bd12`](https://github.com/gradio-app/gradio/commit/88d43bd124792d216da445adef932a2b02f5f416) - Fixes avatar image in chatbot being squashed. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5690](https://github.com/gradio-app/gradio/pull/5690) [`6b8c8afd9`](https://github.com/gradio-app/gradio/commit/6b8c8afd981fea984da568e9a0bd8bfc2a9c06c4) - Fix incorrect behavior of `gr.load()` with `gr.Examples`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5696](https://github.com/gradio-app/gradio/pull/5696) [`e51fcd5d5`](https://github.com/gradio-app/gradio/commit/e51fcd5d54315e8b65ee40e3de4dab17579ff6d5) - setting share=True on Spaces or in wasm should warn instead of raising error. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.4
+
+### Features
+
+- [#5514](https://github.com/gradio-app/gradio/pull/5514) [`52f783175`](https://github.com/gradio-app/gradio/commit/52f7831751b432411e109bd41add4ab286023a8e) - refactor: Use package.json for version management. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5535](https://github.com/gradio-app/gradio/pull/5535) [`d29b1ab74`](https://github.com/gradio-app/gradio/commit/d29b1ab740784d8c70f9ab7bc38bbbf7dd3ff737) - Makes sliders consistent across all browsers. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+### Fixes
+
+- [#5587](https://github.com/gradio-app/gradio/pull/5587) [`e0d61b8ba`](https://github.com/gradio-app/gradio/commit/e0d61b8baa0f6293f53b9bdb1647d42f9ae2583a) - Fix `.clear()` events for audio and image. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5534](https://github.com/gradio-app/gradio/pull/5534) [`d9e9ae43f`](https://github.com/gradio-app/gradio/commit/d9e9ae43f5c52c1f729af5a20e5d4f754689d429) - Guide fixes, esp. streaming audio. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5588](https://github.com/gradio-app/gradio/pull/5588) [`acdeff57e`](https://github.com/gradio-app/gradio/commit/acdeff57ece4672f943c374d537eaf47d3ec034f) - Allow multiple instances of Gradio with authentication to run on different ports. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.3
+
+### Fixes
+
+- [#5562](https://github.com/gradio-app/gradio/pull/5562) [`50d9747d0`](https://github.com/gradio-app/gradio/commit/50d9747d061962cff7f60a8da648bb3781794102) - chore(deps): update dependency iframe-resizer to v4.3.7. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5550](https://github.com/gradio-app/gradio/pull/5550) [`4ed5902e7`](https://github.com/gradio-app/gradio/commit/4ed5902e7dda2d95cd43e4ccaaef520ddd8eba57) - Adding basque language. Thanks [@EkhiAzur](https://github.com/EkhiAzur)!
+- [#5547](https://github.com/gradio-app/gradio/pull/5547) [`290f51871`](https://github.com/gradio-app/gradio/commit/290f5187160cdbd7a786494fe3c19b0e70abe167) - typo in UploadButton's docstring. Thanks [@chaeheum3](https://github.com/chaeheum3)!
+- [#5553](https://github.com/gradio-app/gradio/pull/5553) [`d1bf23cd2`](https://github.com/gradio-app/gradio/commit/d1bf23cd2c6da3692d7753856bfe7564d84778e0) - Modify Image examples docstring. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5563](https://github.com/gradio-app/gradio/pull/5563) [`ba64082ed`](https://github.com/gradio-app/gradio/commit/ba64082ed80c1ed9113497ae089e63f032dbcc75) - preprocess for components when type='index'. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.2
+
+### Fixes
+
+- [#5537](https://github.com/gradio-app/gradio/pull/5537) [`301c7878`](https://github.com/gradio-app/gradio/commit/301c7878217f9fc531c0f28330b394f02955811b) - allow gr.Image() examples to take urls. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5544](https://github.com/gradio-app/gradio/pull/5544) [`a0cc9ac9`](https://github.com/gradio-app/gradio/commit/a0cc9ac931554e06dcb091158c9b9ac0cc580b6c) - Fixes dropdown breaking if a user types in invalid value and presses enter. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.1
+
+### Fixes
+
+- [#5516](https://github.com/gradio-app/gradio/pull/5516) [`c5fe8eba`](https://github.com/gradio-app/gradio/commit/c5fe8ebadbf206e2f4199ccde4606e331a22148a) - Fix docstring of dropdown. Thanks [@hysts](https://github.com/hysts)!
+- [#5529](https://github.com/gradio-app/gradio/pull/5529) [`81c9ca9a`](https://github.com/gradio-app/gradio/commit/81c9ca9a2e00d19334f632fec32081d36ad54c7f) - Fix `.update()` method in `gr.Dropdown()` to handle `choices`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5528](https://github.com/gradio-app/gradio/pull/5528) [`dc86e4a7`](https://github.com/gradio-app/gradio/commit/dc86e4a7e1c40b910c74558e6f88fddf9b3292bc) - Lazy load all images. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5525](https://github.com/gradio-app/gradio/pull/5525) [`21f1db40`](https://github.com/gradio-app/gradio/commit/21f1db40de6d1717eba97a550e11422a457ba7e9) - Ensure input value saves on dropdown blur. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 3.44.0
+
+### Features
+
+- [#5505](https://github.com/gradio-app/gradio/pull/5505) [`9ee20f49`](https://github.com/gradio-app/gradio/commit/9ee20f499f62c1fe5af6b8f84918b3a334eb1c8d) - Validate i18n file names with ISO-639x. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5475](https://github.com/gradio-app/gradio/pull/5475) [`c60b89b0`](https://github.com/gradio-app/gradio/commit/c60b89b0a54758a27277f0a6aa20d0653647c7c8) - Adding Central Kurdish. Thanks [@Hrazhan](https://github.com/Hrazhan)!
+- [#5400](https://github.com/gradio-app/gradio/pull/5400) [`d112e261`](https://github.com/gradio-app/gradio/commit/d112e2611b0fc79ecedfaed367571f3157211387) - Allow interactive input in `gr.HighlightedText`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5488](https://github.com/gradio-app/gradio/pull/5488) [`8909e42a`](https://github.com/gradio-app/gradio/commit/8909e42a7c6272358ad413588d27a5124d151205) - Adds `autoscroll` param to `gr.Textbox()`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5384](https://github.com/gradio-app/gradio/pull/5384) [`ddc02268`](https://github.com/gradio-app/gradio/commit/ddc02268f731bd2ed04b7a5854accf3383f9a0da) - Allows the `gr.Dropdown` to have separate names and values, as well as enables `allow_custom_value` for multiselect dropdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5473](https://github.com/gradio-app/gradio/pull/5473) [`b271e738`](https://github.com/gradio-app/gradio/commit/b271e738860ca238ecdee2991f49b505c7559016) - Remove except asyncio.CancelledError which is no longer necessary due to 53d7025. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5474](https://github.com/gradio-app/gradio/pull/5474) [`041560f9`](https://github.com/gradio-app/gradio/commit/041560f9f11ca2560005b467bb412ee1becfc2b2) - Fix queueing.call_prediction to retrieve the default response class in the same manner as FastAPI's implementation. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5510](https://github.com/gradio-app/gradio/pull/5510) [`afcf3c48`](https://github.com/gradio-app/gradio/commit/afcf3c48e82712067d6d00a0caedb1562eb986f8) - Do not expose existence of files outside of working directory. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5459](https://github.com/gradio-app/gradio/pull/5459) [`bd2fda77`](https://github.com/gradio-app/gradio/commit/bd2fda77fc98d815f4fb670f535af453ebee9b80) - Dispatch `stop_recording` event in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5508](https://github.com/gradio-app/gradio/pull/5508) [`05715f55`](https://github.com/gradio-app/gradio/commit/05715f5599ae3e928d3183c7b0a7f5291f843a96) - Adds a `filterable` parameter to `gr.Dropdown` that controls whether user can type to filter choices. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5470](https://github.com/gradio-app/gradio/pull/5470) [`a4e010a9`](https://github.com/gradio-app/gradio/commit/a4e010a96f1d8a52b3ac645e03fe472b9c3cbbb1) - Fix share button position. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5496](https://github.com/gradio-app/gradio/pull/5496) [`82ec4d26`](https://github.com/gradio-app/gradio/commit/82ec4d2622a43c31b248b78e9410e2ac918f6035) - Allow interface with components to be run inside blocks. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.43.2
+
+### Fixes
+
+- [#5456](https://github.com/gradio-app/gradio/pull/5456) [`6e381c4f`](https://github.com/gradio-app/gradio/commit/6e381c4f146cc8177a4e2b8e39f914f09cd7ff0c) - ensure dataframe doesn't steal focus. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.43.1
+
+### Fixes
+
+- [#5445](https://github.com/gradio-app/gradio/pull/5445) [`67bb7bcb`](https://github.com/gradio-app/gradio/commit/67bb7bcb6a95b7a00a8bdf612cf147850d919a44) - ensure dataframe doesn't scroll unless needed. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5447](https://github.com/gradio-app/gradio/pull/5447) [`7a4a89e5`](https://github.com/gradio-app/gradio/commit/7a4a89e5ca1dedb39e5366867501584b0c636bbb) - ensure iframe is correct size on spaces. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.43.0
+
+### Features
+
+- [#5165](https://github.com/gradio-app/gradio/pull/5165) [`c77f05ab`](https://github.com/gradio-app/gradio/commit/c77f05abb65b2828c9c19af4ec0a0c09412f9f6a) - Fix the Queue to call API endpoints without internal HTTP routing. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5427](https://github.com/gradio-app/gradio/pull/5427) [`aad7acd7`](https://github.com/gradio-app/gradio/commit/aad7acd7128dca05b227ecbba06db9f94d65b088) - Add sort to bar plot. Thanks [@Chaitanya134](https://github.com/Chaitanya134)!
+- [#5342](https://github.com/gradio-app/gradio/pull/5342) [`afac0006`](https://github.com/gradio-app/gradio/commit/afac0006337ce2840cf497cd65691f2f60ee5912) - significantly improve the performance of `gr.Dataframe` for large datasets. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5417](https://github.com/gradio-app/gradio/pull/5417) [`d14d63e3`](https://github.com/gradio-app/gradio/commit/d14d63e30c4af3f9c2a664fd11b0a01943a8300c) - Auto scroll to bottom of textbox. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+### Fixes
+
+- [#5412](https://github.com/gradio-app/gradio/pull/5412) [`26fef8c7`](https://github.com/gradio-app/gradio/commit/26fef8c7f85a006c7e25cdbed1792df19c512d02) - Skip view_api request in js client when auth enabled. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5436](https://github.com/gradio-app/gradio/pull/5436) [`7ab4b70f`](https://github.com/gradio-app/gradio/commit/7ab4b70f6821afb4e85cef225d1235c19df8ebbf) - api_open does not take precedence over show_api. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.42.0
+
+### Highlights
+
+#### Like/Dislike Button for Chatbot ([#5391](https://github.com/gradio-app/gradio/pull/5391) [`abf1c57d`](https://github.com/gradio-app/gradio/commit/abf1c57d7d85de0df233ee3b38aeb38b638477db))
+
+ Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+#### Added the ability to attach event listeners via decorators ([#5395](https://github.com/gradio-app/gradio/pull/5395) [`55fed04f`](https://github.com/gradio-app/gradio/commit/55fed04f559becb9c24f22cc6292dc572d709886))
+
+e.g.
+
+```python
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+
+ @greet_btn.click(inputs=name, outputs=output)
+ def greet(name):
+ return "Hello " + name + "!"
+```
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5334](https://github.com/gradio-app/gradio/pull/5334) [`c5bf9138`](https://github.com/gradio-app/gradio/commit/c5bf91385a632dc9f612499ee01166ac6ae509a9) - Add chat bubble width param. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5267](https://github.com/gradio-app/gradio/pull/5267) [`119c8343`](https://github.com/gradio-app/gradio/commit/119c834331bfae60d4742c8f20e9cdecdd67e8c2) - Faster reload mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5373](https://github.com/gradio-app/gradio/pull/5373) [`79d8f9d8`](https://github.com/gradio-app/gradio/commit/79d8f9d891901683c5a1b7486efb44eab2478c96) - Adds `height` and `zoom_speed` parameters to `Model3D` component, as well as a button to reset the camera position. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5370](https://github.com/gradio-app/gradio/pull/5370) [`61803c65`](https://github.com/gradio-app/gradio/commit/61803c6545e73fce47e8740bd46721ab9bb0ba5c) - chore(deps): update dependency extendable-media-recorder to v9. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5266](https://github.com/gradio-app/gradio/pull/5266) [`4ccb9a86`](https://github.com/gradio-app/gradio/commit/4ccb9a86f194c6997f80a09880edc3c2b0554aab) - Makes it possible to set the initial camera position for the `Model3D` component as a tuple of (alpha, beta, radius). Thanks [@mbahri](https://github.com/mbahri)!
+- [#5271](https://github.com/gradio-app/gradio/pull/5271) [`97c3c7b1`](https://github.com/gradio-app/gradio/commit/97c3c7b1730407f9e80566af9ecb4ca7cccf62ff) - Move scripts from old website to CI. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5369](https://github.com/gradio-app/gradio/pull/5369) [`b8968898`](https://github.com/gradio-app/gradio/commit/b89688984fa9c6be0db06e392e6935a544620764) - Fix typo in utils.py. Thanks [@eltociear](https://github.com/eltociear)!
+
+### Fixes
+
+- [#5304](https://github.com/gradio-app/gradio/pull/5304) [`05892302`](https://github.com/gradio-app/gradio/commit/05892302fb8fe2557d57834970a2b65aea97355b) - Adds kwarg to disable html sanitization in `gr.Chatbot()`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5366](https://github.com/gradio-app/gradio/pull/5366) [`0cc7e2dc`](https://github.com/gradio-app/gradio/commit/0cc7e2dcf60e216e0a30e2f85a9879ce3cb2a1bd) - Hide avatar when message none. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5393](https://github.com/gradio-app/gradio/pull/5393) [`e4e7a431`](https://github.com/gradio-app/gradio/commit/e4e7a4319924aaf51dcb18d07d0c9953d4011074) - Renders LaTeX that is added to the page in `gr.Markdown`, `gr.Chatbot`, and `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5394](https://github.com/gradio-app/gradio/pull/5394) [`4d94ea0a`](https://github.com/gradio-app/gradio/commit/4d94ea0a0cf2103cda19f48398a5634f8341d04d) - Adds horizontal scrolling to content that overflows in gr.Markdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5368](https://github.com/gradio-app/gradio/pull/5368) [`b27f7583`](https://github.com/gradio-app/gradio/commit/b27f7583254165b135bf1496a7d8c489a62ba96f) - Change markdown rendering to set breaks to false. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5360](https://github.com/gradio-app/gradio/pull/5360) [`64666525`](https://github.com/gradio-app/gradio/commit/6466652583e3c620df995fb865ef3511a34cb676) - Cancel Dropdown Filter. Thanks [@deckar01](https://github.com/deckar01)!
+
+## 3.41.2
+
+### Features
+
+- [#5284](https://github.com/gradio-app/gradio/pull/5284) [`5f25eb68`](https://github.com/gradio-app/gradio/commit/5f25eb6836f6a78ce6208b53495a01e1fc1a1d2f) - Minor bug fix sweep. Thanks [@aliabid94](https://github.com/aliabid94)!/n - Our use of __exit__ was catching errors and corrupting the traceback of any component that failed to instantiate (try running blocks_kitchen_sink off main for an example). Now the __exit__ exits immediately if there's been an exception, so the original exception can be printed cleanly/n - HighlightedText was rendering weird, cleaned it up
+
+### Fixes
+
+- [#5319](https://github.com/gradio-app/gradio/pull/5319) [`3341148c`](https://github.com/gradio-app/gradio/commit/3341148c109b5458cc88435d27eb154210efc472) - Fix: wrap avatar-image in a div to clip its shape. Thanks [@Keldos-Li](https://github.com/Keldos-Li)!
+- [#5340](https://github.com/gradio-app/gradio/pull/5340) [`df090e89`](https://github.com/gradio-app/gradio/commit/df090e89f74a16e4cb2b700a1e3263cabd2bdd91) - Fix Checkbox select dispatch. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.41.1
+
+### Fixes
+
+- [#5324](https://github.com/gradio-app/gradio/pull/5324) [`31996c99`](https://github.com/gradio-app/gradio/commit/31996c991d6bfca8cef975eb8e3c9f61a7aced19) - ensure login form has correct styles. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5323](https://github.com/gradio-app/gradio/pull/5323) [`e32b0928`](https://github.com/gradio-app/gradio/commit/e32b0928d2d00342ca917ebb10c379ffc2ec200d) - ensure dropdown stays open when identical data is passed in. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.41.0
+
+### Highlights
+
+#### Improve startup performance and markdown support ([#5279](https://github.com/gradio-app/gradio/pull/5279) [`fe057300`](https://github.com/gradio-app/gradio/commit/fe057300f0672c62dab9d9b4501054ac5d45a4ec))
+
+##### Improved markdown support
+
+We now have better support for markdown in `gr.Markdown` and `gr.Dataframe`. Including syntax highlighting and Github Flavoured Markdown. We also have more consistent markdown behaviour and styling.
+
+##### Various performance improvements
+
+These improvements will be particularly beneficial to large applications.
+
+- Rather than attaching events manually, they are now delegated, leading to a significant performance improvement and addressing a performance regression introduced in a recent version of Gradio. App startup for large applications is now around twice as fast.
+- Optimised the mounting of individual components, leading to a modest performance improvement during startup (~30%).
+- Corrected an issue that was causing markdown to re-render infinitely.
+- Ensured that the `gr.3DModel` does re-render prematurely.
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+#### Enable streaming audio in python client ([#5248](https://github.com/gradio-app/gradio/pull/5248) [`390624d8`](https://github.com/gradio-app/gradio/commit/390624d8ad2b1308a5bf8384435fd0db98d8e29e))
+
+The `gradio_client` now supports streaming file outputs 🌊
+
+No new syntax! Connect to a gradio demo that supports streaming file outputs and call `predict` or `submit` as you normally would.
+
+```python
+import gradio_client as grc
+client = grc.Client("gradio/stream_audio_out")
+
+# Get the entire generated audio as a local file
+client.predict("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+job = client.submit("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+# Get the entire generated audio as a local file
+job.result()
+
+# Each individual chunk
+job.outputs()
+```
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+#### Add `render` function to `` ([#5158](https://github.com/gradio-app/gradio/pull/5158) [`804fcc05`](https://github.com/gradio-app/gradio/commit/804fcc058e147f283ece67f1f353874e26235535))
+
+We now have an event `render` on the web component, which is triggered once the embedded space has finished rendering.
+
+```html
+
+```
+
+ Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Features
+
+- [#5268](https://github.com/gradio-app/gradio/pull/5268) [`f49028cf`](https://github.com/gradio-app/gradio/commit/f49028cfe3e21097001ddbda71c560b3d8b42e1c) - Move markdown & latex processing to the frontend for the gr.Markdown and gr.DataFrame components. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5215](https://github.com/gradio-app/gradio/pull/5215) [`fbdad78a`](https://github.com/gradio-app/gradio/commit/fbdad78af4c47454cbb570f88cc14bf4479bbceb) - Lazy load interactive or static variants of a component individually, rather than loading both variants regardless. This change will improve performance for many applications. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5216](https://github.com/gradio-app/gradio/pull/5216) [`4b58ea6d`](https://github.com/gradio-app/gradio/commit/4b58ea6d98e7a43b3f30d8a4cb6f379bc2eca6a8) - Update i18n tokens and locale files. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5283](https://github.com/gradio-app/gradio/pull/5283) [`a7460557`](https://github.com/gradio-app/gradio/commit/a74605572dd0d6bb41df6b38b120d656370dd67d) - Add height parameter and scrolling to `gr.Dataframe`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5232](https://github.com/gradio-app/gradio/pull/5232) [`c57d4c23`](https://github.com/gradio-app/gradio/commit/c57d4c232a97e03b4671f9e9edc3af456438fe89) - `gr.Radio` and `gr.CheckboxGroup` can now accept different names and values. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5219](https://github.com/gradio-app/gradio/pull/5219) [`e8fd4e4e`](https://github.com/gradio-app/gradio/commit/e8fd4e4ec68a6c974bc8c84b61f4a0ec50a85bc6) - Add `api_name` parameter to `gr.Interface`. Additionally, completely hide api page if show_api=False. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5280](https://github.com/gradio-app/gradio/pull/5280) [`a2f42e28`](https://github.com/gradio-app/gradio/commit/a2f42e28bd793bce4bed6d54164bb2a327a46fd5) - Allow updating the label of `gr.UpdateButton`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5112](https://github.com/gradio-app/gradio/pull/5112) [`1cefee7f`](https://github.com/gradio-app/gradio/commit/1cefee7fc05175aca23ba04b3a3fda7b97f49bf0) - chore(deps): update dependency marked to v7. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5260](https://github.com/gradio-app/gradio/pull/5260) [`a773eaf7`](https://github.com/gradio-app/gradio/commit/a773eaf7504abb53b99885b3454dc1e027adbb42) - Stop passing inputs and preprocessing on iterators. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#4943](https://github.com/gradio-app/gradio/pull/4943) [`947d615d`](https://github.com/gradio-app/gradio/commit/947d615db6f76519d0e8bc0d1a0d7edf89df267b) - Sign in with Hugging Face (OAuth support). Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#5298](https://github.com/gradio-app/gradio/pull/5298) [`cf167cd1`](https://github.com/gradio-app/gradio/commit/cf167cd1dd4acd9aee225ff1cb6fac0e849806ba) - Create event listener table for components on docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5173](https://github.com/gradio-app/gradio/pull/5173) [`730f0c1d`](https://github.com/gradio-app/gradio/commit/730f0c1d54792eb11359e40c9f2326e8a6e39203) - Ensure gradio client works as expected for functions that return nothing. Thanks [@raymondtri](https://github.com/raymondtri)!
+- [#5188](https://github.com/gradio-app/gradio/pull/5188) [`b22e1888`](https://github.com/gradio-app/gradio/commit/b22e1888fcf0843520525c1e4b7e1fe73fdeb948) - Fix the images in the theme builder to use permanent URI. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5221](https://github.com/gradio-app/gradio/pull/5221) [`f344592a`](https://github.com/gradio-app/gradio/commit/f344592aeb1658013235ded154107f72d86f24e7) - Allows setting a height to `gr.File` and improves the UI of the component. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5265](https://github.com/gradio-app/gradio/pull/5265) [`06982212`](https://github.com/gradio-app/gradio/commit/06982212dfbd613853133d5d0eebd75577967027) - Removes scrollbar from File preview when not needed. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5305](https://github.com/gradio-app/gradio/pull/5305) [`15075241`](https://github.com/gradio-app/gradio/commit/15075241fa7ad3f7fd9ae2a91e54faf8f19a46f9) - Rotate axes labels on LinePlot, BarPlot, and ScatterPlot. Thanks [@Faiga91](https://github.com/Faiga91)!
+- [#5258](https://github.com/gradio-app/gradio/pull/5258) [`92282cea`](https://github.com/gradio-app/gradio/commit/92282cea6afdf7e9930ece1046d8a63be34b3cea) - Chatbot Avatar Images. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5244](https://github.com/gradio-app/gradio/pull/5244) [`b3e50db9`](https://github.com/gradio-app/gradio/commit/b3e50db92f452f376aa2cc081326d40bb69d6dd7) - Remove aiohttp dependency. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5264](https://github.com/gradio-app/gradio/pull/5264) [`46a2b600`](https://github.com/gradio-app/gradio/commit/46a2b600a7ff030a9ea1560b882b3bf3ad266bbc) - ensure translations for audio work correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#5256](https://github.com/gradio-app/gradio/pull/5256) [`933db53e`](https://github.com/gradio-app/gradio/commit/933db53e93a1229fdf149556d61da5c4c7e1a331) - Better handling of empty dataframe in `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5242](https://github.com/gradio-app/gradio/pull/5242) [`2b397791`](https://github.com/gradio-app/gradio/commit/2b397791fe2059e4beb72937ff0436f2d4d28b4b) - Fix message text overflow onto copy button in `gr.Chatbot`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5253](https://github.com/gradio-app/gradio/pull/5253) [`ddac7e4d`](https://github.com/gradio-app/gradio/commit/ddac7e4d0f55c3bdc6c3e9a9e24588b2563e4049) - Ensure File component uploads files to the server. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5179](https://github.com/gradio-app/gradio/pull/5179) [`6fb92b48`](https://github.com/gradio-app/gradio/commit/6fb92b48a916104db573602011a448b904d42e5e) - Fixes audio streaming issues. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5295](https://github.com/gradio-app/gradio/pull/5295) [`7b8fa8aa`](https://github.com/gradio-app/gradio/commit/7b8fa8aa58f95f5046b9add64b40368bd3f1b700) - Allow caching examples with streamed output. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5285](https://github.com/gradio-app/gradio/pull/5285) [`cdfd4217`](https://github.com/gradio-app/gradio/commit/cdfd42174a9c777eaee9c1209bf8e90d8c7791f2) - Tweaks to `icon` parameter in `gr.Button()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5122](https://github.com/gradio-app/gradio/pull/5122) [`3b805346`](https://github.com/gradio-app/gradio/commit/3b8053469aca6c7a86a6731e641e4400fc34d7d3) - Allows code block in chatbot to scroll horizontally. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5312](https://github.com/gradio-app/gradio/pull/5312) [`f769cb67`](https://github.com/gradio-app/gradio/commit/f769cb67149d8e209091508f06d87014acaed965) - only start listening for events after the components are mounted. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5254](https://github.com/gradio-app/gradio/pull/5254) [`c39f06e1`](https://github.com/gradio-app/gradio/commit/c39f06e16b9feea97984e4822df35a99c807461c) - Fix `.update()` for `gr.Radio()` and `gr.CheckboxGroup()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5231](https://github.com/gradio-app/gradio/pull/5231) [`87f1c2b4`](https://github.com/gradio-app/gradio/commit/87f1c2b4ac7c685c43477215fa5b96b6cbeffa05) - Allow `gr.Interface.from_pipeline()` and `gr.load()` to work within `gr.Blocks()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5238](https://github.com/gradio-app/gradio/pull/5238) [`de23e9f7`](https://github.com/gradio-app/gradio/commit/de23e9f7d67e685e791faf48a21f34121f6d094a) - Improve audio streaming. Thanks [@aliabid94](https://github.com/aliabid94)!/n - Proper audio streaming with WAV files. We now do the proper processing to stream out wav files as a single stream of audio without any cracks in the seams./n - Audio streaming with bytes. Stream any audio type by yielding out bytes, and it should work flawlessly.
+- [#5313](https://github.com/gradio-app/gradio/pull/5313) [`54bcb724`](https://github.com/gradio-app/gradio/commit/54bcb72417b2781ad9d7500ea0f89aa9d80f7d8f) - Restores missing part of bottom border on file component. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5235](https://github.com/gradio-app/gradio/pull/5235) [`1ecf88ac`](https://github.com/gradio-app/gradio/commit/1ecf88ac5f20bc5a1c91792d1a68559575e6afd7) - fix #5229. Thanks [@breengles](https://github.com/breengles)!
+- [#5276](https://github.com/gradio-app/gradio/pull/5276) [`502f1015`](https://github.com/gradio-app/gradio/commit/502f1015bf23b365bc32446dd2e549b0c5d0dc72) - Ensure `Blocks` translation copy renders correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5296](https://github.com/gradio-app/gradio/pull/5296) [`a0f22626`](https://github.com/gradio-app/gradio/commit/a0f22626f2aff297754414bbc83d5c4cfe086ea0) - `make_waveform()` twitter video resolution fix. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 3.40.0
+
+### Highlights
+
+#### Client.predict will now return the final output for streaming endpoints ([#5057](https://github.com/gradio-app/gradio/pull/5057) [`35856f8b`](https://github.com/gradio-app/gradio/commit/35856f8b54548cae7bd3b8d6a4de69e1748283b2))
+
+### This is a breaking change (for gradio_client only)!
+
+Previously, `Client.predict` would only return the first output of an endpoint that streamed results. This was causing confusion for developers that wanted to call these streaming demos via the client.
+
+We realize that developers using the client don't know the internals of whether a demo streams or not, so we're changing the behavior of predict to match developer expectations.
+
+Using `Client.predict` will now return the final output of a streaming endpoint. This will make it even easier to use gradio apps via the client.
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+#### Gradio now supports streaming audio outputs
+
+Allows users to use generators to stream audio out, yielding consecutive chunks of audio. Requires `streaming=True` to be set on the output audio.
+
+```python
+import gradio as gr
+from pydub import AudioSegment
+
+def stream_audio(audio_file):
+ audio = AudioSegment.from_mp3(audio_file)
+ i = 0
+ chunk_size = 3000
+
+ while chunk_size*i < len(audio):
+ chunk = audio[chunk_size*i:chunk_size*(i+1)]
+ i += 1
+ if chunk:
+ file = f"/tmp/{i}.mp3"
+ chunk.export(file, format="mp3")
+ yield file
+
+demo = gr.Interface(
+ fn=stream_audio,
+ inputs=gr.Audio(type="filepath", label="Audio file to stream"),
+ outputs=gr.Audio(autoplay=True, streaming=True),
+)
+
+demo.queue().launch()
+```
+
+From the backend, streamed outputs are served from the `/stream/` endpoint instead of the `/file/` endpoint. Currently just used to serve audio streaming output. The output JSON will have `is_stream`: `true`, instead of `is_file`: `true` in the file data object. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5081](https://github.com/gradio-app/gradio/pull/5081) [`d7f83823`](https://github.com/gradio-app/gradio/commit/d7f83823fbd7604456b0127d689a63eed759807d) - solve how can I config root_path dynamically? #4968. Thanks [@eastonsuo](https://github.com/eastonsuo)!
+- [#5025](https://github.com/gradio-app/gradio/pull/5025) [`6693660a`](https://github.com/gradio-app/gradio/commit/6693660a790996f8f481feaf22a8c49130d52d89) - Add download button to selected images in `Gallery`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5133](https://github.com/gradio-app/gradio/pull/5133) [`61129052`](https://github.com/gradio-app/gradio/commit/61129052ed1391a75c825c891d57fa0ad6c09fc8) - Update dependency esbuild to ^0.19.0. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5125](https://github.com/gradio-app/gradio/pull/5125) [`80be7a1c`](https://github.com/gradio-app/gradio/commit/80be7a1ca44c0adef1668367b2cf36b65e52e576) - chatbot conversation nodes can contain a copy button. Thanks [@fazpu](https://github.com/fazpu)!
+- [#5048](https://github.com/gradio-app/gradio/pull/5048) [`0b74a159`](https://github.com/gradio-app/gradio/commit/0b74a1595b30df744e32a2c358c07acb7fd1cfe5) - Use `importlib` in favor of deprecated `pkg_resources`. Thanks [@jayceslesar](https://github.com/jayceslesar)!
+- [#5045](https://github.com/gradio-app/gradio/pull/5045) [`3b9494f5`](https://github.com/gradio-app/gradio/commit/3b9494f5c57e6b52e6a040ce8d6b5141f780e84d) - Lite: Fix the analytics module to use asyncio to work in the Wasm env. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5046](https://github.com/gradio-app/gradio/pull/5046) [`5244c587`](https://github.com/gradio-app/gradio/commit/5244c5873c355cf3e2f0acb7d67fda3177ef8b0b) - Allow new lines in `HighlightedText` with `/n` and preserve whitespace. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5076](https://github.com/gradio-app/gradio/pull/5076) [`2745075a`](https://github.com/gradio-app/gradio/commit/2745075a26f80e0e16863d483401ff1b6c5ada7a) - Add deploy_discord to docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5116](https://github.com/gradio-app/gradio/pull/5116) [`0dc49b4c`](https://github.com/gradio-app/gradio/commit/0dc49b4c517706f572240f285313a881089ced79) - Add support for async functions and async generators to `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5047](https://github.com/gradio-app/gradio/pull/5047) [`883ac364`](https://github.com/gradio-app/gradio/commit/883ac364f69d92128774ac446ce49bdf8415fd7b) - Add `step` param to `Number`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5137](https://github.com/gradio-app/gradio/pull/5137) [`22aa5eba`](https://github.com/gradio-app/gradio/commit/22aa5eba3fee3f14473e4b0fac29cf72fe31ef04) - Use font size `--text-md` for `` in Chatbot messages. Thanks [@jaywonchung](https://github.com/jaywonchung)!
+- [#5005](https://github.com/gradio-app/gradio/pull/5005) [`f5539c76`](https://github.com/gradio-app/gradio/commit/f5539c7618e31451420bd3228754774da14dc65f) - Enhancement: Add focus event to textbox and number component. Thanks [@JodyZ0203](https://github.com/JodyZ0203)!
+- [#5104](https://github.com/gradio-app/gradio/pull/5104) [`34f6b22e`](https://github.com/gradio-app/gradio/commit/34f6b22efbfedfa569d452f3f99ed2e6593e3c21) - Strip leading and trailing spaces from username in login route. Thanks [@sweep-ai](https://github.com/apps/sweep-ai)!
+- [#5149](https://github.com/gradio-app/gradio/pull/5149) [`144df459`](https://github.com/gradio-app/gradio/commit/144df459a3b7895e524defcfc4c03fbb8b083aca) - Add `show_edit_button` param to `gr.Audio`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5136](https://github.com/gradio-app/gradio/pull/5136) [`eaa1ce14`](https://github.com/gradio-app/gradio/commit/eaa1ce14ac41de1c23321e93f11f1b03a2f3c7f4) - Enhancing Tamil Translation: Language Refinement 🌟. Thanks [@sanjaiyan-dev](https://github.com/sanjaiyan-dev)!
+- [#5035](https://github.com/gradio-app/gradio/pull/5035) [`8b4eb8ca`](https://github.com/gradio-app/gradio/commit/8b4eb8cac9ea07bde31b44e2006ca2b7b5f4de36) - JS Client: Fixes cannot read properties of null (reading 'is_file'). Thanks [@raymondtri](https://github.com/raymondtri)!
+- [#5023](https://github.com/gradio-app/gradio/pull/5023) [`e6317d77`](https://github.com/gradio-app/gradio/commit/e6317d77f87d3dad638acca3dbc4a9228570e63c) - Update dependency extendable-media-recorder to v8. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5085](https://github.com/gradio-app/gradio/pull/5085) [`13e47835`](https://github.com/gradio-app/gradio/commit/13e478353532c4af18cfa50772f8b6fb3c6c9818) - chore(deps): update dependency extendable-media-recorder to v8. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5080](https://github.com/gradio-app/gradio/pull/5080) [`37caa2e0`](https://github.com/gradio-app/gradio/commit/37caa2e0fe95d6cab8beb174580fb557904f137f) - Add icon and link params to `gr.Button`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#5062](https://github.com/gradio-app/gradio/pull/5062) [`7d897165`](https://github.com/gradio-app/gradio/commit/7d89716519d0751072792c9bbda668ffeb597296) - `gr.Dropdown` now has correct behavior in static mode as well as when an option is selected. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5077](https://github.com/gradio-app/gradio/pull/5077) [`667875b2`](https://github.com/gradio-app/gradio/commit/667875b2441753e74d25bd9d3c8adedd8ede11cd) - Live audio streaming output
+- [#5118](https://github.com/gradio-app/gradio/pull/5118) [`1b017e68`](https://github.com/gradio-app/gradio/commit/1b017e68f6a9623cc2ec085bd20e056229552028) - Add `interactive` args to `gr.ColorPicker`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5114](https://github.com/gradio-app/gradio/pull/5114) [`56d2609d`](https://github.com/gradio-app/gradio/commit/56d2609de93387a75dc82b1c06c1240c5b28c0b8) - Reset textbox value to empty string when value is None. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5075](https://github.com/gradio-app/gradio/pull/5075) [`67265a58`](https://github.com/gradio-app/gradio/commit/67265a58027ef1f9e4c0eb849a532f72eaebde48) - Allow supporting >1000 files in `gr.File()` and `gr.UploadButton()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5135](https://github.com/gradio-app/gradio/pull/5135) [`80727bbe`](https://github.com/gradio-app/gradio/commit/80727bbe2c6d631022054edf01515017691b3bdd) - Fix dataset features and dataset preview for HuggingFaceDatasetSaver. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5039](https://github.com/gradio-app/gradio/pull/5039) [`620e4645`](https://github.com/gradio-app/gradio/commit/620e46452729d6d4877b3fab84a65daf2f2b7bc6) - `gr.Dropdown()` now supports values with arbitrary characters and doesn't clear value when re-focused. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5061](https://github.com/gradio-app/gradio/pull/5061) [`136adc9c`](https://github.com/gradio-app/gradio/commit/136adc9ccb23e5cb4d02d2e88f23f0b850041f98) - Ensure `gradio_client` is backwards compatible with `gradio==3.24.1`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5129](https://github.com/gradio-app/gradio/pull/5129) [`97d804c7`](https://github.com/gradio-app/gradio/commit/97d804c748be9acfe27b8369dd2d64d61f43c2e7) - [Spaces] ZeroGPU Queue fix. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5140](https://github.com/gradio-app/gradio/pull/5140) [`cd1353fa`](https://github.com/gradio-app/gradio/commit/cd1353fa3eb1b015f5860ca5d5a8e8d1aa4a831c) - Fixes the display of minutes in the video player. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5111](https://github.com/gradio-app/gradio/pull/5111) [`b84a35b7`](https://github.com/gradio-app/gradio/commit/b84a35b7b91eca947f787648ceb361b1d023427b) - Add icon and link to DuplicateButton. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5030](https://github.com/gradio-app/gradio/pull/5030) [`f6c491b0`](https://github.com/gradio-app/gradio/commit/f6c491b079d335af633dd854c68eb26f9e61c552) - highlightedtext throws an error basing on model. Thanks [@rajeunoia](https://github.com/rajeunoia)!
+
+## 3.39.0
+
+### Highlights
+
+#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
+
+We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
+
+It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
+
+_🦙 Turning Llama 2 70b into a discord bot 🦙_
+
+```python
+import gradio_client as grc
+grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
+```
+
+
+
+#### Getting started with template spaces
+
+To help get you started, we have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) with template spaces you can use to turn state of the art LLMs powered by Gradio to discord bots.
+
+Currently we have template spaces for:
+
+- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
+- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
+- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
+
+But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
+
+❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
+
+Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Features
+
+- [#4995](https://github.com/gradio-app/gradio/pull/4995) [`3f8c210b`](https://github.com/gradio-app/gradio/commit/3f8c210b01ef1ceaaf8ee73be4bf246b5b745bbf) - Implement left and right click in `Gallery` component and show implicit images in `Gallery` grid. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#4993](https://github.com/gradio-app/gradio/pull/4993) [`dc07a9f9`](https://github.com/gradio-app/gradio/commit/dc07a9f947de44b419d8384987a02dcf94977851) - Bringing back the "Add download button for audio" PR by [@leuryr](https://github.com/leuryr). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#4979](https://github.com/gradio-app/gradio/pull/4979) [`44ac8ad0`](https://github.com/gradio-app/gradio/commit/44ac8ad08d82ea12c503dde5c78f999eb0452de2) - Allow setting sketch color default. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#4985](https://github.com/gradio-app/gradio/pull/4985) [`b74f8453`](https://github.com/gradio-app/gradio/commit/b74f8453034328f0e42da8e41785f5eb039b45d7) - Adds `additional_inputs` to `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#4997](https://github.com/gradio-app/gradio/pull/4997) [`41c83070`](https://github.com/gradio-app/gradio/commit/41c83070b01632084e7d29123048a96c1e261407) - Add CSS resets and specifiers to play nice with HF blog. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 3.38
+
+### New Features:
+
+- Provide a parameter `animate` (`False` by default) in `gr.make_waveform()` which animates the overlayed waveform by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4918](https://github.com/gradio-app/gradio/pull/4918)
+- Add `show_download_button` param to allow the download button in static Image components to be hidden by [@hannahblair](https://github.com/hannahblair) in [PR 4959](https://github.com/gradio-app/gradio/pull/4959)
+- Added autofocus argument to Textbox by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
+- The `gr.ChatInterface` UI now converts the "Submit" button to a "Stop" button in ChatInterface while streaming, which can be used to pause generation. By [@abidlabs](https://github.com/abidlabs) in [PR 4971](https://github.com/gradio-app/gradio/pull/4971).
+- Add a `border_color_accent_subdued` theme variable to add a subdued border color to accented items. This is used by chatbot user messages. Set the value of this variable in `Default` theme to `*primary_200`. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4989](https://github.com/gradio-app/gradio/pull/4989)
+- Add default sketch color argument `brush_color`. Also, masks drawn on images are now slightly translucent (and mask color can also be set via brush_color). By [@aliabid94](https://github.com/aliabid94) in [PR 4979](https://github.com/gradio-app/gradio/pull/4979)
+
+### Bug Fixes:
+
+- Fixes `cancels` for generators so that if a generator is canceled before it is complete, subsequent runs of the event do not continue from the previous iteration, but rather start from the beginning. By [@abidlabs](https://github.com/abidlabs) in [PR 4969](https://github.com/gradio-app/gradio/pull/4969).
+- Use `gr.State` in `gr.ChatInterface` to reduce latency by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4976](https://github.com/gradio-app/gradio/pull/4976)
+- Fix bug with `gr.Interface` where component labels inferred from handler parameters were including special args like `gr.Request` or `gr.EventData`. By [@cbensimon](https://github.com/cbensimon) in [PR 4956](https://github.com/gradio-app/gradio/pull/4956)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Other Changes:
+
+- Apply pyright to the `components` directory by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4948](https://github.com/gradio-app/gradio/pull/4948)
+- Improved look of ChatInterface by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
+
+## 3.37
+
+### New Features:
+
+Introducing a new `gr.ChatInterface` abstraction, which allows Gradio users to build fully functioning Chat interfaces very easily. The only required parameter is a chat function `fn`, which accepts a (string) user input `message` and a (list of lists) chat `history` and returns a (string) response. Here's a toy example:
+
+```py
+import gradio as gr
+
+def echo(message, history):
+ return message
+
+demo = gr.ChatInterface(fn=echo, examples=["hello", "hola", "merhaba"], title="Echo Bot")
+demo.launch()
+```
+
+Which produces:
+
+
+
+And a corresponding easy-to-use API at `/chat`:
+
+
+
+The `gr.ChatInterface` abstraction works nicely with various LLM libraries, such as `langchain`. See the [dedicated guide](https://gradio.app/guides/creating-a-chatbot-fast) for more examples using `gr.ChatInterface`. Collective team effort in [PR 4869](https://github.com/gradio-app/gradio/pull/4869)
+
+- Chatbot messages now show hyperlinks to download files uploaded to `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4848](https://github.com/gradio-app/gradio/pull/4848)
+- Cached examples now work with generators and async generators by [@abidlabs](https://github.com/abidlabs) in [PR 4927](https://github.com/gradio-app/gradio/pull/4927)
+- Add RTL support to `gr.Markdown`, `gr.Chatbot`, `gr.Textbox` (via the `rtl` boolean parameter) and text-alignment to `gr.Textbox`(via the string `text_align` parameter) by [@abidlabs](https://github.com/abidlabs) in [PR 4933](https://github.com/gradio-app/gradio/pull/4933)
+
+Examples of usage:
+
+```py
+with gr.Blocks() as demo:
+ gr.Textbox(interactive=True, text_align="right")
+demo.launch()
+```
+
+```py
+with gr.Blocks() as demo:
+ gr.Markdown("سلام", rtl=True)
+demo.launch()
+```
+
+- The `get_api_info` method of `Blocks` now supports layout output components [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
+
+- Added the support for the new command `gradio environment`to make it easier for people to file bug reports if we shipped an easy command to list the OS, gradio version, and versions of gradio/gradio-client dependencies. bu [@varshneydevansh](https://github.com/varshneydevansh) in [PR 4915](https://github.com/gradio-app/gradio/pull/4915).
+
+### Bug Fixes:
+
+- The `.change()` event is fixed in `Video` and `Image` so that it only fires once by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
+- The `.change()` event is fixed in `Audio` so that fires when the component value is programmatically updated by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
+
+* Add missing `display: flex` property to `Row` so that flex styling is applied to children by [@hannahblair] in [PR 4896](https://github.com/gradio-app/gradio/pull/4896)
+* Fixed bug where `gr.Video` could not preprocess urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4904](https://github.com/gradio-app/gradio/pull/4904)
+* Fixed copy button rendering in API page on Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4924](https://github.com/gradio-app/gradio/pull/4924)
+* Fixed `gr.Group` and `container=False`. `container` parameter only available for `Textbox`, `Number`, and `Dropdown`, the only elements where it makes sense. By [@aliabid94](https://github.com/aliabid94) in [PR 4916](https://github.com/gradio-app/gradio/pull/4916)
+* Fixed broken image link in auto-generated `app.py` from `ThemeClass.push_to_hub` by [@deepkyu](https://github.com/deepkyu) in [PR 4944](https://github.com/gradio-app/gradio/pull/4944)
+
+### Other Changes:
+
+- Warning on mobile that if a user leaves the tab, websocket connection may break. On broken connection, tries to rejoin queue and displays error conveying connection broke. By [@aliabid94](https://github.com/aliabid94) in [PR 4742](https://github.com/gradio-app/gradio/pull/4742)
+- Remove blocking network calls made before the local URL gets printed - these slow down the display of the local URL, especially when no internet is available. [@aliabid94](https://github.com/aliabid94) in [PR 4905](https://github.com/gradio-app/gradio/pull/4905).
+- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
+- Queue `max_size` defaults to parent Blocks `max_thread` when running on Spaces with ZeroGPU hardware. By [@cbensimon](https://github.com/cbensimon) in [PR 4937](https://github.com/gradio-app/gradio/pull/4937)
+
+### Breaking Changes:
+
+Motivated by the release of `pydantic==2.0`, which included breaking changes that broke a large number of Gradio apps, we've pinned many gradio dependencies. Note that pinned dependencies can cause downstream conflicts, so this may be a breaking change. That being said, we've kept the pins pretty loose, and we're expecting change to be better for the long-term stability of Gradio apps.
+
+## 3.36.1
+
+### New Features:
+
+- Hotfix to support pydantic v1 and v2 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4835](https://github.com/gradio-app/gradio/pull/4835)
+
+### Bug Fixes:
+
+- Fix bug where `gr.File` change event was not triggered when the value was changed by another event by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4811](https://github.com/gradio-app/gradio/pull/4811)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.36.0
+
+### New Features:
+
+- The `gr.Video`, `gr.Audio`, `gr.Image`, `gr.Chatbot`, and `gr.Gallery` components now include a share icon when deployed on Spaces. This behavior can be modified by setting the `show_share_button` parameter in the component classes. by [@aliabid94](https://github.com/aliabid94) in [PR 4651](https://github.com/gradio-app/gradio/pull/4651)
+- Allow the web component `space`, `src`, and `host` attributes to be updated dynamically by [@pngwn](https://github.com/pngwn) in [PR 4461](https://github.com/gradio-app/gradio/pull/4461)
+- Suggestion for Spaces Duplication built into Gradio, by [@aliabid94](https://github.com/aliabid94) in [PR 4458](https://github.com/gradio-app/gradio/pull/4458)
+- The `api_name` parameter now accepts `False` as a value, which means it does not show up in named or unnamed endpoints. By [@abidlabs](https://github.com/aliabid94) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+- Added support for `pathlib.Path` in `gr.Video`, `gr.Gallery`, and `gr.Chatbot` by [sunilkumardash9](https://github.com/sunilkumardash9) in [PR 4581](https://github.com/gradio-app/gradio/pull/4581).
+
+### Bug Fixes:
+
+- Updated components with `info` attribute to update when `update()` is called on them. by [@jebarpg](https://github.com/jebarpg) in [PR 4715](https://github.com/gradio-app/gradio/pull/4715).
+- Ensure the `Image` components undo button works mode is `mask` or `color-sketch` by [@amyorz](https://github.com/AmyOrz) in [PR 4692](https://github.com/gradio-app/gradio/pull/4692)
+- Load the iframe resizer external asset asynchronously, by [@akx](https://github.com/akx) in [PR 4336](https://github.com/gradio-app/gradio/pull/4336)
+- Restored missing imports in `gr.components` by [@abidlabs](https://github.com/abidlabs) in [PR 4566](https://github.com/gradio-app/gradio/pull/4566)
+- Fix bug where `select` event was not triggered in `gr.Gallery` if `height` was set to be large with `allow_preview=False` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4551](https://github.com/gradio-app/gradio/pull/4551)
+- Fix bug where setting `visible=False` in `gr.Group` event did not work by [@abidlabs](https://github.com/abidlabs) in [PR 4567](https://github.com/gradio-app/gradio/pull/4567)
+- Fix `make_waveform` to work with paths that contain spaces [@akx](https://github.com/akx) in [PR 4570](https://github.com/gradio-app/gradio/pull/4570) & [PR 4578](https://github.com/gradio-app/gradio/pull/4578)
+- Send captured data in `stop_recording` event for `gr.Audio` and `gr.Video` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4554](https://github.com/gradio-app/gradio/pull/4554)
+- Fix bug in `gr.Gallery` where `height` and `object_fit` parameters where being ignored by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4576](https://github.com/gradio-app/gradio/pull/4576)
+- Fixes an HTML sanitization issue in DOMPurify where links in markdown were not opening in a new window by [@hannahblair] in [PR 4577](https://github.com/gradio-app/gradio/pull/4577)
+- Fixed Dropdown height rendering in Columns by [@aliabid94](https://github.com/aliabid94) in [PR 4584](https://github.com/gradio-app/gradio/pull/4584)
+- Fixed bug where `AnnotatedImage` css styling was causing the annotation masks to not be displayed correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4628](https://github.com/gradio-app/gradio/pull/4628)
+- Ensure that Gradio does not silently fail when running on a port that is occupied by [@abidlabs](https://github.com/abidlabs) in [PR 4624](https://github.com/gradio-app/gradio/pull/4624).
+- Fix double upload bug that caused lag in file uploads by [@aliabid94](https://github.com/aliabid94) in [PR 4661](https://github.com/gradio-app/gradio/pull/4661)
+- `Progress` component now appears even when no `iterable` is specified in `tqdm` constructor by [@itrushkin](https://github.com/itrushkin) in [PR 4475](https://github.com/gradio-app/gradio/pull/4475)
+- Deprecation warnings now point at the user code using those deprecated features, instead of Gradio internals, by (https://github.com/akx) in [PR 4694](https://github.com/gradio-app/gradio/pull/4694)
+- Adapt column widths in gr.Examples based on content by [@pngwn](https://github.com/pngwn) & [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4700](https://github.com/gradio-app/gradio/pull/4700)
+- The `plot` parameter deprecation warnings should now only be emitted for `Image` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
+- Removed uncessessary `type` deprecation warning by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
+- Ensure Audio autoplays works when `autoplay=True` and the video source is dynamically updated [@pngwn](https://github.com/pngwn) in [PR 4705](https://github.com/gradio-app/gradio/pull/4705)
+- When an error modal is shown in spaces, ensure we scroll to the top so it can be seen by [@pngwn](https://github.com/pngwn) in [PR 4712](https://github.com/gradio-app/gradio/pull/4712)
+- Update depedencies by [@pngwn](https://github.com/pngwn) in [PR 4675](https://github.com/gradio-app/gradio/pull/4675)
+- Fixes `gr.Dropdown` being cutoff at the bottom by [@abidlabs](https://github.com/abidlabs) in [PR 4691](https://github.com/gradio-app/gradio/pull/4691).
+- Scroll top when clicking "View API" in spaces by [@pngwn](https://github.com/pngwn) in [PR 4714](https://github.com/gradio-app/gradio/pull/4714)
+- Fix bug where `show_label` was hiding the entire component for `gr.Label` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4713](https://github.com/gradio-app/gradio/pull/4713)
+- Don't crash when uploaded image has broken EXIF data, by [@akx](https://github.com/akx) in [PR 4764](https://github.com/gradio-app/gradio/pull/4764)
+- Place toast messages at the top of the screen by [@pngwn](https://github.com/pngwn) in [PR 4796](https://github.com/gradio-app/gradio/pull/4796)
+- Fix regressed styling of Login page when auth is enabled by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4797](https://github.com/gradio-app/gradio/pull/4797)
+- Prevent broken scrolling to output on Spaces by [@aliabid94](https://github.com/aliabid94) in [PR 4822](https://github.com/gradio-app/gradio/pull/4822)
+
+### Other Changes:
+
+- Add `.git-blame-ignore-revs` by [@akx](https://github.com/akx) in [PR 4586](https://github.com/gradio-app/gradio/pull/4586)
+- Update frontend dependencies in [PR 4601](https://github.com/gradio-app/gradio/pull/4601)
+- Use `typing.Literal` where possible in gradio library and client by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4608](https://github.com/gradio-app/gradio/pull/4608)
+- Remove unnecessary mock json files for frontend E2E tests by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4625](https://github.com/gradio-app/gradio/pull/4625)
+- Update dependencies by [@pngwn](https://github.com/pngwn) in [PR 4643](https://github.com/gradio-app/gradio/pull/4643)
+- The theme builder now launches successfully, and the API docs are cleaned up. By [@abidlabs](https://github.com/aliabid94) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+- Remove `cleared_value` from some components as its no longer used internally by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4685](https://github.com/gradio-app/gradio/pull/4685)
+- Better errors when you define two Blocks and reference components in one Blocks from the events in the other Blocks [@abidlabs](https://github.com/abidlabs) in [PR 4738](https://github.com/gradio-app/gradio/pull/4738).
+- Better message when share link is not created by [@abidlabs](https://github.com/abidlabs) in [PR 4773](https://github.com/gradio-app/gradio/pull/4773).
+- Improve accessibility around selected images in gr.Gallery component by [@hannahblair](https://github.com/hannahblair) in [PR 4790](https://github.com/gradio-app/gradio/pull/4790)
+
+### Breaking Changes:
+
+[PR 4683](https://github.com/gradio-app/gradio/pull/4683) removes the explict named endpoint "load_examples" from gr.Interface that was introduced in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).
+
+## 3.35.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix chatbot streaming by [@aliabid94](https://github.com/aliabid94) in [PR 4537](https://github.com/gradio-app/gradio/pull/4537)
+- Fix chatbot height and scrolling by [@aliabid94](https://github.com/aliabid94) in [PR 4540](https://github.com/gradio-app/gradio/pull/4540)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.35.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix chatbot streaming by [@aliabid94](https://github.com/aliabid94) in [PR 4537](https://github.com/gradio-app/gradio/pull/4537)
+- Fix error modal position and text size by [@pngwn](https://github.com/pngwn) in [PR 4538](https://github.com/gradio-app/gradio/pull/4538).
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.35.0
+
+### New Features:
+
+- A `gr.ClearButton` which allows users to easily clear the values of components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)
+
+Example usage:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot([("Hello", "How are you?")])
+ with gr.Row():
+ textbox = gr.Textbox(scale=3, interactive=True)
+ gr.ClearButton([textbox, chatbot], scale=1)
+
+demo.launch()
+```
+
+- Min and max value for gr.Number by [@artegoser](https://github.com/artegoser) and [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3991](https://github.com/gradio-app/gradio/pull/3991)
+- Add `start_recording` and `stop_recording` events to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4422](https://github.com/gradio-app/gradio/pull/4422)
+- Allow any function to generate an error message and allow multiple messages to appear at a time. Other error modal improvements such as auto dismiss after a time limit and a new layout on mobile [@pngwn](https://github.com/pngwn) in [PR 4459](https://github.com/gradio-app/gradio/pull/4459).
+- Add `autoplay` kwarg to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4453](https://github.com/gradio-app/gradio/pull/4453)
+- Add `allow_preview` parameter to `Gallery` to control whether a detailed preview is displayed on click by
+ [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4470](https://github.com/gradio-app/gradio/pull/4470)
+- Add `latex_delimiters` parameter to `Chatbot` to control the delimiters used for LaTeX and to disable LaTeX in the `Chatbot` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4516](https://github.com/gradio-app/gradio/pull/4516)
+- Can now issue `gr.Warning` and `gr.Info` modals. Simply put the code `gr.Warning("Your warning message")` or `gr.Info("Your info message")` as a standalone line in your function. By [@aliabid94](https://github.com/aliabid94) in [PR 4518](https://github.com/gradio-app/gradio/pull/4518).
+
+Example:
+
+```python
+def start_process(name):
+ gr.Info("Starting process")
+ if name is None:
+ gr.Warning("Name is empty")
+ ...
+ if success == False:
+ raise gr.Error("Process failed")
+```
+
+### Bug Fixes:
+
+- Add support for PAUSED state in the JS client by [@abidlabs](https://github.com/abidlabs) in [PR 4438](https://github.com/gradio-app/gradio/pull/4438)
+- Ensure Tabs only occupy the space required by [@pngwn](https://github.com/pngwn) in [PR 4419](https://github.com/gradio-app/gradio/pull/4419)
+- Ensure components have the correct empty sizes to prevent empty containers from collapsing by [@pngwn](https://github.com/pngwn) in [PR 4447](https://github.com/gradio-app/gradio/pull/4447).
+- Frontend code no longer crashes when there is a relative URL in an `` element, by [@akx](https://github.com/akx) in [PR 4449](https://github.com/gradio-app/gradio/pull/4449).
+- Fix bug where setting `format='mp4'` on a video component would cause the function to error out if the uploaded video was not playable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4467](https://github.com/gradio-app/gradio/pull/4467)
+- Fix `_js` parameter to work even without backend function, by [@aliabid94](https://github.com/aliabid94) in [PR 4486](https://github.com/gradio-app/gradio/pull/4486).
+- Fix new line issue with `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4491](https://github.com/gradio-app/gradio/pull/4491)
+- Fixes issue with Clear button not working for `Label` component by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)
+- Restores the ability to pass in a tuple (sample rate, audio array) to gr.Audio() by [@abidlabs](https://github.com/abidlabs) in [PR 4525](https://github.com/gradio-app/gradio/pull/4525)
+- Ensure code is correctly formatted and copy button is always present in Chatbot by [@pngwn](https://github.com/pngwn) in [PR 4527](https://github.com/gradio-app/gradio/pull/4527)
+- `show_label` will not automatically be set to `True` in `gr.BarPlot.update` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4531](https://github.com/gradio-app/gradio/pull/4531)
+- `gr.BarPlot` group text now respects darkmode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4531](https://github.com/gradio-app/gradio/pull/4531)
+- Fix dispatched errors from within components [@aliabid94](https://github.com/aliabid94) in [PR 4786](https://github.com/gradio-app/gradio/pull/4786)
+
+### Other Changes:
+
+- Change styling of status and toast error components by [@hannahblair](https://github.com/hannahblair) in [PR 4454](https://github.com/gradio-app/gradio/pull/4454).
+- Clean up unnecessary `new Promise()`s by [@akx](https://github.com/akx) in [PR 4442](https://github.com/gradio-app/gradio/pull/4442).
+- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
+- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
+- Add Catalan translation [@jordimas](https://github.com/jordimas) in [PR 4483](https://github.com/gradio-app/gradio/pull/4483).
+- The API endpoint that loads examples upon click has been given an explicit name ("/load_examples") by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).
+- Allows configuration of FastAPI app when calling `mount_gradio_app`, by [@charlesfrye](https://github.com/charlesfrye) in [PR4519](https://github.com/gradio-app/gradio/pull/4519).
+
+### Breaking Changes:
+
+- The behavior of the `Clear` button has been changed for `Slider`, `CheckboxGroup`, `Radio`, `Dropdown` components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456). The Clear button now sets the value of these components to be empty as opposed to the original default set by the developer. This is to make them in line with the rest of the Gradio components.
+- Python 3.7 end of life is June 27 2023. Gradio will no longer support python 3.7 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4484](https://github.com/gradio-app/gradio/pull/4484)
+- Removed `$` as a default LaTeX delimiter for the `Chatbot` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4516](https://github.com/gradio-app/gradio/pull/4516). The specific LaTeX delimeters can be set using the new `latex_delimiters` parameter in `Chatbot`.
+
+## 3.34.0
+
+### New Features:
+
+- The `gr.UploadButton` component now supports the `variant` and `interactive` parameters by [@abidlabs](https://github.com/abidlabs) in [PR 4436](https://github.com/gradio-app/gradio/pull/4436).
+
+### Bug Fixes:
+
+- Remove target="\_blank" override on anchor tags with internal targets by [@hannahblair](https://github.com/hannahblair) in [PR 4405](https://github.com/gradio-app/gradio/pull/4405)
+- Fixed bug where `gr.File(file_count='multiple')` could not be cached as output by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4421](https://github.com/gradio-app/gradio/pull/4421)
+- Restricts the domains that can be proxied via `/proxy` route by [@abidlabs](https://github.com/abidlabs) in [PR 4406](https://github.com/gradio-app/gradio/pull/4406).
+- Fixes issue where `gr.UploadButton` could not be used to upload the same file twice by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4437](https://github.com/gradio-app/gradio/pull/4437)
+- Fixes bug where `/proxy` route was being incorrectly constructed by the frontend by [@abidlabs](https://github.com/abidlabs) in [PR 4430](https://github.com/gradio-app/gradio/pull/4430).
+- Fix z-index of status component by [@hannahblair](https://github.com/hannahblair) in [PR 4429](https://github.com/gradio-app/gradio/pull/4429)
+- Fix video rendering in Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4433](https://github.com/gradio-app/gradio/pull/4433).
+- The output directory for files downloaded when calling Blocks as a function is now set to a temporary directory by default (instead of the working directory in some cases) by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Other Changes:
+
+- When running on Spaces, handler functions will be transformed by the [PySpaces](https://pypi.org/project/spaces/) library in order to make them work with specific hardware. It will have no effect on standalone Gradio apps or regular Gradio Spaces and can be globally deactivated as follows : `import spaces; spaces.disable_gradio_auto_wrap()` by [@cbensimon](https://github.com/cbensimon) in [PR 4389](https://github.com/gradio-app/gradio/pull/4389).
+- Deprecated `.style` parameter and moved arguments to constructor. Added support for `.update()` to all arguments initially in style. Added `scale` and `min_width` support to every Component. By [@aliabid94](https://github.com/aliabid94) in [PR 4374](https://github.com/gradio-app/gradio/pull/4374)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.33.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Allow `every` to work with generators by [@dkjshk](https://github.com/dkjshk) in [PR 4434](https://github.com/gradio-app/gradio/pull/4434)
+- Fix z-index of status component by [@hannahblair](https://github.com/hannahblair) in [PR 4429](https://github.com/gradio-app/gradio/pull/4429)
+- Allow gradio to work offline, by [@aliabid94](https://github.com/aliabid94) in [PR 4398](https://github.com/gradio-app/gradio/pull/4398).
+- Fixed `validate_url` to check for 403 errors and use a GET request in place of a HEAD by [@alvindaiyan](https://github.com/alvindaiyan) in [PR 4388](https://github.com/gradio-app/gradio/pull/4388).
+
+### Other Changes:
+
+- More explicit error message when share link binary is blocked by antivirus by [@abidlabs](https://github.com/abidlabs) in [PR 4380](https://github.com/gradio-app/gradio/pull/4380).
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.33.0
+
+### New Features:
+
+- Introduced `gradio deploy` to launch a Gradio app to Spaces directly from your terminal. By [@aliabid94](https://github.com/aliabid94) in [PR 4033](https://github.com/gradio-app/gradio/pull/4033).
+- Introduce `show_progress='corner'` argument to event listeners, which will not cover the output components with the progress animation, but instead show it in the corner of the components. By [@aliabid94](https://github.com/aliabid94) in [PR 4396](https://github.com/gradio-app/gradio/pull/4396).
+
+### Bug Fixes:
+
+- Fix bug where Label change event was triggering itself by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4371](https://github.com/gradio-app/gradio/pull/4371)
+- Make `Blocks.load` behave like other event listeners (allows chaining `then` off of it) [@anentropic](https://github.com/anentropic/) in [PR 4304](https://github.com/gradio-app/gradio/pull/4304)
+- Respect `interactive=True` in output components of a `gr.Interface` by [@abidlabs](https://github.com/abidlabs) in [PR 4356](https://github.com/gradio-app/gradio/pull/4356).
+- Remove unused frontend code by [@akx](https://github.com/akx) in [PR 4275](https://github.com/gradio-app/gradio/pull/4275)
+- Fixes favicon path on Windows by [@abidlabs](https://github.com/abidlabs) in [PR 4369](https://github.com/gradio-app/gradio/pull/4369).
+- Prevent path traversal in `/file` routes by [@abidlabs](https://github.com/abidlabs) in [PR 4370](https://github.com/gradio-app/gradio/pull/4370).
+- Do not send HF token to other domains via `/proxy` route by [@abidlabs](https://github.com/abidlabs) in [PR 4368](https://github.com/gradio-app/gradio/pull/4368).
+- Replace default `markedjs` sanitize function with DOMPurify sanitizer for `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4360](https://github.com/gradio-app/gradio/pull/4360)
+- Prevent the creation of duplicate copy buttons in the chatbot and ensure copy buttons work in non-secure contexts by [@binary-husky](https://github.com/binary-husky) in [PR 4350](https://github.com/gradio-app/gradio/pull/4350).
+
+### Other Changes:
+
+- Remove flicker of loading bar by adding opacity transition, by [@aliabid94](https://github.com/aliabid94) in [PR 4349](https://github.com/gradio-app/gradio/pull/4349).
+- Performance optimization in the frontend's Blocks code by [@akx](https://github.com/akx) in [PR 4334](https://github.com/gradio-app/gradio/pull/4334)
+- Upgrade the pnpm lock file format version from v6.0 to v6.1 by [@whitphx](https://github.com/whitphx) in [PR 4393](https://github.com/gradio-app/gradio/pull/4393)
+
+### Breaking Changes:
+
+- The `/file=` route no longer allows accessing dotfiles or files in "dot directories" by [@akx](https://github.com/akx) in [PR 4303](https://github.com/gradio-app/gradio/pull/4303)
+
+## 3.32.0
+
+### New Features:
+
+- `Interface.launch()` and `Blocks.launch()` now accept an `app_kwargs` argument to allow customizing the configuration of the underlying FastAPI app, by [@akx](https://github.com/akx) in [PR 4282](https://github.com/gradio-app/gradio/pull/4282)
+
+### Bug Fixes:
+
+- Fixed Gallery/AnnotatedImage components not respecting GRADIO_DEFAULT_DIR variable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed Gallery/AnnotatedImage components resaving identical images by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed Audio/Video/File components creating empty tempfiles on each run by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed the behavior of the `run_on_click` parameter in `gr.Examples` by [@abidlabs](https://github.com/abidlabs) in [PR 4258](https://github.com/gradio-app/gradio/pull/4258).
+- Ensure error modal displays when the queue is enabled by [@pngwn](https://github.com/pngwn) in [PR 4273](https://github.com/gradio-app/gradio/pull/4273)
+- Ensure js client respcts the full root when making requests to the server by [@pngwn](https://github.com/pngwn) in [PR 4271](https://github.com/gradio-app/gradio/pull/4271)
+
+### Other Changes:
+
+- Refactor web component `initial_height` attribute by [@whitphx](https://github.com/whitphx) in [PR 4223](https://github.com/gradio-app/gradio/pull/4223)
+- Relocate `mount_css` fn to remove circular dependency [@whitphx](https://github.com/whitphx) in [PR 4222](https://github.com/gradio-app/gradio/pull/4222)
+- Upgrade Black to 23.3 by [@akx](https://github.com/akx) in [PR 4259](https://github.com/gradio-app/gradio/pull/4259)
+- Add frontend LaTeX support in `gr.Chatbot()` using `KaTeX` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4285](https://github.com/gradio-app/gradio/pull/4285).
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.31.0
+
+### New Features:
+
+- The reloader command (`gradio app.py`) can now accept command line arguments by [@micky2be](https://github.com/micky2be) in [PR 4119](https://github.com/gradio-app/gradio/pull/4119)
+- Added `format` argument to `Audio` component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4178](https://github.com/gradio-app/gradio/pull/4178)
+- Add JS client code snippets to use via api page by [@aliabd](https://github.com/aliabd) in [PR 3927](https://github.com/gradio-app/gradio/pull/3927).
+- Update to the JS client by [@pngwn](https://github.com/pngwn) in [PR 4202](https://github.com/gradio-app/gradio/pull/4202)
+
+### Bug Fixes:
+
+- Fix "TypeError: issubclass() arg 1 must be a class" When use Optional[Types] by [@lingfengchencn](https://github.com/lingfengchencn) in [PR 4200](https://github.com/gradio-app/gradio/pull/4200).
+- Gradio will no longer send any analytics or call home if analytics are disabled with the GRADIO_ANALYTICS_ENABLED environment variable. By [@akx](https://github.com/akx) in [PR 4194](https://github.com/gradio-app/gradio/pull/4194) and [PR 4236](https://github.com/gradio-app/gradio/pull/4236)
+- The deprecation warnings for kwargs now show the actual stack level for the invocation, by [@akx](https://github.com/akx) in [PR 4203](https://github.com/gradio-app/gradio/pull/4203).
+- Fix "TypeError: issubclass() arg 1 must be a class" When use Optional[Types] by [@lingfengchencn](https://github.com/lingfengchencn) in [PR 4200](https://github.com/gradio-app/gradio/pull/4200).
+- Ensure cancelling functions work correctly by [@pngwn](https://github.com/pngwn) in [PR 4225](https://github.com/gradio-app/gradio/pull/4225)
+- Fixes a bug with typing.get_type_hints() on Python 3.9 by [@abidlabs](https://github.com/abidlabs) in [PR 4228](https://github.com/gradio-app/gradio/pull/4228).
+- Fixes JSONDecodeError by [@davidai](https://github.com/davidai) in [PR 4241](https://github.com/gradio-app/gradio/pull/4241)
+- Fix `chatbot_dialogpt` demo by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4238](https://github.com/gradio-app/gradio/pull/4238).
+
+### Other Changes:
+
+- Change `gr.Chatbot()` markdown parsing to frontend using `marked` library and `prism` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4150](https://github.com/gradio-app/gradio/pull/4150)
+- Update the js client by [@pngwn](https://github.com/pngwn) in [PR 3899](https://github.com/gradio-app/gradio/pull/3899)
+- Fix documentation for the shape of the numpy array produced by the `Image` component by [@der3318](https://github.com/der3318) in [PR 4204](https://github.com/gradio-app/gradio/pull/4204).
+- Updates the timeout for websocket messaging from 1 second to 5 seconds by [@abidlabs](https://github.com/abidlabs) in [PR 4235](https://github.com/gradio-app/gradio/pull/4235)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.30.0
+
+### New Features:
+
+- Adds a `root_path` parameter to `launch()` that allows running Gradio applications on subpaths (e.g. www.example.com/app) behind a proxy, by [@abidlabs](https://github.com/abidlabs) in [PR 4133](https://github.com/gradio-app/gradio/pull/4133)
+- Fix dropdown change listener to trigger on change when updated as an output by [@aliabid94](https://github.com/aliabid94) in [PR 4128](https://github.com/gradio-app/gradio/pull/4128).
+- Add `.input` event listener, which is only triggered when a user changes the component value (as compared to `.change`, which is also triggered when a component updates as the result of a function trigger), by [@aliabid94](https://github.com/aliabid94) in [PR 4157](https://github.com/gradio-app/gradio/pull/4157).
+
+### Bug Fixes:
+
+- Records username when flagging by [@abidlabs](https://github.com/abidlabs) in [PR 4135](https://github.com/gradio-app/gradio/pull/4135)
+- Fix website build issue by [@aliabd](https://github.com/aliabd) in [PR 4142](https://github.com/gradio-app/gradio/pull/4142)
+- Fix lang agnostic type info for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.29.0
+
+### New Features:
+
+- Returning language agnostic types in the `/info` route by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4039](https://github.com/gradio-app/gradio/pull/4039)
+
+### Bug Fixes:
+
+- Allow users to upload audio files in Audio component on iOS by by [@aliabid94](https://github.com/aliabid94) in [PR 4071](https://github.com/gradio-app/gradio/pull/4071).
+- Fixes the gradio theme builder error that appeared on launch by [@aliabid94](https://github.com/aliabid94) and [@abidlabs](https://github.com/abidlabs) in [PR 4080](https://github.com/gradio-app/gradio/pull/4080)
+- Keep Accordion content in DOM by [@aliabid94](https://github.com/aliabid94) in [PR 4070](https://github.com/gradio-app/gradio/pull/4073)
+- Fixed bug where type hints in functions caused the event handler to crash by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4068](https://github.com/gradio-app/gradio/pull/4068)
+- Fix dropdown default value not appearing by [@aliabid94](https://github.com/aliabid94) in [PR 4072](https://github.com/gradio-app/gradio/pull/4072).
+- Soft theme label color fix by [@aliabid94](https://github.com/aliabid94) in [PR 4070](https://github.com/gradio-app/gradio/pull/4070)
+- Fix `gr.Slider` `release` event not triggering on mobile by [@space-nuko](https://github.com/space-nuko) in [PR 4098](https://github.com/gradio-app/gradio/pull/4098)
+- Removes extraneous `State` component info from the `/info` route by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+- Make .then() work even if first event fails by [@aliabid94](https://github.com/aliabid94) in [PR 4115](https://github.com/gradio-app/gradio/pull/4115).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Allow users to submit with enter in Interfaces with textbox / number inputs [@aliabid94](https://github.com/aliabid94) in [PR 4090](https://github.com/gradio-app/gradio/pull/4090).
+- Updates gradio's requirements.txt to requires uvicorn>=0.14.0 by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+- Updates some error messaging by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+- Renames simplified Chinese translation file from `zh-cn.json` to `zh-CN.json` by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes issue with indentation in `gr.Code()` component with streaming by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4043](https://github.com/gradio-app/gradio/pull/4043)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.2
+
+### Bug Fixes
+
+- Code component visual updates by [@pngwn](https://github.com/pngwn) in [PR 4051](https://github.com/gradio-app/gradio/pull/4051)
+
+### New Features:
+
+- Add support for `visual-question-answering`, `document-question-answering`, and `image-to-text` using `gr.Interface.load("models/...")` and `gr.Interface.from_pipeline` by [@osanseviero](https://github.com/osanseviero) in [PR 3887](https://github.com/gradio-app/gradio/pull/3887)
+- Add code block support in `gr.Chatbot()`, by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4048](https://github.com/gradio-app/gradio/pull/4048)
+- Adds the ability to blocklist filepaths (and also improves the allowlist mechanism) by [@abidlabs](https://github.com/abidlabs) in [PR 4047](https://github.com/gradio-app/gradio/pull/4047).
+- Adds the ability to specify the upload directory via an environment variable by [@abidlabs](https://github.com/abidlabs) in [PR 4047](https://github.com/gradio-app/gradio/pull/4047).
+
+### Bug Fixes:
+
+- Fixes issue with `matplotlib` not rendering correctly if the backend was not set to `Agg` by [@abidlabs](https://github.com/abidlabs) in [PR 4029](https://github.com/gradio-app/gradio/pull/4029)
+- Fixes bug where rendering the same `gr.State` across different Interfaces/Blocks within larger Blocks would not work by [@abidlabs](https://github.com/abidlabs) in [PR 4030](https://github.com/gradio-app/gradio/pull/4030)
+- Code component visual updates by [@pngwn](https://github.com/pngwn) in [PR 4051](https://github.com/gradio-app/gradio/pull/4051)
+
+### Documentation Changes:
+
+- Adds a Guide on how to use the Python Client within a FastAPI app, by [@abidlabs](https://github.com/abidlabs) in [PR 3892](https://github.com/gradio-app/gradio/pull/3892)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+- `gr.HuggingFaceDatasetSaver` behavior changed internally. The `flagging/` folder is not a `.git/` folder anymore when using it. `organization` parameter is now ignored in favor of passing a full dataset id as `dataset_name` (e.g. `"username/my-dataset"`).
+- New lines (`\n`) are not automatically converted to ` ` in `gr.Markdown()` or `gr.Chatbot()`. For multiple new lines, a developer must add multiple ` ` tags.
+
+### Full Changelog:
+
+- Safer version of `gr.HuggingFaceDatasetSaver` using HTTP methods instead of git pull/push by [@Wauplin](https://github.com/Wauplin) in [PR 3973](https://github.com/gradio-app/gradio/pull/3973)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.1
+
+### New Features:
+
+- Add a "clear mask" button to `gr.Image` sketch modes, by [@space-nuko](https://github.com/space-nuko) in [PR 3615](https://github.com/gradio-app/gradio/pull/3615)
+
+### Bug Fixes:
+
+- Fix dropdown default value not appearing by [@aliabid94](https://github.com/aliabid94) in [PR 3996](https://github.com/gradio-app/gradio/pull/3996).
+- Fix faded coloring of output textboxes in iOS / Safari by [@aliabid94](https://github.com/aliabid94) in [PR 3993](https://github.com/gradio-app/gradio/pull/3993)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+- CI: Simplified Python CI workflow by [@akx](https://github.com/akx) in [PR 3982](https://github.com/gradio-app/gradio/pull/3982)
+- Upgrade pyright to 1.1.305 by [@akx](https://github.com/akx) in [PR 4042](https://github.com/gradio-app/gradio/pull/4042)
+- More Ruff rules are enabled and lint errors fixed by [@akx](https://github.com/akx) in [PR 4038](https://github.com/gradio-app/gradio/pull/4038)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.0
+
+### Bug Fixes:
+
+- Fix duplicate play commands in full-screen mode of 'video'. by [@tomchang25](https://github.com/tomchang25) in [PR 3968](https://github.com/gradio-app/gradio/pull/3968).
+- Fix the issue of the UI stuck caused by the 'selected' of DataFrame not being reset. by [@tomchang25](https://github.com/tomchang25) in [PR 3916](https://github.com/gradio-app/gradio/pull/3916).
+- Fix issue where `gr.Video()` would not work inside a `gr.Tab()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3891](https://github.com/gradio-app/gradio/pull/3891)
+- Fixed issue with old_value check in File. by [@tomchang25](https://github.com/tomchang25) in [PR 3859](https://github.com/gradio-app/gradio/pull/3859).
+- Fixed bug where all bokeh plots appeared in the same div by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3896](https://github.com/gradio-app/gradio/pull/3896)
+- Fixed image outputs to automatically take full output image height, unless explicitly set, by [@aliabid94](https://github.com/aliabid94) in [PR 3905](https://github.com/gradio-app/gradio/pull/3905)
+- Fix issue in `gr.Gallery()` where setting height causes aspect ratio of images to collapse by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3830](https://github.com/gradio-app/gradio/pull/3830)
+- Fix issue where requesting for a non-existing file would trigger a 500 error by [@micky2be](https://github.com/micky2be) in `[PR 3895](https://github.com/gradio-app/gradio/pull/3895)`.
+- Fix bugs with abspath about symlinks, and unresolvable path on Windows by [@micky2be](https://github.com/micky2be) in `[PR 3895](https://github.com/gradio-app/gradio/pull/3895)`.
+- Fixes type in client `Status` enum by [@10zinten](https://github.com/10zinten) in [PR 3931](https://github.com/gradio-app/gradio/pull/3931)
+- Fix `gr.ChatBot` to handle image url [tye-singwa](https://github.com/tye-signwa) in [PR 3953](https://github.com/gradio-app/gradio/pull/3953)
+- Move Google Tag Manager related initialization code to analytics-enabled block by [@akx](https://github.com/akx) in [PR 3956](https://github.com/gradio-app/gradio/pull/3956)
+- Fix bug where port was not reused if the demo was closed and then re-launched by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3896](https://github.com/gradio-app/gradio/pull/3959)
+- Fixes issue where dropdown does not position itself at selected element when opened [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3639](https://github.com/gradio-app/gradio/pull/3639)
+
+### Documentation Changes:
+
+- Make use of `gr` consistent across the docs by [@duerrsimon](https://github.com/duerrsimon) in [PR 3901](https://github.com/gradio-app/gradio/pull/3901)
+- Fixed typo in theming-guide.md by [@eltociear](https://github.com/eltociear) in [PR 3952](https://github.com/gradio-app/gradio/pull/3952)
+
+### Testing and Infrastructure Changes:
+
+- CI: Python backend lint is only run once, by [@akx](https://github.com/akx) in [PR 3960](https://github.com/gradio-app/gradio/pull/3960)
+- Format invocations and concatenations were replaced by f-strings where possible by [@akx](https://github.com/akx) in [PR 3984](https://github.com/gradio-app/gradio/pull/3984)
+- Linting rules were made more strict and issues fixed by [@akx](https://github.com/akx) in [PR 3979](https://github.com/gradio-app/gradio/pull/3979).
+
+### Breaking Changes:
+
+- Some re-exports in `gradio.themes` utilities (introduced in 3.24.0) have been eradicated.
+ By [@akx](https://github.com/akx) in [PR 3958](https://github.com/gradio-app/gradio/pull/3958)
+
+### Full Changelog:
+
+- Add DESCRIPTION.md to image_segmentation demo by [@aliabd](https://github.com/aliabd) in [PR 3866](https://github.com/gradio-app/gradio/pull/3866)
+- Fix error in running `gr.themes.builder()` by [@deepkyu](https://github.com/deepkyu) in [PR 3869](https://github.com/gradio-app/gradio/pull/3869)
+- Fixed a JavaScript TypeError when loading custom JS with `_js` and setting `outputs` to `None` in `gradio.Blocks()` by [@DavG25](https://github.com/DavG25) in [PR 3883](https://github.com/gradio-app/gradio/pull/3883)
+- Fixed bg_background_fill theme property to expand to whole background, block_radius to affect form elements as well, and added block_label_shadow theme property by [@aliabid94](https://github.com/aliabid94) in [PR 3590](https://github.com/gradio-app/gradio/pull/3590)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.27.0
+
+### New Features:
+
+###### AnnotatedImage Component
+
+New AnnotatedImage component allows users to highlight regions of an image, either by providing bounding boxes, or 0-1 pixel masks. This component is useful for tasks such as image segmentation, object detection, and image captioning.
+
+![AnnotatedImage screenshot](https://user-images.githubusercontent.com/7870876/232142720-86e0020f-beaf-47b9-a843-689c9621f09c.gif)
+
+Example usage:
+
+```python
+with gr.Blocks() as demo:
+ img = gr.Image()
+ img_section = gr.AnnotatedImage()
+ def mask(img):
+ top_left_corner = [0, 0, 20, 20]
+ random_mask = np.random.randint(0, 2, img.shape[:2])
+ return (img, [(top_left_corner, "left corner"), (random_mask, "random")])
+ img.change(mask, img, img_section)
+```
+
+See the [image_segmentation demo](https://github.com/gradio-app/gradio/tree/main/demo/image_segmentation) for a full example. By [@aliabid94](https://github.com/aliabid94) in [PR 3836](https://github.com/gradio-app/gradio/pull/3836)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.26.0
+
+### New Features:
+
+###### `Video` component supports subtitles
+
+- Allow the video component to accept subtitles as input, by [@tomchang25](https://github.com/tomchang25) in [PR 3673](https://github.com/gradio-app/gradio/pull/3673). To provide subtitles, simply return a tuple consisting of `(path_to_video, path_to_subtitles)` from your function. Both `.srt` and `.vtt` formats are supported:
+
+```py
+with gr.Blocks() as demo:
+ gr.Video(("video.mp4", "captions.srt"))
+```
+
+### Bug Fixes:
+
+- Fix code markdown support in `gr.Chatbot()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3816](https://github.com/gradio-app/gradio/pull/3816)
+
+### Documentation Changes:
+
+- Updates the "view API" page in Gradio apps to use the `gradio_client` library by [@aliabd](https://github.com/aliabd) in [PR 3765](https://github.com/gradio-app/gradio/pull/3765)
+
+- Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.25.0
+
+### New Features:
+
+- Improve error messages when number of inputs/outputs to event handlers mismatch, by [@space-nuko](https://github.com/space-nuko) in [PR 3519](https://github.com/gradio-app/gradio/pull/3519)
+
+- Add `select` listener to Images, allowing users to click on any part of an image and get the coordinates of the click by [@aliabid94](https://github.com/aliabid94) in [PR 3786](https://github.com/gradio-app/gradio/pull/3786).
+
+```python
+with gr.Blocks() as demo:
+ img = gr.Image()
+ textbox = gr.Textbox()
+
+ def select_handler(img, evt: gr.SelectData):
+ selected_pixel = img[evt.index[1], evt.index[0]]
+ return f"Selected pixel: {selected_pixel}"
+
+ img.select(select_handler, img, textbox)
+```
+
+![Recording 2023-04-08 at 17 44 39](https://user-images.githubusercontent.com/7870876/230748572-90a2a8d5-116d-4769-bb53-5516555fbd0f.gif)
+
+### Bug Fixes:
+
+- Increase timeout for sending analytics data by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3647](https://github.com/gradio-app/gradio/pull/3647)
+- Fix bug where http token was not accessed over websocket connections by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3735](https://github.com/gradio-app/gradio/pull/3735)
+- Add ability to specify `rows`, `columns` and `object-fit` in `style()` for `gr.Gallery()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3586](https://github.com/gradio-app/gradio/pull/3586)
+- Fix bug where recording an audio file through the microphone resulted in a corrupted file name by [@abidlabs](https://github.com/abidlabs) in [PR 3770](https://github.com/gradio-app/gradio/pull/3770)
+- Added "ssl_verify" to blocks.launch method to allow for use of self-signed certs by [@garrettsutula](https://github.com/garrettsutula) in [PR 3873](https://github.com/gradio-app/gradio/pull/3873)
+- Fix bug where iterators where not being reset for processes that terminated early by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3777](https://github.com/gradio-app/gradio/pull/3777)
+- Fix bug where the upload button was not properly handling the `file_count='multiple'` case by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3782](https://github.com/gradio-app/gradio/pull/3782)
+- Fix bug where use Via API button was giving error by [@Devang-C](https://github.com/Devang-C) in [PR 3783](https://github.com/gradio-app/gradio/pull/3783)
+
+### Documentation Changes:
+
+- Fix invalid argument docstrings, by [@akx](https://github.com/akx) in [PR 3740](https://github.com/gradio-app/gradio/pull/3740)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed IPv6 listening to work with bracket [::1] notation, by [@dsully](https://github.com/dsully) in [PR 3695](https://github.com/gradio-app/gradio/pull/3695)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.24.1
+
+### New Features:
+
+- No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes Chatbot issue where new lines were being created every time a message was sent back and forth by [@aliabid94](https://github.com/aliabid94) in [PR 3717](https://github.com/gradio-app/gradio/pull/3717).
+- Fixes data updating in DataFrame invoking a `select` event once the dataframe has been selected. By [@yiyuezhuo](https://github.com/yiyuezhuo) in [PR 3861](https://github.com/gradio-app/gradio/pull/3861)
+- Fixes false positive warning which is due to too strict type checking by [@yiyuezhuo](https://github.com/yiyuezhuo) in [PR 3837](https://github.com/gradio-app/gradio/pull/3837).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.24.0
+
+### New Features:
+
+- Trigger the release event when Slider number input is released or unfocused by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3589](https://github.com/gradio-app/gradio/pull/3589)
+- Created Theme Builder, which allows users to create themes without writing any code, by [@aliabid94](https://github.com/aliabid94) in [PR 3664](https://github.com/gradio-app/gradio/pull/3664). Launch by:
+
+ ```python
+ import gradio as gr
+ gr.themes.builder()
+ ```
+
+ ![Theme Builder](https://user-images.githubusercontent.com/7870876/228204929-d71cbba5-69c2-45b3-bd20-e3a201d98b12.png)
+
+- The `Dropdown` component now has a `allow_custom_value` parameter that lets users type in custom values not in the original list of choices.
+- The `Colorpicker` component now has a `.blur()` event
+
+###### Added a download button for videos! 📥
+
+![download_video](https://user-images.githubusercontent.com/41651716/227009612-9bc5fb72-2a44-4c55-9b7b-a0fa098e7f25.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3581](https://github.com/gradio-app/gradio/pull/3581).
+
+- Trigger the release event when Slider number input is released or unfocused by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3589](https://github.com/gradio-app/gradio/pull/3589)
+
+### Bug Fixes:
+
+- Fixed bug where text for altair plots was not legible in dark mode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3555](https://github.com/gradio-app/gradio/pull/3555)
+- Fixes `Chatbot` and `Image` components so that files passed during processing are added to a directory where they can be served from, by [@abidlabs](https://github.com/abidlabs) in [PR 3523](https://github.com/gradio-app/gradio/pull/3523)
+- Use Gradio API server to send telemetry using `huggingface_hub` [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3488](https://github.com/gradio-app/gradio/pull/3488)
+- Fixes an an issue where if the Blocks scope was not exited, then State could be shared across sessions, by [@abidlabs](https://github.com/abidlabs) in [PR 3600](https://github.com/gradio-app/gradio/pull/3600)
+- Ensures that `gr.load()` loads and applies the upstream theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641)
+- Fixed bug where "or" was not being localized in file upload text by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3599](https://github.com/gradio-app/gradio/pull/3599)
+- Fixed bug where chatbot does not autoscroll inside of a tab, row or column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637)
+- Fixed bug where textbox shrinks when `lines` set to larger than 20 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637)
+- Ensure CSS has fully loaded before rendering the application, by [@pngwn](https://github.com/pngwn) in [PR 3573](https://github.com/gradio-app/gradio/pull/3573)
+- Support using an empty list as `gr.Dataframe` value, by [@space-nuko](https://github.com/space-nuko) in [PR 3646](https://github.com/gradio-app/gradio/pull/3646)
+- Fixed `gr.Image` not filling the entire element size, by [@space-nuko](https://github.com/space-nuko) in [PR 3649](https://github.com/gradio-app/gradio/pull/3649)
+- Make `gr.Code` support the `lines` property, by [@space-nuko](https://github.com/space-nuko) in [PR 3651](https://github.com/gradio-app/gradio/pull/3651)
+- Fixes certain `_js` return values being double wrapped in an array, by [@space-nuko](https://github.com/space-nuko) in [PR 3594](https://github.com/gradio-app/gradio/pull/3594)
+- Correct the documentation of `gr.File` component to state that its preprocessing method converts the uploaded file to a temporary file, by @RussellLuo in [PR 3660](https://github.com/gradio-app/gradio/pull/3660)
+- Fixed bug in Serializer ValueError text by [@osanseviero](https://github.com/osanseviero) in [PR 3669](https://github.com/gradio-app/gradio/pull/3669)
+- Fix default parameter argument and `gr.Progress` used in same function, by [@space-nuko](https://github.com/space-nuko) in [PR 3671](https://github.com/gradio-app/gradio/pull/3671)
+- Hide `Remove All` button in `gr.Dropdown` single-select mode by [@space-nuko](https://github.com/space-nuko) in [PR 3678](https://github.com/gradio-app/gradio/pull/3678)
+- Fix broken spaces in docs by [@aliabd](https://github.com/aliabd) in [PR 3698](https://github.com/gradio-app/gradio/pull/3698)
+- Fix items in `gr.Dropdown` besides the selected item receiving a checkmark, by [@space-nuko](https://github.com/space-nuko) in [PR 3644](https://github.com/gradio-app/gradio/pull/3644)
+- Fix several `gr.Dropdown` issues and improve usability, by [@space-nuko](https://github.com/space-nuko) in [PR 3705](https://github.com/gradio-app/gradio/pull/3705)
+
+### Documentation Changes:
+
+- Makes some fixes to the Theme Guide related to naming of variables, by [@abidlabs](https://github.com/abidlabs) in [PR 3561](https://github.com/gradio-app/gradio/pull/3561)
+- Documented `HuggingFaceDatasetJSONSaver` by [@osanseviero](https://github.com/osanseviero) in [PR 3604](https://github.com/gradio-app/gradio/pull/3604)
+- Makes some additions to documentation of `Audio` and `State` components, and fixes the `pictionary` demo by [@abidlabs](https://github.com/abidlabs) in [PR 3611](https://github.com/gradio-app/gradio/pull/3611)
+- Fix outdated sharing your app guide by [@aliabd](https://github.com/aliabd) in [PR 3699](https://github.com/gradio-app/gradio/pull/3699)
+
+### Testing and Infrastructure Changes:
+
+- Removed heavily-mocked tests related to comet_ml, wandb, and mlflow as they added a significant amount of test dependencies that prevented installation of test dependencies on Windows environments. By [@abidlabs](https://github.com/abidlabs) in [PR 3608](https://github.com/gradio-app/gradio/pull/3608)
+- Added Windows continuous integration, by [@space-nuko](https://github.com/space-nuko) in [PR 3628](https://github.com/gradio-app/gradio/pull/3628)
+- Switched linting from flake8 + isort to `ruff`, by [@akx](https://github.com/akx) in [PR 3710](https://github.com/gradio-app/gradio/pull/3710)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Mobile responsive iframes in themes guide by [@aliabd](https://github.com/aliabd) in [PR 3562](https://github.com/gradio-app/gradio/pull/3562)
+- Remove extra $demo from theme guide by [@aliabd](https://github.com/aliabd) in [PR 3563](https://github.com/gradio-app/gradio/pull/3563)
+- Set the theme name to be the upstream repo name when loading from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3595](https://github.com/gradio-app/gradio/pull/3595)
+- Copy everything in website Dockerfile, fix build issues by [@aliabd](https://github.com/aliabd) in [PR 3659](https://github.com/gradio-app/gradio/pull/3659)
+- Raise error when an event is queued but the queue is not configured by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3640](https://github.com/gradio-app/gradio/pull/3640)
+- Allows users to apss in a string name for a built-in theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641)
+- Added `orig_name` to Video output in the backend so that the front end can set the right name for downloaded video files by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3700](https://github.com/gradio-app/gradio/pull/3700)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.23.0
+
+### New Features:
+
+###### Theme Sharing!
+
+Once you have created a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it! You can also download, reuse, and remix other peoples' themes. See https://gradio.app/theming-guide/ for more details.
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3428](https://github.com/gradio-app/gradio/pull/3428)
+
+### Bug Fixes:
+
+- Removes leading spaces from all lines of code uniformly in the `gr.Code()` component. By [@abidlabs](https://github.com/abidlabs) in [PR 3556](https://github.com/gradio-app/gradio/pull/3556)
+- Fixed broken login page, by [@aliabid94](https://github.com/aliabid94) in [PR 3529](https://github.com/gradio-app/gradio/pull/3529)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fix rendering of dropdowns to take more space, and related bugs, by [@aliabid94](https://github.com/aliabid94) in [PR 3549](https://github.com/gradio-app/gradio/pull/3549)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.22.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Restore label bars by [@aliabid94](https://github.com/aliabid94) in [PR 3507](https://github.com/gradio-app/gradio/pull/3507)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.22.0
+
+### New Features:
+
+###### Official Theme release
+
+Gradio now supports a new theme system, which allows you to customize the look and feel of your app. You can now use the `theme=` kwarg to pass in a prebuilt theme, or customize your own! See https://gradio.app/theming-guide/ for more details. By [@aliabid94](https://github.com/aliabid94) in [PR 3470](https://github.com/gradio-app/gradio/pull/3470) and [PR 3497](https://github.com/gradio-app/gradio/pull/3497)
+
+###### `elem_classes`
+
+Add keyword argument `elem_classes` to Components to control class names of components, in the same manner as existing `elem_id`.
+By [@aliabid94](https://github.com/aliabid94) in [PR 3466](https://github.com/gradio-app/gradio/pull/3466)
+
+### Bug Fixes:
+
+- Fixes the File.upload() event trigger which broke as part of the change in how we uploaded files by [@abidlabs](https://github.com/abidlabs) in [PR 3462](https://github.com/gradio-app/gradio/pull/3462)
+- Fixed issue with `gr.Request` object failing to handle dictionaries when nested keys couldn't be converted to variable names [#3454](https://github.com/gradio-app/gradio/issues/3454) by [@radames](https://github.com/radames) in [PR 3459](https://github.com/gradio-app/gradio/pull/3459)
+- Fixed bug where css and client api was not working properly when mounted in a subpath by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3482](https://github.com/gradio-app/gradio/pull/3482)
+
+### Documentation Changes:
+
+- Document gr.Error in the docs by [@aliabd](https://github.com/aliabd) in [PR 3465](https://github.com/gradio-app/gradio/pull/3465)
+
+### Testing and Infrastructure Changes:
+
+- Pinned `pyright==1.1.298` for stability by [@abidlabs](https://github.com/abidlabs) in [PR 3475](https://github.com/gradio-app/gradio/pull/3475)
+- Removed `IOComponent.add_interactive_to_config()` by [@space-nuko](https://github.com/space-nuko) in [PR 3476](https://github.com/gradio-app/gradio/pull/3476)
+- Removed `IOComponent.generate_sample()` by [@space-nuko](https://github.com/space-nuko) in [PR 3475](https://github.com/gradio-app/gradio/pull/3483)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Revert primary button background color in dark mode by [@aliabid94](https://github.com/aliabid94) in [PR 3468](https://github.com/gradio-app/gradio/pull/3468)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.21.0
+
+### New Features:
+
+###### Theme Sharing 🎨 🤝
+
+You can now share your gradio themes with the world!
+
+After creating a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it!
+
+###### Uploading
+
+There are two ways to upload a theme, via the theme class instance or the command line.
+
+1. Via the class instance
+
+```python
+my_theme.push_to_hub(repo_name="my_theme",
+ version="0.2.0",
+ hf_token="...")
+```
+
+2. Via the command line
+
+First save the theme to disk
+
+```python
+my_theme.dump(filename="my_theme.json")
+```
+
+Then use the `upload_theme` command:
+
+```bash
+upload_theme\
+"my_theme.json"\
+"my_theme"\
+"0.2.0"\
+""
+```
+
+The `version` must be a valid [semantic version](https://www.geeksforgeeks.org/introduction-semantic-versioning/) string.
+
+This creates a space on the huggingface hub to host the theme files and show potential users a preview of your theme.
+
+An example theme space is here: https://huggingface.co/spaces/freddyaboulton/dracula_revamped
+
+###### Downloading
+
+To use a theme from the hub, use the `from_hub` method on the `ThemeClass` and pass it to your app:
+
+```python
+my_theme = gr.Theme.from_hub("freddyaboulton/my_theme")
+
+with gr.Blocks(theme=my_theme) as demo:
+ ....
+```
+
+You can also pass the theme string directly to `Blocks` or `Interface` (`gr.Blocks(theme="freddyaboulton/my_theme")`)
+
+You can pin your app to an upstream theme version by using semantic versioning expressions.
+
+For example, the following would ensure the theme we load from the `my_theme` repo was between versions `0.1.0` and `0.2.0`:
+
+```python
+with gr.Blocks(theme="freddyaboulton/my_theme@>=0.1.0,<0.2.0") as demo:
+ ....
+```
+
+by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3428](https://github.com/gradio-app/gradio/pull/3428)
+
+###### Code component 🦾
+
+New code component allows you to enter, edit and display code with full syntax highlighting by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+
+###### The `Chatbot` component now supports audio, video, and images
+
+The `Chatbot` component now supports audio, video, and images with a simple syntax: simply
+pass in a tuple with the URL or filepath (the second optional element of the tuple is alt text), and the image/audio/video will be displayed:
+
+```python
+gr.Chatbot([
+ (("driving.mp4",), "cool video"),
+ (("cantina.wav",), "cool audio"),
+ (("lion.jpg", "A lion"), "cool pic"),
+]).style(height=800)
+```
+
+
+
+Note: images were previously supported via Markdown syntax and that is still supported for backwards compatibility. By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3413](https://github.com/gradio-app/gradio/pull/3413)
+
+- Allow consecutive function triggers with `.then` and `.success` by [@aliabid94](https://github.com/aliabid94) in [PR 3430](https://github.com/gradio-app/gradio/pull/3430)
+
+- New code component allows you to enter, edit and display code with full syntax highlighting by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+
+![](https://user-images.githubusercontent.com/12937446/224116643-5cfb94b3-93ce-43ee-bb7b-c25c3b66e0a1.png)
+
+- Added the `.select()` event listener, which also includes event data that can be passed as an argument to a function with type hint `gr.SelectData`. The following components support the `.select()` event listener: Chatbot, CheckboxGroup, Dataframe, Dropdown, File, Gallery, HighlightedText, Label, Radio, TabItem, Tab, Textbox. Example usage:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gallery = gr.Gallery(["images/1.jpg", "images/2.jpg", "images/3.jpg"])
+ selected_index = gr.Textbox()
+
+ def on_select(evt: gr.SelectData):
+ return evt.index
+
+ gallery.select(on_select, None, selected_index)
+```
+
+By [@aliabid94](https://github.com/aliabid94) in [PR 3399](https://github.com/gradio-app/gradio/pull/3399)
+
+- The `Textbox` component now includes a copy button by [@abidlabs](https://github.com/abidlabs) in [PR 3452](https://github.com/gradio-app/gradio/pull/3452)
+
+### Bug Fixes:
+
+- Use `huggingface_hub` to send telemetry on `interface` and `blocks`; eventually to replace segment by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3342](https://github.com/gradio-app/gradio/pull/3342)
+- Ensure load events created by components (randomize for slider, callable values) are never queued unless every is passed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3391](https://github.com/gradio-app/gradio/pull/3391)
+- Prevent in-place updates of `generic_update` by shallow copying by [@gitgithan](https://github.com/gitgithan) in [PR 3405](https://github.com/gradio-app/gradio/pull/3405) to fix [#3282](https://github.com/gradio-app/gradio/issues/3282)
+- Fix bug caused by not importing `BlockContext` in `utils.py` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3424](https://github.com/gradio-app/gradio/pull/3424)
+- Ensure dropdown does not highlight partial matches by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+- Fix mic button display by [@aliabid94](https://github.com/aliabid94) in [PR 3456](https://github.com/gradio-app/gradio/pull/3456)
+
+### Documentation Changes:
+
+- Added a section on security and access when sharing Gradio apps by [@abidlabs](https://github.com/abidlabs) in [PR 3408](https://github.com/gradio-app/gradio/pull/3408)
+- Add Chinese README by [@uanu2002](https://github.com/uanu2002) in [PR 3394](https://github.com/gradio-app/gradio/pull/3394)
+- Adds documentation for web components by [@abidlabs](https://github.com/abidlabs) in [PR 3407](https://github.com/gradio-app/gradio/pull/3407)
+- Fixed link in Chinese readme by [@eltociear](https://github.com/eltociear) in [PR 3417](https://github.com/gradio-app/gradio/pull/3417)
+- Document Blocks methods by [@aliabd](https://github.com/aliabd) in [PR 3427](https://github.com/gradio-app/gradio/pull/3427)
+- Fixed bug where event handlers were not showing up in documentation by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3434](https://github.com/gradio-app/gradio/pull/3434)
+
+### Testing and Infrastructure Changes:
+
+- Fixes tests that were failing locally but passing on CI by [@abidlabs](https://github.com/abidlabs) in [PR 3411](https://github.com/gradio-app/gradio/pull/3411)
+- Remove codecov from the repo by [@aliabd](https://github.com/aliabd) in [PR 3415](https://github.com/gradio-app/gradio/pull/3415)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Prevent in-place updates of `generic_update` by shallow copying by [@gitgithan](https://github.com/gitgithan) in [PR 3405](https://github.com/gradio-app/gradio/pull/3405) to fix [#3282](https://github.com/gradio-app/gradio/issues/3282)
+- Persist file names of files uploaded through any Gradio component by [@abidlabs](https://github.com/abidlabs) in [PR 3412](https://github.com/gradio-app/gradio/pull/3412)
+- Fix markdown embedded component in docs by [@aliabd](https://github.com/aliabd) in [PR 3410](https://github.com/gradio-app/gradio/pull/3410)
+- Clean up event listeners code by [@aliabid94](https://github.com/aliabid94) in [PR 3420](https://github.com/gradio-app/gradio/pull/3420)
+- Fix css issue with spaces logo by [@aliabd](https://github.com/aliabd) in [PR 3422](https://github.com/gradio-app/gradio/pull/3422)
+- Makes a few fixes to the `JSON` component (show_label parameter, icons) in [@abidlabs](https://github.com/abidlabs) in [PR 3451](https://github.com/gradio-app/gradio/pull/3451)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.20.1
+
+### New Features:
+
+- Add `height` kwarg to style in `gr.Chatbot()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3369](https://github.com/gradio-app/gradio/pull/3369)
+
+```python
+chatbot = gr.Chatbot().style(height=500)
+```
+
+### Bug Fixes:
+
+- Ensure uploaded images are always shown in the sketch tool by [@pngwn](https://github.com/pngwn) in [PR 3386](https://github.com/gradio-app/gradio/pull/3386)
+- Fixes bug where when if fn is a non-static class member, then self should be ignored as the first param of the fn by [@or25](https://github.com/or25) in [PR #3227](https://github.com/gradio-app/gradio/pull/3227)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.20.0
+
+### New Features:
+
+###### Release event for Slider
+
+Now you can trigger your python function to run when the slider is released as opposed to every slider change value!
+
+Simply use the `release` method on the slider
+
+```python
+slider.release(function, inputs=[...], outputs=[...], api_name="predict")
+```
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3353](https://github.com/gradio-app/gradio/pull/3353)
+
+###### Dropdown Component Updates
+
+The standard dropdown component now supports searching for choices. Also when `multiselect` is `True`, you can specify `max_choices` to set the maximum number of choices you want the user to be able to select from the dropdown component.
+
+```python
+gr.Dropdown(label="Choose your favorite colors", choices=["red", "blue", "green", "yellow", "orange"], multiselect=True, max_choices=2)
+```
+
+by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3211](https://github.com/gradio-app/gradio/pull/3211)
+
+###### Download button for images 🖼️
+
+Output images will now automatically have a download button displayed to make it easier to save and share
+the results of Machine Learning art models.
+
+![download_sketch](https://user-images.githubusercontent.com/41651716/221025113-e693bf41-eabd-42b3-a4f2-26f2708d98fe.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3297](https://github.com/gradio-app/gradio/pull/3297)
+
+- Updated image upload component to accept all image formats, including lossless formats like .webp by [@fienestar](https://github.com/fienestar) in [PR 3225](https://github.com/gradio-app/gradio/pull/3225)
+- Adds a disabled mode to the `gr.Button` component by setting `interactive=False` by [@abidlabs](https://github.com/abidlabs) in [PR 3266](https://github.com/gradio-app/gradio/pull/3266) and [PR 3288](https://github.com/gradio-app/gradio/pull/3288)
+- Adds visual feedback to the when the Flag button is clicked, by [@abidlabs](https://github.com/abidlabs) in [PR 3289](https://github.com/gradio-app/gradio/pull/3289)
+- Adds ability to set `flagging_options` display text and saved flag separately by [@abidlabs](https://github.com/abidlabs) in [PR 3289](https://github.com/gradio-app/gradio/pull/3289)
+- Allow the setting of `brush_radius` for the `Image` component both as a default and via `Image.update()` by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Added `info=` argument to form components to enable extra context provided to users, by [@aliabid94](https://github.com/aliabid94) in [PR 3291](https://github.com/gradio-app/gradio/pull/3291)
+- Allow developers to access the username of a logged-in user from the `gr.Request()` object using the `.username` attribute by [@abidlabs](https://github.com/abidlabs) in [PR 3296](https://github.com/gradio-app/gradio/pull/3296)
+- Add `preview` option to `Gallery.style` that launches the gallery in preview mode when first loaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3345](https://github.com/gradio-app/gradio/pull/3345)
+
+### Bug Fixes:
+
+- Ensure `mirror_webcam` is always respected by [@pngwn](https://github.com/pngwn) in [PR 3245](https://github.com/gradio-app/gradio/pull/3245)
+- Fix issue where updated markdown links were not being opened in a new tab by [@gante](https://github.com/gante) in [PR 3236](https://github.com/gradio-app/gradio/pull/3236)
+- API Docs Fixes by [@aliabd](https://github.com/aliabd) in [PR 3287](https://github.com/gradio-app/gradio/pull/3287)
+- Added a timeout to queue messages as some demos were experiencing infinitely growing queues from active jobs waiting forever for clients to respond by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3196](https://github.com/gradio-app/gradio/pull/3196)
+- Fixes the height of rendered LaTeX images so that they match the height of surrounding text by [@abidlabs](https://github.com/abidlabs) in [PR 3258](https://github.com/gradio-app/gradio/pull/3258) and in [PR 3276](https://github.com/gradio-app/gradio/pull/3276)
+- Fix bug where matplotlib images where always too small on the front end by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3274](https://github.com/gradio-app/gradio/pull/3274)
+- Remove embed's `initial_height` when loading is complete so the embed finds its natural height once it is loaded [@pngwn](https://github.com/pngwn) in [PR 3292](https://github.com/gradio-app/gradio/pull/3292)
+- Prevent Sketch from crashing when a default image is provided by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Respect the `shape` argument on the front end when creating Image Sketches by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Fix infinite loop caused by setting `Dropdown's` value to be `[]` and adding a change event on the dropdown by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3295](https://github.com/gradio-app/gradio/pull/3295)
+- Fix change event listed twice in image docs by [@aliabd](https://github.com/aliabd) in [PR 3318](https://github.com/gradio-app/gradio/pull/3318)
+- Fix bug that cause UI to be vertically centered at all times by [@pngwn](https://github.com/pngwn) in [PR 3336](https://github.com/gradio-app/gradio/pull/3336)
+- Fix bug where `height` set in `Gallery.style` was not respected by the front-end by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3343](https://github.com/gradio-app/gradio/pull/3343)
+- Ensure markdown lists are rendered correctly by [@pngwn](https://github.com/pngwn) in [PR 3341](https://github.com/gradio-app/gradio/pull/3341)
+- Ensure that the initial empty value for `gr.Dropdown(Multiselect=True)` is an empty list and the initial value for `gr.Dropdown(Multiselect=False)` is an empty string by [@pngwn](https://github.com/pngwn) in [PR 3338](https://github.com/gradio-app/gradio/pull/3338)
+- Ensure uploaded images respect the shape property when the canvas is also enabled by [@pngwn](https://github.com/pngwn) in [PR 3351](https://github.com/gradio-app/gradio/pull/3351)
+- Ensure that Google Analytics works correctly when gradio apps are created with `analytics_enabled=True` by [@abidlabs](https://github.com/abidlabs) in [PR 3349](https://github.com/gradio-app/gradio/pull/3349)
+- Fix bug where files were being re-uploaded after updates by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3375](https://github.com/gradio-app/gradio/pull/3375)
+- Fix error when using backen_fn and custom js at the same time by [@jialeicui](https://github.com/jialeicui) in [PR 3358](https://github.com/gradio-app/gradio/pull/3358)
+- Support new embeds for huggingface spaces subdomains by [@pngwn](https://github.com/pngwn) in [PR 3367](https://github.com/gradio-app/gradio/pull/3367)
+
+### Documentation Changes:
+
+- Added the `types` field to the dependency field in the config by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3315](https://github.com/gradio-app/gradio/pull/3315)
+- Gradio Status Page by [@aliabd](https://github.com/aliabd) in [PR 3331](https://github.com/gradio-app/gradio/pull/3331)
+- Adds a Guide on setting up a dashboard from Supabase data using the `gr.BarPlot`
+ component by [@abidlabs](https://github.com/abidlabs) in [PR 3275](https://github.com/gradio-app/gradio/pull/3275)
+
+### Testing and Infrastructure Changes:
+
+- Adds a script to benchmark the performance of the queue and adds some instructions on how to use it. By [@freddyaboulton](https://github.com/freddyaboulton) and [@abidlabs](https://github.com/abidlabs) in [PR 3272](https://github.com/gradio-app/gradio/pull/3272)
+- Flaky python tests no longer cancel non-flaky tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3344](https://github.com/gradio-app/gradio/pull/3344)
+
+### Breaking Changes:
+
+- Chatbot bubble colors can no longer be set by `chatbot.style(color_map=)` by [@aliabid94] in [PR 3370](https://github.com/gradio-app/gradio/pull/3370)
+
+### Full Changelog:
+
+- Fixed comment typo in components.py by [@eltociear](https://github.com/eltociear) in [PR 3235](https://github.com/gradio-app/gradio/pull/3235)
+- Cleaned up chatbot ui look and feel by [@aliabid94] in [PR 3370](https://github.com/gradio-app/gradio/pull/3370)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.19.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- UI fixes including footer and API docs by [@aliabid94](https://github.com/aliabid94) in [PR 3242](https://github.com/gradio-app/gradio/pull/3242)
+- Updated image upload component to accept all image formats, including lossless formats like .webp by [@fienestar](https://github.com/fienestar) in [PR 3225](https://github.com/gradio-app/gradio/pull/3225)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Added backend support for themes by [@aliabid94](https://github.com/aliabid94) in [PR 2931](https://github.com/gradio-app/gradio/pull/2931)
+- Added support for button sizes "lg" (default) and "sm".
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.19.0
+
+### New Features:
+
+###### Improved embedding experience
+
+When embedding a spaces-hosted gradio app as a web component, you now get an improved UI linking back to the original space, better error handling and more intelligent load performance. No changes are required to your code to benefit from this enhanced experience; simply upgrade your gradio SDK to the latest version.
+
+![](https://user-images.githubusercontent.com/12937446/219653294-86937632-72c1-4e93-a77c-af705d49382a.png)
+
+This behaviour is configurable. You can disable the info panel at the bottom by passing `info="false"`. You can disable the container entirely by passing `container="false"`.
+
+Error statuses are reported in the UI with an easy way for end-users to report problems to the original space author via the community tab of that Hugginface space:
+
+![](https://user-images.githubusercontent.com/12937446/219655499-88019443-d694-44e7-9e6d-242e19d10a5c.png)
+
+By default, gradio apps are lazy loaded, vastly improving performance when there are several demos on the page. Metadata is loaded ahead of time, but the space will only be loaded and rendered when it is in view.
+
+This behaviour is configurable. You can pass `eager="true"` to load and render the space regardless of whether or not it is currently on the screen.
+
+by [@pngwn](https://github.com/pngwn) in [PR 3205](https://github.com/gradio-app/gradio/pull/3205)
+
+###### New `gr.BarPlot` component! 📊
+
+Create interactive bar plots from a high-level interface with `gr.BarPlot`.
+No need to remember matplotlib syntax anymore!
+
+Example usage:
+
+```python
+import gradio as gr
+import pandas as pd
+
+simple = pd.DataFrame({
+ 'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
+ 'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
+})
+
+with gr.Blocks() as demo:
+ gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ title="Simple Bar Plot with made up data",
+ tooltip=['a', 'b'],
+ )
+
+demo.launch()
+```
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3157](https://github.com/gradio-app/gradio/pull/3157)
+
+###### Bokeh plots are back! 🌠
+
+Fixed a bug that prevented bokeh plots from being displayed on the front end and extended support for both 2.x and 3.x versions of bokeh!
+
+![image](https://user-images.githubusercontent.com/41651716/219468324-0d82e07f-8fb4-4ff9-b40c-8250b29e45f7.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3212](https://github.com/gradio-app/gradio/pull/3212)
+
+### Bug Fixes:
+
+- Adds ability to add a single message from the bot or user side. Ex: specify `None` as the second value in the tuple, to add a single message in the chatbot from the "bot" side.
+
+```python
+gr.Chatbot([("Hi, I'm DialoGPT. Try asking me a question.", None)])
+```
+
+By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3165](https://github.com/gradio-app/gradio/pull/3165)
+
+- Fixes `gr.utils.delete_none` to only remove props whose values are `None` from the config by [@abidlabs](https://github.com/abidlabs) in [PR 3188](https://github.com/gradio-app/gradio/pull/3188)
+- Fix bug where embedded demos were not loading files properly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3177](https://github.com/gradio-app/gradio/pull/3177)
+- The `change` event is now triggered when users click the 'Clear All' button of the multiselect DropDown component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3195](https://github.com/gradio-app/gradio/pull/3195)
+- Stops File component from freezing when a large file is uploaded by [@aliabid94](https://github.com/aliabid94) in [PR 3191](https://github.com/gradio-app/gradio/pull/3191)
+- Support Chinese pinyin in Dataframe by [@aliabid94](https://github.com/aliabid94) in [PR 3206](https://github.com/gradio-app/gradio/pull/3206)
+- The `clear` event is now triggered when images are cleared by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3218](https://github.com/gradio-app/gradio/pull/3218)
+- Fix bug where auth cookies where not sent when connecting to an app via http by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3223](https://github.com/gradio-app/gradio/pull/3223)
+- Ensure latext CSS is always applied in light and dark mode by [@pngwn](https://github.com/pngwn) in [PR 3233](https://github.com/gradio-app/gradio/pull/3233)
+
+### Documentation Changes:
+
+- Sort components in docs by alphabetic order by [@aliabd](https://github.com/aliabd) in [PR 3152](https://github.com/gradio-app/gradio/pull/3152)
+- Changes to W&B guide by [@scottire](https://github.com/scottire) in [PR 3153](https://github.com/gradio-app/gradio/pull/3153)
+- Keep pnginfo metadata for gallery by [@wfng92](https://github.com/wfng92) in [PR 3150](https://github.com/gradio-app/gradio/pull/3150)
+- Add a section on how to run a Gradio app locally [@osanseviero](https://github.com/osanseviero) in [PR 3170](https://github.com/gradio-app/gradio/pull/3170)
+- Fixed typos in gradio events function documentation by [@vidalmaxime](https://github.com/vidalmaxime) in [PR 3168](https://github.com/gradio-app/gradio/pull/3168)
+- Added an example using Gradio's batch mode with the diffusers library by [@abidlabs](https://github.com/abidlabs) in [PR 3224](https://github.com/gradio-app/gradio/pull/3224)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fix demos page css and add close demos button by [@aliabd](https://github.com/aliabd) in [PR 3151](https://github.com/gradio-app/gradio/pull/3151)
+- Caches temp files from base64 input data by giving them a deterministic path based on the contents of data by [@abidlabs](https://github.com/abidlabs) in [PR 3197](https://github.com/gradio-app/gradio/pull/3197)
+- Better warnings (when there is a mismatch between the number of output components and values returned by a function, or when the `File` component or `UploadButton` component includes a `file_types` parameter along with `file_count=="dir"`) by [@abidlabs](https://github.com/abidlabs) in [PR 3194](https://github.com/gradio-app/gradio/pull/3194)
+- Raises a `gr.Error` instead of a regular Python error when you use `gr.Interface.load()` to load a model and there's an error querying the HF API by [@abidlabs](https://github.com/abidlabs) in [PR 3194](https://github.com/gradio-app/gradio/pull/3194)
+- Fixed gradio share links so that they are persistent and do not reset if network
+ connection is disrupted by by [XciD](https://github.com/XciD), [Wauplin](https://github.com/Wauplin), and [@abidlabs](https://github.com/abidlabs) in [PR 3149](https://github.com/gradio-app/gradio/pull/3149) and a follow-up to allow it to work for users upgrading from a previous Gradio version in [PR 3221](https://github.com/gradio-app/gradio/pull/3221)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.18.0
+
+### New Features:
+
+###### Revamped Stop Button for Interfaces 🛑
+
+If your Interface function is a generator, there used to be a separate `Stop` button displayed next
+to the `Submit` button.
+
+We've revamed the `Submit` button so that it turns into a `Stop` button during the generation process.
+Clicking on the `Stop` button will cancel the generation and turn it back to a `Submit` button.
+The `Stop` button will automatically turn back to a `Submit` button at the end of the generation if you don't use it!
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3124](https://github.com/gradio-app/gradio/pull/3124)
+
+###### Queue now works with reload mode!
+
+You can now call `queue` on your `demo` outside of the `if __name__ == "__main__"` block and
+run the script in reload mode with the `gradio` command.
+
+Any changes to the `app.py` file will be reflected in the webpage automatically and the queue will work
+properly!
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+
+###### Allow serving files from additional directories
+
+```python
+demo = gr.Interface(...)
+demo.launch(
+ file_directories=["/var/lib/demo/path/to/resources"]
+)
+```
+
+By [@maxaudron](https://github.com/maxaudron) in [PR 3075](https://github.com/gradio-app/gradio/pull/3075)
+
+### Bug Fixes:
+
+- Fixes URL resolution on Windows by [@abidlabs](https://github.com/abidlabs) in [PR 3108](https://github.com/gradio-app/gradio/pull/3108)
+- Example caching now works with components without a label attribute (e.g. `Column`) by [@abidlabs](https://github.com/abidlabs) in [PR 3123](https://github.com/gradio-app/gradio/pull/3123)
+- Ensure the Video component correctly resets the UI state when a new video source is loaded and reduce choppiness of UI by [@pngwn](https://github.com/abidlabs) in [PR 3117](https://github.com/gradio-app/gradio/pull/3117)
+- Fixes loading private Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 3068](https://github.com/gradio-app/gradio/pull/3068)
+- Added a warning when attempting to launch an `Interface` via the `%%blocks` jupyter notebook magic command by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3126](https://github.com/gradio-app/gradio/pull/3126)
+- Fixes bug where interactive output image cannot be set when in edit mode by [@dawoodkhan82](https://github.com/@dawoodkhan82) in [PR 3135](https://github.com/gradio-app/gradio/pull/3135)
+- A share link will automatically be created when running on Sagemaker notebooks so that the front-end is properly displayed by [@abidlabs](https://github.com/abidlabs) in [PR 3137](https://github.com/gradio-app/gradio/pull/3137)
+- Fixes a few dropdown component issues; hide checkmark next to options as expected, and keyboard hover is visible by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3145]https://github.com/gradio-app/gradio/pull/3145)
+- Fixed bug where example pagination buttons were not visible in dark mode or displayed under the examples table. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3144](https://github.com/gradio-app/gradio/pull/3144)
+- Fixed bug where the font color of axis labels and titles for native plots did not respond to dark mode preferences. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3146](https://github.com/gradio-app/gradio/pull/3146)
+
+### Documentation Changes:
+
+- Added a guide on the 4 kinds of Gradio Interfaces by [@yvrjsharma](https://github.com/yvrjsharma) and [@abidlabs](https://github.com/abidlabs) in [PR 3003](https://github.com/gradio-app/gradio/pull/3003)
+- Explained that the parameters in `launch` will not be respected when using reload mode, e.g. `gradio` command by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+- Added a demo to show how to set up variable numbers of outputs in Gradio by [@abidlabs](https://github.com/abidlabs) in [PR 3127](https://github.com/gradio-app/gradio/pull/3127)
+- Updated docs to reflect that the `equal_height` parameter should be passed to the `.style()` method of `gr.Row()` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3125](https://github.com/gradio-app/gradio/pull/3125)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Changed URL of final image for `fake_diffusion` demos by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3120](https://github.com/gradio-app/gradio/pull/3120)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.17.1
+
+### New Features:
+
+###### iOS image rotation fixed 🔄
+
+Previously photos uploaded via iOS would be rotated after processing. This has been fixed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3091)
+
+######### Before
+
+![image](https://user-images.githubusercontent.com/41651716/215846507-a36e9d05-1ac2-4867-8ab3-ce045a9415d9.png)
+
+######### After
+
+![image](https://user-images.githubusercontent.com/41651716/215846554-e41773ed-70f0-491a-9952-6a18babf91ef.png)
+
+###### Run on Kaggle kernels 🧪
+
+A share link will automatically be created when running on Kaggle kernels (notebooks) so that the front-end is properly displayed.
+
+![image](https://user-images.githubusercontent.com/41651716/216104254-2cf55599-449c-436c-b57e-40f6a83f9eee.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3101](https://github.com/gradio-app/gradio/pull/3101)
+
+### Bug Fixes:
+
+- Fix bug where examples were not rendered correctly for demos created with Blocks api that had multiple input compinents by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3090](https://github.com/gradio-app/gradio/pull/3090)
+- Fix change event listener for JSON, HighlightedText, Chatbot by [@aliabid94](https://github.com/aliabid94) in [PR 3095](https://github.com/gradio-app/gradio/pull/3095)
+- Fixes bug where video and file change event not working [@tomchang25](https://github.com/tomchang25) in [PR 3098](https://github.com/gradio-app/gradio/pull/3098)
+- Fixes bug where static_video play and pause event not working [@tomchang25](https://github.com/tomchang25) in [PR 3098](https://github.com/gradio-app/gradio/pull/3098)
+- Fixed `Gallery.style(grid=...)` by by [@aliabd](https://github.com/aliabd) in [PR 3107](https://github.com/gradio-app/gradio/pull/3107)
+
+### Documentation Changes:
+
+- Update chatbot guide to include blocks demo and markdown support section by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3023](https://github.com/gradio-app/gradio/pull/3023)
+
+* Fix a broken link in the Quick Start guide, by [@cakiki](https://github.com/cakiki) in [PR 3109](https://github.com/gradio-app/gradio/pull/3109)
+* Better docs navigation on mobile by [@aliabd](https://github.com/aliabd) in [PR 3112](https://github.com/gradio-app/gradio/pull/3112)
+* Add a guide on using Gradio with [Comet](https://comet.com/), by [@DN6](https://github.com/DN6/) in [PR 3058](https://github.com/gradio-app/gradio/pull/3058)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Set minimum `markdown-it-py` version to `2.0.0` so that the dollar math plugin is compatible by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3102](https://github.com/gradio-app/gradio/pull/3102)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.17.0
+
+### New Features:
+
+###### Extended support for Interface.load! 🏗️
+
+You can now load `image-to-text` and `conversational` pipelines from the hub!
+
+###### Image-to-text Demo
+
+```python
+io = gr.Interface.load("models/nlpconnect/vit-gpt2-image-captioning",
+ api_key="")
+io.launch()
+```
+
+
+
+###### conversational Demo
+
+```python
+chatbot = gr.Interface.load("models/microsoft/DialoGPT-medium",
+ api_key="")
+chatbot.launch()
+```
+
+![chatbot_load](https://user-images.githubusercontent.com/41651716/213260220-3eaa25b7-a38b-48c6-adeb-2718bdf297a2.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3011](https://github.com/gradio-app/gradio/pull/3011)
+
+###### Download Button added to Model3D Output Component 📥
+
+No need for an additional file output component to enable model3d file downloads anymore. We now added a download button to the model3d component itself.
+
+
+
+By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3014](https://github.com/gradio-app/gradio/pull/3014)
+
+###### Fixing Auth on Spaces 🔑
+
+Authentication on spaces works now! Third party cookies must be enabled on your browser to be able
+to log in. Some browsers disable third party cookies by default (Safari, Chrome Incognito).
+
+![auth_spaces](https://user-images.githubusercontent.com/41651716/215528417-09538933-0576-4d1d-b3b9-1e877ab01905.gif)
+
+### Bug Fixes:
+
+- Fixes bug where interpretation event was not configured correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2993](https://github.com/gradio-app/gradio/pull/2993)
+- Fix relative import bug in reload mode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2992](https://github.com/gradio-app/gradio/pull/2992)
+- Fixes bug where png files were not being recognized when uploading images by [@abidlabs](https://github.com/abidlabs) in [PR 3002](https://github.com/gradio-app/gradio/pull/3002)
+- Fixes bug where external Spaces could not be loaded and used as functions if they returned files by [@abidlabs](https://github.com/abidlabs) in [PR 3004](https://github.com/gradio-app/gradio/pull/3004)
+- Fix bug where file serialization output was not JSON serializable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2999](https://github.com/gradio-app/gradio/pull/2999)
+- Fixes bug where png files were not being recognized when uploading images by [@abidlabs](https://github.com/abidlabs) in [PR 3002](https://github.com/gradio-app/gradio/pull/3002)
+- Fixes bug where temporary uploaded files were not being added to temp sets by [@abidlabs](https://github.com/abidlabs) in [PR 3005](https://github.com/gradio-app/gradio/pull/3005)
+- Fixes issue where markdown support in chatbot breaks older demos [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3006](https://github.com/gradio-app/gradio/pull/3006)
+- Fixes the `/file/` route that was broken in a recent change in [PR 3010](https://github.com/gradio-app/gradio/pull/3010)
+- Fix bug where the Image component could not serialize image urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2957](https://github.com/gradio-app/gradio/pull/2957)
+- Fix forwarding for guides after SEO renaming by [@aliabd](https://github.com/aliabd) in [PR 3017](https://github.com/gradio-app/gradio/pull/3017)
+- Switch all pages on the website to use latest stable gradio by [@aliabd](https://github.com/aliabd) in [PR 3016](https://github.com/gradio-app/gradio/pull/3016)
+- Fix bug related to deprecated parameters in `huggingface_hub` for the HuggingFaceDatasetSaver in [PR 3025](https://github.com/gradio-app/gradio/pull/3025)
+- Added better support for symlinks in the way absolute paths are resolved by [@abidlabs](https://github.com/abidlabs) in [PR 3037](https://github.com/gradio-app/gradio/pull/3037)
+- Fix several minor frontend bugs (loading animation, examples as gallery) frontend [@aliabid94](https://github.com/3026) in [PR 2961](https://github.com/gradio-app/gradio/pull/3026).
+- Fixes bug that the chatbot sample code does not work with certain input value by [@petrov826](https://github.com/petrov826) in [PR 3039](https://github.com/gradio-app/gradio/pull/3039).
+- Fix shadows for form element and ensure focus styles more visible in dark mode [@pngwn](https://github.com/pngwn) in [PR 3042](https://github.com/gradio-app/gradio/pull/3042).
+- Fixed bug where the Checkbox and Dropdown change events were not triggered in response to other component changes by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3045](https://github.com/gradio-app/gradio/pull/3045)
+- Fix bug where the queue was not properly restarted after launching a `closed` app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3022](https://github.com/gradio-app/gradio/pull/3022)
+- Adding missing embedded components on docs by [@aliabd](https://github.com/aliabd) in [PR 3027](https://github.com/gradio-app/gradio/pull/3027)
+- Fixes bug where app would crash if the `file_types` parameter of `gr.File` or `gr.UploadButton` was not a list by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3048](https://github.com/gradio-app/gradio/pull/3048)
+- Ensure CSS mounts correctly regardless of how many Gradio instances are on the page [@pngwn](https://github.com/pngwn) in [PR 3059](https://github.com/gradio-app/gradio/pull/3059).
+- Fix bug where input component was not hidden in the frontend for `UploadButton` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3053](https://github.com/gradio-app/gradio/pull/3053)
+- Fixes issue where after clicking submit or undo, the sketch output wouldn't clear. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3047](https://github.com/gradio-app/gradio/pull/3047)
+- Ensure spaces embedded via the web component always use the correct URLs for server requests and change ports for testing to avoid strange collisions when users are working with embedded apps locally by [@pngwn](https://github.com/pngwn) in [PR 3065](https://github.com/gradio-app/gradio/pull/3065)
+- Preserve selected image of Gallery through updated by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3061](https://github.com/gradio-app/gradio/pull/3061)
+- Fix bug where auth was not respected on HF spaces by [@freddyaboulton](https://github.com/freddyaboulton) and [@aliabid94](https://github.com/aliabid94) in [PR 3049](https://github.com/gradio-app/gradio/pull/3049)
+- Fixes bug where tabs selected attribute not working if manually change tab by [@tomchang25](https://github.com/tomchang25) in [3055](https://github.com/gradio-app/gradio/pull/3055)
+- Change chatbot to show dots on progress, and fix bug where chatbot would not stick to bottom in the case of images by [@aliabid94](https://github.com/aliabid94) in [PR 3067](https://github.com/gradio-app/gradio/pull/3079)
+
+### Documentation Changes:
+
+- SEO improvements to guides by[@aliabd](https://github.com/aliabd) in [PR 2915](https://github.com/gradio-app/gradio/pull/2915)
+- Use `gr.LinePlot` for the `blocks_kinematics` demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2998](https://github.com/gradio-app/gradio/pull/2998)
+- Updated the `interface_series_load` to include some inline markdown code by [@abidlabs](https://github.com/abidlabs) in [PR 3051](https://github.com/gradio-app/gradio/pull/3051)
+
+### Testing and Infrastructure Changes:
+
+- Adds a GitHub action to test if any large files (> 5MB) are present by [@abidlabs](https://github.com/abidlabs) in [PR 3013](https://github.com/gradio-app/gradio/pull/3013)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Rewrote frontend using CSS variables for themes by [@pngwn](https://github.com/pngwn) in [PR 2840](https://github.com/gradio-app/gradio/pull/2840)
+- Moved telemetry requests to run on background threads by [@abidlabs](https://github.com/abidlabs) in [PR 3054](https://github.com/gradio-app/gradio/pull/3054)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed file upload fails for files with zero size by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2923](https://github.com/gradio-app/gradio/pull/2923)
+- Fixed bug where `mount_gradio_app` would not launch if the queue was enabled in a gradio app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2939](https://github.com/gradio-app/gradio/pull/2939)
+- Fix custom long CSS handling in Blocks by [@anton-l](https://github.com/anton-l) in [PR 2953](https://github.com/gradio-app/gradio/pull/2953)
+- Recovers the dropdown change event by [@abidlabs](https://github.com/abidlabs) in [PR 2954](https://github.com/gradio-app/gradio/pull/2954).
+- Fix audio file output by [@aliabid94](https://github.com/aliabid94) in [PR 2961](https://github.com/gradio-app/gradio/pull/2961).
+- Fixed bug where file extensions of really long files were not kept after download by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2929](https://github.com/gradio-app/gradio/pull/2929)
+- Fix bug where outputs for examples where not being returned by the backend by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2955](https://github.com/gradio-app/gradio/pull/2955)
+- Fix bug in `blocks_plug` demo that prevented switching tabs programmatically with python [@TashaSkyUp](https://github.com/https://github.com/TashaSkyUp) in [PR 2971](https://github.com/gradio-app/gradio/pull/2971).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix audio file output by [@aliabid94](https://github.com/aliabid94) in [PR 2950](https://github.com/gradio-app/gradio/pull/2950).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.0
+
+### New Features:
+
+###### Send custom progress updates by adding a `gr.Progress` argument after the input arguments to any function. Example:
+
+```python
+def reverse(word, progress=gr.Progress()):
+ progress(0, desc="Starting")
+ time.sleep(1)
+ new_string = ""
+ for letter in progress.tqdm(word, desc="Reversing"):
+ time.sleep(0.25)
+ new_string = letter + new_string
+ return new_string
+
+demo = gr.Interface(reverse, gr.Text(), gr.Text())
+```
+
+Progress indicator bar by [@aliabid94](https://github.com/aliabid94) in [PR 2750](https://github.com/gradio-app/gradio/pull/2750).
+
+- Added `title` argument to `TabbedInterface` by @MohamedAliRashad in [#2888](https://github.com/gradio-app/gradio/pull/2888)
+- Add support for specifying file extensions for `gr.File` and `gr.UploadButton`, using `file_types` parameter (e.g `gr.File(file_count="multiple", file_types=["text", ".json", ".csv"])`) by @dawoodkhan82 in [#2901](https://github.com/gradio-app/gradio/pull/2901)
+- Added `multiselect` option to `Dropdown` by @dawoodkhan82 in [#2871](https://github.com/gradio-app/gradio/pull/2871)
+
+###### With `multiselect` set to `true` a user can now select multiple options from the `gr.Dropdown` component.
+
+```python
+gr.Dropdown(["angola", "pakistan", "canada"], multiselect=True, value=["angola"])
+```
+
+
+
+### Bug Fixes:
+
+- Fixed bug where an error opening an audio file led to a crash by [@FelixDombek](https://github.com/FelixDombek) in [PR 2898](https://github.com/gradio-app/gradio/pull/2898)
+- Fixed bug where setting `default_enabled=False` made it so that the entire queue did not start by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2876](https://github.com/gradio-app/gradio/pull/2876)
+- Fixed bug where csv preview for DataFrame examples would show filename instead of file contents by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2877](https://github.com/gradio-app/gradio/pull/2877)
+- Fixed bug where an error raised after yielding iterative output would not be displayed in the browser by
+ [@JaySmithWpg](https://github.com/JaySmithWpg) in [PR 2889](https://github.com/gradio-app/gradio/pull/2889)
+- Fixed bug in `blocks_style` demo that was preventing it from launching by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2890](https://github.com/gradio-app/gradio/pull/2890)
+- Fixed bug where files could not be downloaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2926](https://github.com/gradio-app/gradio/pull/2926)
+- Fixed bug where cached examples were not displaying properly by [@a-rogalska](https://github.com/a-rogalska) in [PR 2974](https://github.com/gradio-app/gradio/pull/2974)
+
+### Documentation Changes:
+
+- Added a Guide on using Google Sheets to create a real-time dashboard with Gradio's `DataFrame` and `LinePlot` component, by [@abidlabs](https://github.com/abidlabs) in [PR 2816](https://github.com/gradio-app/gradio/pull/2816)
+- Add a components - events matrix on the docs by [@aliabd](https://github.com/aliabd) in [PR 2921](https://github.com/gradio-app/gradio/pull/2921)
+
+### Testing and Infrastructure Changes:
+
+- Deployed PRs from forks to spaces by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2895](https://github.com/gradio-app/gradio/pull/2895)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- The `default_enabled` parameter of the `Blocks.queue` method has no effect by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2876](https://github.com/gradio-app/gradio/pull/2876)
+- Added typing to several Python files in codebase by [@abidlabs](https://github.com/abidlabs) in [PR 2887](https://github.com/gradio-app/gradio/pull/2887)
+- Excluding untracked files from demo notebook check action by [@aliabd](https://github.com/aliabd) in [PR 2897](https://github.com/gradio-app/gradio/pull/2897)
+- Optimize images and gifs by [@aliabd](https://github.com/aliabd) in [PR 2922](https://github.com/gradio-app/gradio/pull/2922)
+- Updated typing by [@1nF0rmed](https://github.com/1nF0rmed) in [PR 2904](https://github.com/gradio-app/gradio/pull/2904)
+
+### Contributors Shoutout:
+
+- @JaySmithWpg for making their first contribution to gradio!
+- @MohamedAliRashad for making their first contribution to gradio!
+
+## 3.15.0
+
+### New Features:
+
+Gradio's newest plotting component `gr.LinePlot`! 📈
+
+With this component you can easily create time series visualizations with customizable
+appearance for your demos and dashboards ... all without having to know an external plotting library.
+
+For an example of the api see below:
+
+```python
+gr.LinePlot(stocks,
+ x="date",
+ y="price",
+ color="symbol",
+ color_legend_position="bottom",
+ width=600, height=400, title="Stock Prices")
+```
+
+![image](https://user-images.githubusercontent.com/41651716/208711646-81ae3745-149b-46a3-babd-0569aecdd409.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2807](https://github.com/gradio-app/gradio/pull/2807)
+
+### Bug Fixes:
+
+- Fixed bug where the `examples_per_page` parameter of the `Examples` component was not passed to the internal `Dataset` component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2861](https://github.com/gradio-app/gradio/pull/2861)
+- Fixes loading Spaces that have components with default values by [@abidlabs](https://github.com/abidlabs) in [PR 2855](https://github.com/gradio-app/gradio/pull/2855)
+- Fixes flagging when `allow_flagging="auto"` in `gr.Interface()` by [@abidlabs](https://github.com/abidlabs) in [PR 2695](https://github.com/gradio-app/gradio/pull/2695)
+- Fixed bug where passing a non-list value to `gr.CheckboxGroup` would crash the entire app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2866](https://github.com/gradio-app/gradio/pull/2866)
+
+### Documentation Changes:
+
+- Added a Guide on using BigQuery with Gradio's `DataFrame` and `ScatterPlot` component,
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2794](https://github.com/gradio-app/gradio/pull/2794)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed importing gradio can cause PIL.Image.registered_extensions() to break by `[@aliencaocao](https://github.com/aliencaocao)` in `[PR 2846](https://github.com/gradio-app/gradio/pull/2846)`
+- Fix css glitch and navigation in docs by [@aliabd](https://github.com/aliabd) in [PR 2856](https://github.com/gradio-app/gradio/pull/2856)
+- Added the ability to set `x_lim`, `y_lim` and legend positions for `gr.ScatterPlot` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2807](https://github.com/gradio-app/gradio/pull/2807)
+- Remove footers and min-height the correct way by [@aliabd](https://github.com/aliabd) in [PR 2860](https://github.com/gradio-app/gradio/pull/2860)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.14.0
+
+### New Features:
+
+###### Add Waveform Visual Support to Audio
+
+Adds a `gr.make_waveform()` function that creates a waveform video by combining an audio and an optional background image by [@dawoodkhan82](http://github.com/dawoodkhan82) and [@aliabid94](http://github.com/aliabid94) in [PR 2706](https://github.com/gradio-app/gradio/pull/2706. Helpful for making audio outputs much more shareable.
+
+![waveform screenrecording](https://user-images.githubusercontent.com/7870876/206062396-164a5e71-451a-4fe0-94a7-cbe9269d57e6.gif)
+
+###### Allows Every Component to Accept an `every` Parameter
+
+When a component's initial value is a function, the `every` parameter re-runs the function every `every` seconds. By [@abidlabs](https://github.com/abidlabs) in [PR 2806](https://github.com/gradio-app/gradio/pull/2806). Here's a code example:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ df = gr.DataFrame(run_query, every=60*60)
+
+demo.queue().launch()
+```
+
+### Bug Fixes:
+
+- Fixed issue where too many temporary files were created, all with randomly generated
+ filepaths. Now fewer temporary files are created and are assigned a path that is a
+ hash based on the file contents by [@abidlabs](https://github.com/abidlabs) in [PR 2758](https://github.com/gradio-app/gradio/pull/2758)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.13.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+\*No changes to highlight.
+
+-
+
+### Documentation Changes:
+
+- Improves documentation of several queuing-related parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2825](https://github.com/gradio-app/gradio/pull/2825)
+
+### Testing and Infrastructure Changes:
+
+- Remove h11 pinning by [@ecederstrand](https://github.com/ecederstrand) in [PR 2820](https://github.com/gradio-app/gradio/pull/2820)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.13.1
+
+### New Features:
+
+###### New Shareable Links
+
+Replaces tunneling logic based on ssh port-forwarding to that based on `frp` by [XciD](https://github.com/XciD) and [Wauplin](https://github.com/Wauplin) in [PR 2509](https://github.com/gradio-app/gradio/pull/2509)
+
+You don't need to do anything differently, but when you set `share=True` in `launch()`,
+you'll get this message and a public link that look a little bit different:
+
+```bash
+Setting up a public link... we have recently upgraded the way public links are generated. If you encounter any problems, please downgrade to gradio version 3.13.0
+.
+Running on public URL: https://bec81a83-5b5c-471e.gradio.live
+```
+
+These links are a more secure and scalable way to create shareable demos!
+
+### Bug Fixes:
+
+- Allows `gr.Dataframe()` to take a `pandas.DataFrame` that includes numpy array and other types as its initial value, by [@abidlabs](https://github.com/abidlabs) in [PR 2804](https://github.com/gradio-app/gradio/pull/2804)
+- Add `altair` to requirements.txt by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2811](https://github.com/gradio-app/gradio/pull/2811)
+- Added aria-labels to icon buttons that are built into UI components by [@emilyuhde](http://github.com/emilyuhde) in [PR 2791](https://github.com/gradio-app/gradio/pull/2791)
+
+### Documentation Changes:
+
+- Fixed some typos in the "Plot Component for Maps" guide by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2811](https://github.com/gradio-app/gradio/pull/2811)
+
+### Testing and Infrastructure Changes:
+
+- Fixed test for IP address by [@abidlabs](https://github.com/abidlabs) in [PR 2808](https://github.com/gradio-app/gradio/pull/2808)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed typo in parameter `visible` in classes in `templates.py` by [@abidlabs](https://github.com/abidlabs) in [PR 2805](https://github.com/gradio-app/gradio/pull/2805)
+- Switched external service for getting IP address from `https://api.ipify.org` to `https://checkip.amazonaws.com/` by [@abidlabs](https://github.com/abidlabs) in [PR 2810](https://github.com/gradio-app/gradio/pull/2810)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+- Fixed typo in parameter `visible` in classes in `templates.py` by [@abidlabs](https://github.com/abidlabs) in [PR 2805](https://github.com/gradio-app/gradio/pull/2805)
+- Switched external service for getting IP address from `https://api.ipify.org` to `https://checkip.amazonaws.com/` by [@abidlabs](https://github.com/abidlabs) in [PR 2810](https://github.com/gradio-app/gradio/pull/2810)
+
+## 3.13.0
+
+### New Features:
+
+###### Scatter plot component
+
+It is now possible to create a scatter plot natively in Gradio!
+
+The `gr.ScatterPlot` component accepts a pandas dataframe and some optional configuration parameters
+and will automatically create a plot for you!
+
+This is the first of many native plotting components in Gradio!
+
+For an example of how to use `gr.ScatterPlot` see below:
+
+```python
+import gradio as gr
+from vega_datasets import data
+
+cars = data.cars()
+
+with gr.Blocks() as demo:
+ gr.ScatterPlot(show_label=False,
+ value=cars,
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ tooltip="Name",
+ title="Car Data",
+ y_title="Miles per Gallon",
+ color_legend_title="Origin of Car").style(container=False)
+
+demo.launch()
+```
+
+
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2764](https://github.com/gradio-app/gradio/pull/2764)
+
+###### Support for altair plots
+
+The `Plot` component can now accept altair plots as values!
+Simply return an altair plot from your event listener and gradio will display it in the front-end.
+See the example below:
+
+```python
+import gradio as gr
+import altair as alt
+from vega_datasets import data
+
+cars = data.cars()
+chart = (
+ alt.Chart(cars)
+ .mark_point()
+ .encode(
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ )
+)
+
+with gr.Blocks() as demo:
+ gr.Plot(value=chart)
+demo.launch()
+```
+
+
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2741](https://github.com/gradio-app/gradio/pull/2741)
+
+###### Set the background color of a Label component
+
+The `Label` component now accepts a `color` argument by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2736](https://github.com/gradio-app/gradio/pull/2736).
+The `color` argument should either be a valid css color name or hexadecimal string.
+You can update the color with `gr.Label.update`!
+
+This lets you create Alert and Warning boxes with the `Label` component. See below:
+
+```python
+import gradio as gr
+import random
+
+def update_color(value):
+ if value < 0:
+ # This is bad so use red
+ return "#FF0000"
+ elif 0 <= value <= 20:
+ # Ok but pay attention (use orange)
+ return "#ff9966"
+ else:
+ # Nothing to worry about
+ return None
+
+def update_value():
+ choice = random.choice(['good', 'bad', 'so-so'])
+ color = update_color(choice)
+ return gr.Label.update(value=choice, color=color)
+
+
+with gr.Blocks() as demo:
+ label = gr.Label(value=-10)
+ demo.load(lambda: update_value(), inputs=None, outputs=[label], every=1)
+demo.queue().launch()
+```
+
+![label_bg_color_update](https://user-images.githubusercontent.com/41651716/204400372-80e53857-f26f-4a38-a1ae-1acadff75e89.gif)
+
+###### Add Brazilian Portuguese translation
+
+Add Brazilian Portuguese translation (pt-BR.json) by [@pstwh](http://github.com/pstwh) in [PR 2753](https://github.com/gradio-app/gradio/pull/2753):
+
+
+
+### Bug Fixes:
+
+- Fixed issue where image thumbnails were not showing when an example directory was provided
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2745](https://github.com/gradio-app/gradio/pull/2745)
+- Fixed bug loading audio input models from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2779](https://github.com/gradio-app/gradio/pull/2779).
+- Fixed issue where entities were not merged when highlighted text was generated from the
+ dictionary inputs [@payoto](https://github.com/payoto) in [PR 2767](https://github.com/gradio-app/gradio/pull/2767)
+- Fixed bug where generating events did not finish running even if the websocket connection was closed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2783](https://github.com/gradio-app/gradio/pull/2783).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Images in the chatbot component are now resized if they exceed a max width by [@abidlabs](https://github.com/abidlabs) in [PR 2748](https://github.com/gradio-app/gradio/pull/2748)
+- Missing parameters have been added to `gr.Blocks().load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2755](https://github.com/gradio-app/gradio/pull/2755)
+- Deindex share URLs from search by [@aliabd](https://github.com/aliabd) in [PR 2772](https://github.com/gradio-app/gradio/pull/2772)
+- Redirect old links and fix broken ones by [@aliabd](https://github.com/aliabd) in [PR 2774](https://github.com/gradio-app/gradio/pull/2774)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.12.0
+
+### New Features:
+
+###### The `Chatbot` component now supports a subset of Markdown (including bold, italics, code, images)
+
+You can now pass in some Markdown to the Chatbot component and it will show up,
+meaning that you can pass in images as well! by [@abidlabs](https://github.com/abidlabs) in [PR 2731](https://github.com/gradio-app/gradio/pull/2731)
+
+Here's a simple example that references a local image `lion.jpg` that is in the same
+folder as the Python script:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Chatbot([("hi", "hello **abubakar**"), ("![](/file=lion.jpg)", "cool pic")])
+
+demo.launch()
+```
+
+![Alt text](https://user-images.githubusercontent.com/1778297/204357455-5c1a4002-eee7-479d-9a1e-ba2c12522723.png)
+
+To see a more realistic example, see the new demo `/demo/chatbot_multimodal/run.py`.
+
+###### Latex support
+
+Added mathtext (a subset of latex) support to gr.Markdown. Added by [@kashif](https://github.com/kashif) and [@aliabid94](https://github.com/aliabid94) in [PR 2696](https://github.com/gradio-app/gradio/pull/2696).
+
+Example of how it can be used:
+
+```python
+gr.Markdown(
+ r"""
+ # Hello World! $\frac{\sqrt{x + y}}{4}$ is today's lesson.
+ """)
+```
+
+###### Update Accordion properties from the backend
+
+You can now update the Accordion `label` and `open` status with `gr.Accordion.update` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2690](https://github.com/gradio-app/gradio/pull/2690)
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Accordion(label="Open for greeting", open=False) as accordion:
+ gr.Textbox("Hello!")
+ open_btn = gr.Button(value="Open Accordion")
+ close_btn = gr.Button(value="Close Accordion")
+ open_btn.click(
+ lambda: gr.Accordion.update(open=True, label="Open Accordion"),
+ inputs=None,
+ outputs=[accordion],
+ )
+ close_btn.click(
+ lambda: gr.Accordion.update(open=False, label="Closed Accordion"),
+ inputs=None,
+ outputs=[accordion],
+ )
+demo.launch()
+```
+
+![update_accordion](https://user-images.githubusercontent.com/41651716/203164176-b102eae3-babe-4986-ae30-3ab4f400cedc.gif)
+
+### Bug Fixes:
+
+- Fixed bug where requests timeout is missing from utils.version_check() by [@yujiehecs](https://github.com/yujiehecs) in [PR 2729](https://github.com/gradio-app/gradio/pull/2729)
+- Fixed bug where so that the `File` component can properly preprocess files to "binary" byte-string format by [CoffeeVampir3](https://github.com/CoffeeVampir3) in [PR 2727](https://github.com/gradio-app/gradio/pull/2727)
+- Fixed bug to ensure that filenames are less than 200 characters even for non-English languages by [@SkyTNT](https://github.com/SkyTNT) in [PR 2685](https://github.com/gradio-app/gradio/pull/2685)
+
+### Documentation Changes:
+
+- Performance improvements to docs on mobile by [@aliabd](https://github.com/aliabd) in [PR 2730](https://github.com/gradio-app/gradio/pull/2730)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Make try examples button more prominent by [@aliabd](https://github.com/aliabd) in [PR 2705](https://github.com/gradio-app/gradio/pull/2705)
+- Fix id clashes in docs by [@aliabd](https://github.com/aliabd) in [PR 2713](https://github.com/gradio-app/gradio/pull/2713)
+- Fix typos in guide docs by [@andridns](https://github.com/andridns) in [PR 2722](https://github.com/gradio-app/gradio/pull/2722)
+- Add option to `include_audio` in Video component. When `True`, for `source="webcam"` this will record audio and video, for `source="upload"` this will retain the audio in an uploaded video by [@mandargogate](https://github.com/MandarGogate) in [PR 2721](https://github.com/gradio-app/gradio/pull/2721)
+
+### Contributors Shoutout:
+
+- [@andridns](https://github.com/andridns) made their first contribution in [PR 2722](https://github.com/gradio-app/gradio/pull/2722)!
+
+## 3.11.0
+
+### New Features:
+
+###### Upload Button
+
+There is now a new component called the `UploadButton` which is a file upload component but in button form! You can also specify what file types it should accept in the form of a list (ex: `image`, `video`, `audio`, `text`, or generic `file`). Added by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2591](https://github.com/gradio-app/gradio/pull/2591).
+
+Example of how it can be used:
+
+```python
+import gradio as gr
+
+def upload_file(files):
+ file_paths = [file.name for file in files]
+ return file_paths
+
+with gr.Blocks() as demo:
+ file_output = gr.File()
+ upload_button = gr.UploadButton("Click to Upload a File", file_types=["image", "video"], file_count="multiple")
+ upload_button.upload(upload_file, upload_button, file_output)
+
+demo.launch()
+```
+
+###### Revamped API documentation page
+
+New API Docs page with in-browser playground and updated aesthetics. [@gary149](https://github.com/gary149) in [PR 2652](https://github.com/gradio-app/gradio/pull/2652)
+
+###### Revamped Login page
+
+Previously our login page had its own CSS, had no dark mode, and had an ugly json message on the wrong credentials. Made the page more aesthetically consistent, added dark mode support, and a nicer error message. [@aliabid94](https://github.com/aliabid94) in [PR 2684](https://github.com/gradio-app/gradio/pull/2684)
+
+###### Accessing the Requests Object Directly
+
+You can now access the Request object directly in your Python function by [@abidlabs](https://github.com/abidlabs) in [PR 2641](https://github.com/gradio-app/gradio/pull/2641). This means that you can access request headers, the client IP address, and so on. In order to use it, add a parameter to your function and set its type hint to be `gr.Request`. Here's a simple example:
+
+```py
+import gradio as gr
+
+def echo(name, request: gr.Request):
+ if request:
+ print("Request headers dictionary:", request.headers)
+ print("IP address:", request.client.host)
+ return name
+
+io = gr.Interface(echo, "textbox", "textbox").launch()
+```
+
+### Bug Fixes:
+
+- Fixed bug that limited files from being sent over websockets to 16MB. The new limit
+ is now 1GB by [@abidlabs](https://github.com/abidlabs) in [PR 2709](https://github.com/gradio-app/gradio/pull/2709)
+
+### Documentation Changes:
+
+- Updated documentation for embedding Gradio demos on Spaces as web components by
+ [@julien-c](https://github.com/julien-c) in [PR 2698](https://github.com/gradio-app/gradio/pull/2698)
+- Updated IFrames in Guides to use the host URL instead of the Space name to be consistent with the new method for embedding Spaces, by
+ [@julien-c](https://github.com/julien-c) in [PR 2692](https://github.com/gradio-app/gradio/pull/2692)
+- Colab buttons on every demo in the website! Just click open in colab, and run the demo there.
+
+https://user-images.githubusercontent.com/9021060/202878400-cb16ed47-f4dd-4cb0-b2f0-102a9ff64135.mov
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Better warnings and error messages for `gr.Interface.load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2694](https://github.com/gradio-app/gradio/pull/2694)
+- Add open in colab buttons to demos in docs and /demos by [@aliabd](https://github.com/aliabd) in [PR 2608](https://github.com/gradio-app/gradio/pull/2608)
+- Apply different formatting for the types in component docstrings by [@aliabd](https://github.com/aliabd) in [PR 2707](https://github.com/gradio-app/gradio/pull/2707)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.10.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Passes kwargs into `gr.Interface.load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2669](https://github.com/gradio-app/gradio/pull/2669)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Clean up printed statements in Embedded Colab Mode by [@aliabid94](https://github.com/aliabid94) in [PR 2612](https://github.com/gradio-app/gradio/pull/2612)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.10.0
+
+- Add support for `'password'` and `'email'` types to `Textbox`. [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653)
+- `gr.Textbox` component will now raise an exception if `type` is not "text", "email", or "password" [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653). This will cause demos using the deprecated `gr.Textbox(type="number")` to raise an exception.
+
+### Bug Fixes:
+
+- Updated the minimum FastApi used in tests to version 0.87 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2647](https://github.com/gradio-app/gradio/pull/2647)
+- Fixed bug where interfaces with examples could not be loaded with `gr.Interface.load` by [@freddyaboulton](https://github.com/freddyaboulton) [PR 2640](https://github.com/gradio-app/gradio/pull/2640)
+- Fixed bug where the `interactive` property of a component could not be updated by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2639](https://github.com/gradio-app/gradio/pull/2639)
+- Fixed bug where some URLs were not being recognized as valid URLs and thus were not
+ loading correctly in various components by [@abidlabs](https://github.com/abidlabs) in [PR 2659](https://github.com/gradio-app/gradio/pull/2659)
+
+### Documentation Changes:
+
+- Fix some typos in the embedded demo names in "05_using_blocks_like_functions.md" by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2656](https://github.com/gradio-app/gradio/pull/2656)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Add support for `'password'` and `'email'` types to `Textbox`. [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.9.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Only set a min height on md and html when loading by [@pngwn](https://github.com/pngwn) in [PR 2623](https://github.com/gradio-app/gradio/pull/2623)
+
+### Documentation Changes:
+
+- See docs for the latest gradio commit to main as well the latest pip release:
+
+![main-vs-pip](https://user-images.githubusercontent.com/9021060/199607887-aab1ae4e-a070-4527-966d-024397abe15b.gif)
+
+- Modified the "Connecting To a Database Guide" to use `pd.read_sql` as opposed to low-level postgres connector by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2604](https://github.com/gradio-app/gradio/pull/2604)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Dropdown for seeing docs as latest or main by [@aliabd](https://github.com/aliabd) in [PR 2544](https://github.com/gradio-app/gradio/pull/2544)
+- Allow `gr.Templates` to accept parameters to override the defaults by [@abidlabs](https://github.com/abidlabs) in [PR 2600](https://github.com/gradio-app/gradio/pull/2600)
+- Components now throw a `ValueError()` if constructed with invalid parameters for `type` or `source` (for components that take those parameters) in [PR 2610](https://github.com/gradio-app/gradio/pull/2610)
+- Allow auth with using queue by [@GLGDLY](https://github.com/GLGDLY) in [PR 2611](https://github.com/gradio-app/gradio/pull/2611)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.9
+
+### New Features:
+
+- Gradio is now embedded directly in colab without requiring the share link by [@aliabid94](https://github.com/aliabid94) in [PR 2455](https://github.com/gradio-app/gradio/pull/2455)
+
+###### Calling functions by api_name in loaded apps
+
+When you load an upstream app with `gr.Blocks.load`, you can now specify which fn
+to call with the `api_name` parameter.
+
+```python
+import gradio as gr
+english_translator = gr.Blocks.load(name="spaces/gradio/english-translator")
+german = english_translator("My name is Freddy", api_name='translate-to-german')
+```
+
+The `api_name` parameter will take precedence over the `fn_index` parameter.
+
+### Bug Fixes:
+
+- Fixed bug where None could not be used for File,Model3D, and Audio examples by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2588](https://github.com/gradio-app/gradio/pull/2588)
+- Fixed links in Plotly map guide + demo by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2578](https://github.com/gradio-app/gradio/pull/2578)
+- `gr.Blocks.load()` now correctly loads example files from Spaces [@abidlabs](https://github.com/abidlabs) in [PR 2594](https://github.com/gradio-app/gradio/pull/2594)
+- Fixed bug when image clear started upload dialog [@mezotaken](https://github.com/mezotaken) in [PR 2577](https://github.com/gradio-app/gradio/pull/2577)
+
+### Documentation Changes:
+
+- Added a Guide on how to configure the queue for maximum performance by [@abidlabs](https://github.com/abidlabs) in [PR 2558](https://github.com/gradio-app/gradio/pull/2558)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Add `api_name` to `Blocks.__call__` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2593](https://github.com/gradio-app/gradio/pull/2593)
+- Update queue with using deque & update requirements by [@GLGDLY](https://github.com/GLGDLY) in [PR 2428](https://github.com/gradio-app/gradio/pull/2428)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.8.2
+
+### Bug Fixes:
+
+- Ensure gradio apps embedded via spaces use the correct endpoint for predictions. [@pngwn](https://github.com/pngwn) in [PR 2567](https://github.com/gradio-app/gradio/pull/2567)
+- Ensure gradio apps embedded via spaces use the correct websocket protocol. [@pngwn](https://github.com/pngwn) in [PR 2571](https://github.com/gradio-app/gradio/pull/2571)
+
+### New Features:
+
+###### Running Events Continuously
+
+Gradio now supports the ability to run an event continuously on a fixed schedule. To use this feature,
+pass `every=# of seconds` to the event definition. This will run the event every given number of seconds!
+
+This can be used to:
+
+- Create live visualizations that show the most up to date data
+- Refresh the state of the frontend automatically in response to changes in the backend
+
+Here is an example of a live plot that refreshes every half second:
+
+```python
+import math
+import gradio as gr
+import plotly.express as px
+import numpy as np
+
+
+plot_end = 2 * math.pi
+
+
+def get_plot(period=1):
+ global plot_end
+ x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)
+ y = np.sin(2*math.pi*period * x)
+ fig = px.line(x=x, y=y)
+ plot_end += 2 * math.pi
+ return fig
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ gr.Markdown("Change the value of the slider to automatically update the plot")
+ period = gr.Slider(label="Period of plot", value=1, minimum=0, maximum=10, step=1)
+ plot = gr.Plot(label="Plot (updates every half second)")
+
+ dep = demo.load(get_plot, None, plot, every=0.5)
+ period.change(get_plot, period, plot, every=0.5, cancels=[dep])
+
+demo.queue().launch()
+```
+
+![live_demo](https://user-images.githubusercontent.com/41651716/198357377-633ce460-4e31-47bd-8202-1440cdd6fe19.gif)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+- Explained how to set up `queue` and `auth` when working with reload mode by by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Allows loading private Spaces by passing an an `api_key` to `gr.Interface.load()`
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2568](https://github.com/gradio-app/gradio/pull/2568)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.8
+
+### New Features:
+
+- Allows event listeners to accept a single dictionary as its argument, where the keys are the components and the values are the component values. This is set by passing the input components in the event listener as a set instead of a list. [@aliabid94](https://github.com/aliabid94) in [PR 2550](https://github.com/gradio-app/gradio/pull/2550)
+
+### Bug Fixes:
+
+- Fix whitespace issue when using plotly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2548](https://github.com/gradio-app/gradio/pull/2548)
+- Apply appropriate alt text to all gallery images. [@camenduru](https://github.com/camenduru) in [PR 2358](https://github.com/gradio-app/gradio/pull/2538)
+- Removed erroneous tkinter import in gradio.blocks by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2555](https://github.com/gradio-app/gradio/pull/2555)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Added the `every` keyword to event listeners that runs events on a fixed schedule by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2512](https://github.com/gradio-app/gradio/pull/2512)
+- Fix whitespace issue when using plotly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2548](https://github.com/gradio-app/gradio/pull/2548)
+- Apply appropriate alt text to all gallery images. [@camenduru](https://github.com/camenduru) in [PR 2358](https://github.com/gradio-app/gradio/pull/2538)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.7
+
+### New Features:
+
+###### Batched Functions
+
+Gradio now supports the ability to pass _batched_ functions. Batched functions are just
+functions which take in a list of inputs and return a list of predictions.
+
+For example, here is a batched function that takes in two lists of inputs (a list of
+words and a list of ints), and returns a list of trimmed words as output:
+
+```py
+import time
+
+def trim_words(words, lens):
+ trimmed_words = []
+ time.sleep(5)
+ for w, l in zip(words, lens):
+ trimmed_words.append(w[:l])
+ return [trimmed_words]
+```
+
+The advantage of using batched functions is that if you enable queuing, the Gradio
+server can automatically _batch_ incoming requests and process them in parallel,
+potentially speeding up your demo. Here's what the Gradio code looks like (notice
+the `batch=True` and `max_batch_size=16` -- both of these parameters can be passed
+into event triggers or into the `Interface` class)
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ word = gr.Textbox(label="word", value="abc")
+ leng = gr.Number(label="leng", precision=0, value=1)
+ output = gr.Textbox(label="Output")
+ with gr.Row():
+ run = gr.Button()
+
+ event = run.click(trim_words, [word, leng], output, batch=True, max_batch_size=16)
+
+demo.queue()
+demo.launch()
+```
+
+In the example above, 16 requests could be processed in parallel (for a total inference
+time of 5 seconds), instead of each request being processed separately (for a total
+inference time of 80 seconds).
+
+###### Upload Event
+
+`Video`, `Audio`, `Image`, and `File` components now support a `upload()` event that is triggered when a user uploads a file into any of these components.
+
+Example usage:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ input_video = gr.Video()
+ output_video = gr.Video()
+
+ # Clears the output video when an input video is uploaded
+ input_video.upload(lambda : None, None, output_video)
+```
+
+### Bug Fixes:
+
+- Fixes issue where plotly animations, interactivity, titles, legends, were not working properly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2486](https://github.com/gradio-app/gradio/pull/2486)
+- Prevent requests to the `/api` endpoint from skipping the queue if the queue is enabled for that event by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2493](https://github.com/gradio-app/gradio/pull/2493)
+- Fixes a bug with `cancels` in event triggers so that it works properly if multiple
+ Blocks are rendered by [@abidlabs](https://github.com/abidlabs) in [PR 2530](https://github.com/gradio-app/gradio/pull/2530)
+- Prevent invalid targets of events from crashing the whole application. [@pngwn](https://github.com/pngwn) in [PR 2534](https://github.com/gradio-app/gradio/pull/2534)
+- Properly dequeue cancelled events when multiple apps are rendered by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2540](https://github.com/gradio-app/gradio/pull/2540)
+- Fixes videos being cropped due to height/width params not being used [@hannahblair](https://github.com/hannahblair) in [PR 4946](https://github.com/gradio-app/gradio/pull/4946)
+
+### Documentation Changes:
+
+- Added an example interactive dashboard to the "Tabular & Plots" section of the Demos page by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2508](https://github.com/gradio-app/gradio/pull/2508)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixes the error message if a user builds Gradio locally and tries to use `share=True` by [@abidlabs](https://github.com/abidlabs) in [PR 2502](https://github.com/gradio-app/gradio/pull/2502)
+- Allows the render() function to return self by [@Raul9595](https://github.com/Raul9595) in [PR 2514](https://github.com/gradio-app/gradio/pull/2514)
+- Fixes issue where plotly animations, interactivity, titles, legends, were not working properly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2486](https://github.com/gradio-app/gradio/pull/2486)
+- Gradio now supports batched functions by [@abidlabs](https://github.com/abidlabs) in [PR 2218](https://github.com/gradio-app/gradio/pull/2218)
+- Add `upload` event for `Video`, `Audio`, `Image`, and `File` components [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2448](https://github.com/gradio-app/gradio/pull/2456)
+- Changes websocket path for Spaces as it is no longer necessary to have a different URL for websocket connections on Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 2528](https://github.com/gradio-app/gradio/pull/2528)
+- Clearer error message when events are defined outside of a Blocks scope, and a warning if you
+ try to use `Series` or `Parallel` with `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 2543](https://github.com/gradio-app/gradio/pull/2543)
+- Adds support for audio samples that are in `float64`, `float16`, or `uint16` formats by [@abidlabs](https://github.com/abidlabs) in [PR 2545](https://github.com/gradio-app/gradio/pull/2545)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.6
+
+### New Features:
+
+###### Cancelling Running Events
+
+Running events can be cancelled when other events are triggered! To test this feature, pass the `cancels` parameter to the event listener.
+For this feature to work, the queue must be enabled.
+
+![cancel_on_change_rl](https://user-images.githubusercontent.com/41651716/195952623-61a606bd-e82b-4e1a-802e-223154cb8727.gif)
+
+Code:
+
+```python
+import time
+import gradio as gr
+
+def fake_diffusion(steps):
+ for i in range(steps):
+ time.sleep(1)
+ yield str(i)
+
+def long_prediction(*args, **kwargs):
+ time.sleep(10)
+ return 42
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ n = gr.Slider(1, 10, value=9, step=1, label="Number Steps")
+ run = gr.Button()
+ output = gr.Textbox(label="Iterative Output")
+ stop = gr.Button(value="Stop Iterating")
+ with gr.Column():
+ prediction = gr.Number(label="Expensive Calculation")
+ run_pred = gr.Button(value="Run Expensive Calculation")
+ with gr.Column():
+ cancel_on_change = gr.Textbox(label="Cancel Iteration and Expensive Calculation on Change")
+
+ click_event = run.click(fake_diffusion, n, output)
+ stop.click(fn=None, inputs=None, outputs=None, cancels=[click_event])
+ pred_event = run_pred.click(fn=long_prediction, inputs=None, outputs=prediction)
+
+ cancel_on_change.change(None, None, None, cancels=[click_event, pred_event])
+
+
+demo.queue(concurrency_count=1, max_size=20).launch()
+```
+
+For interfaces, a stop button will be added automatically if the function uses a `yield` statement.
+
+```python
+import gradio as gr
+import time
+
+def iteration(steps):
+ for i in range(steps):
+ time.sleep(0.5)
+ yield i
+
+gr.Interface(iteration,
+ inputs=gr.Slider(minimum=1, maximum=10, step=1, value=5),
+ outputs=gr.Number()).queue().launch()
+```
+
+![stop_interface_rl](https://user-images.githubusercontent.com/41651716/195952883-e7ca4235-aae3-4852-8f28-96d01d0c5822.gif)
+
+### Bug Fixes:
+
+- Add loading status tracker UI to HTML and Markdown components. [@pngwn](https://github.com/pngwn) in [PR 2474](https://github.com/gradio-app/gradio/pull/2474)
+- Fixed videos being mirrored in the front-end if source is not webcam by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2475](https://github.com/gradio-app/gradio/pull/2475)
+- Add clear button for timeseries component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2487](https://github.com/gradio-app/gradio/pull/2487)
+- Removes special characters from temporary filenames so that the files can be served by components [@abidlabs](https://github.com/abidlabs) in [PR 2480](https://github.com/gradio-app/gradio/pull/2480)
+- Fixed infinite reload loop when mounting gradio as a sub application by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2477](https://github.com/gradio-app/gradio/pull/2477)
+
+### Documentation Changes:
+
+- Adds a demo to show how a sound alert can be played upon completion of a prediction by [@abidlabs](https://github.com/abidlabs) in [PR 2478](https://github.com/gradio-app/gradio/pull/2478)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Enable running events to be cancelled from other events by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2433](https://github.com/gradio-app/gradio/pull/2433)
+- Small fix for version check before reuploading demos by [@aliabd](https://github.com/aliabd) in [PR 2469](https://github.com/gradio-app/gradio/pull/2469)
+- Add loading status tracker UI to HTML and Markdown components. [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2474)
+- Add clear button for timeseries component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2487](https://github.com/gradio-app/gradio/pull/2487)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.5
+
+### Bug Fixes:
+
+- Ensure that Gradio does not take control of the HTML page title when embedding a gradio app as a web component, this behaviour flipped by adding `control_page_title="true"` to the webcomponent. [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2400)
+- Decreased latency in iterative-output demos by making the iteration asynchronous [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2409](https://github.com/gradio-app/gradio/pull/2409)
+- Fixed queue getting stuck under very high load by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2374](https://github.com/gradio-app/gradio/pull/2374)
+- Ensure that components always behave as if `interactive=True` were set when the following conditions are true:
+
+ - no default value is provided,
+ - they are not set as the input or output of an event,
+ - `interactive` kwarg is not set.
+
+ [@pngwn](https://github.com/pngwn) in [PR 2459](https://github.com/gradio-app/gradio/pull/2459)
+
+### New Features:
+
+- When an `Image` component is set to `source="upload"`, it is now possible to drag and drop and image to replace a previously uploaded image by [@pngwn](https://github.com/pngwn) in [PR 1711](https://github.com/gradio-app/gradio/issues/1711)
+- The `gr.Dataset` component now accepts `HTML` and `Markdown` components by [@abidlabs](https://github.com/abidlabs) in [PR 2437](https://github.com/gradio-app/gradio/pull/2437)
+
+### Documentation Changes:
+
+- Improved documentation for the `gr.Dataset` component by [@abidlabs](https://github.com/abidlabs) in [PR 2437](https://github.com/gradio-app/gradio/pull/2437)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+- The `Carousel` component is officially deprecated. Since gradio 3.0, code containing the `Carousel` component would throw warnings. As of the next release, the `Carousel` component will raise an exception.
+
+### Full Changelog:
+
+- Speeds up Gallery component by using temporary files instead of base64 representation in the front-end by [@proxyphi](https://github.com/proxyphi), [@pngwn](https://github.com/pngwn), and [@abidlabs](https://github.com/abidlabs) in [PR 2265](https://github.com/gradio-app/gradio/pull/2265)
+- Fixed some embedded demos in the guides by not loading the gradio web component in some guides by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2403](https://github.com/gradio-app/gradio/pull/2403)
+- When an `Image` component is set to `source="upload"`, it is now possible to drag and drop and image to replace a previously uploaded image by [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2410)
+- Improve documentation of the `Blocks.load()` event by [@abidlabs](https://github.com/abidlabs) in [PR 2413](https://github.com/gradio-app/gradio/pull/2413)
+- Decreased latency in iterative-output demos by making the iteration asynchronous [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2409](https://github.com/gradio-app/gradio/pull/2409)
+- Updated share link message to reference new Spaces Hardware [@abidlabs](https://github.com/abidlabs) in [PR 2423](https://github.com/gradio-app/gradio/pull/2423)
+- Automatically restart spaces if they're down by [@aliabd](https://github.com/aliabd) in [PR 2405](https://github.com/gradio-app/gradio/pull/2405)
+- Carousel component is now deprecated by [@abidlabs](https://github.com/abidlabs) in [PR 2434](https://github.com/gradio-app/gradio/pull/2434)
+- Build Gradio from source in ui tests by by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2440](https://github.com/gradio-app/gradio/pull/2440)
+- Change "return ValueError" to "raise ValueError" by [@vzakharov](https://github.com/vzakharov) in [PR 2445](https://github.com/gradio-app/gradio/pull/2445)
+- Add guide on creating a map demo using the `gr.Plot()` component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2402](https://github.com/gradio-app/gradio/pull/2402)
+- Add blur event for `Textbox` and `Number` components [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2448](https://github.com/gradio-app/gradio/pull/2448)
+- Stops a gradio launch from hogging a port even after it's been killed [@aliabid94](https://github.com/aliabid94) in [PR 2453](https://github.com/gradio-app/gradio/pull/2453)
+- Fix embedded interfaces on touch screen devices by [@aliabd](https://github.com/aliabd) in [PR 2457](https://github.com/gradio-app/gradio/pull/2457)
+- Upload all demos to spaces by [@aliabd](https://github.com/aliabd) in [PR 2281](https://github.com/gradio-app/gradio/pull/2281)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.4.1
+
+### New Features:
+
+###### 1. See Past and Upcoming Changes in the Release History 👀
+
+You can now see gradio's release history directly on the website, and also keep track of upcoming changes. Just go [here](https://gradio.app/changelog/).
+
+![release-history](https://user-images.githubusercontent.com/9021060/193145458-3de699f7-7620-45de-aa73-a1c1b9b96257.gif)
+
+### Bug Fixes:
+
+1. Fix typo in guide image path by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2357](https://github.com/gradio-app/gradio/pull/2357)
+2. Raise error if Blocks has duplicate component with same IDs by [@abidlabs](https://github.com/abidlabs) in [PR 2359](https://github.com/gradio-app/gradio/pull/2359)
+3. Catch the permission exception on the audio component by [@Ian-GL](https://github.com/Ian-GL) in [PR 2330](https://github.com/gradio-app/gradio/pull/2330)
+4. Fix image_classifier_interface_load demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2365](https://github.com/gradio-app/gradio/pull/2365)
+5. Fix combining adjacent components without gaps by introducing `gr.Row(variant="compact")` by [@aliabid94](https://github.com/aliabid94) in [PR 2291](https://github.com/gradio-app/gradio/pull/2291) This comes with deprecation of the following arguments for `Component.style`: `round`, `margin`, `border`.
+6. Fix audio streaming, which was previously choppy in [PR 2351](https://github.com/gradio-app/gradio/pull/2351). Big thanks to [@yannickfunk](https://github.com/yannickfunk) for the proposed solution.
+7. Fix bug where new typeable slider doesn't respect the minimum and maximum values [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2380](https://github.com/gradio-app/gradio/pull/2380)
+
+### Documentation Changes:
+
+1. New Guide: Connecting to a Database 🗄️
+
+ A new guide by [@freddyaboulton](https://github.com/freddyaboulton) that explains how you can use Gradio to connect your app to a database. Read more [here](https://gradio.app/connecting_to_a_database/).
+
+2. New Guide: Running Background Tasks 🥷
+
+ A new guide by [@freddyaboulton](https://github.com/freddyaboulton) that explains how you can run background tasks from your gradio app. Read more [here](https://gradio.app/running_background_tasks/).
+
+3. Small fixes to docs for `Image` component by [@abidlabs](https://github.com/abidlabs) in [PR 2372](https://github.com/gradio-app/gradio/pull/2372)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Create a guide on how to connect an app to a database hosted on the cloud by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2341](https://github.com/gradio-app/gradio/pull/2341)
+- Removes `analytics` dependency by [@abidlabs](https://github.com/abidlabs) in [PR 2347](https://github.com/gradio-app/gradio/pull/2347)
+- Add guide on launching background tasks from your app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2350](https://github.com/gradio-app/gradio/pull/2350)
+- Fix typo in guide image path by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2357](https://github.com/gradio-app/gradio/pull/2357)
+- Raise error if Blocks has duplicate component with same IDs by [@abidlabs](https://github.com/abidlabs) in [PR 2359](https://github.com/gradio-app/gradio/pull/2359)
+- Hotfix: fix version back to 3.4 by [@abidlabs](https://github.com/abidlabs) in [PR 2361](https://github.com/gradio-app/gradio/pull/2361)
+- Change version.txt to 3.4 instead of 3.4.0 by [@aliabd](https://github.com/aliabd) in [PR 2363](https://github.com/gradio-app/gradio/pull/2363)
+- Catch the permission exception on the audio component by [@Ian-GL](https://github.com/Ian-GL) in [PR 2330](https://github.com/gradio-app/gradio/pull/2330)
+- Fix image_classifier_interface_load demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2365](https://github.com/gradio-app/gradio/pull/2365)
+- Small fixes to docs for `Image` component by [@abidlabs](https://github.com/abidlabs) in [PR 2372](https://github.com/gradio-app/gradio/pull/2372)
+- Automated Release Notes by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2306](https://github.com/gradio-app/gradio/pull/2306)
+- Fixed small typos in the docs [@julien-c](https://github.com/julien-c) in [PR 2373](https://github.com/gradio-app/gradio/pull/2373)
+- Adds ability to disable pre/post-processing for examples [@abidlabs](https://github.com/abidlabs) in [PR 2383](https://github.com/gradio-app/gradio/pull/2383)
+- Copy changelog file in website docker by [@aliabd](https://github.com/aliabd) in [PR 2384](https://github.com/gradio-app/gradio/pull/2384)
+- Lets users provide a `gr.update()` dictionary even if post-processing is disabled [@abidlabs](https://github.com/abidlabs) in [PR 2385](https://github.com/gradio-app/gradio/pull/2385)
+- Fix bug where errors would cause apps run in reload mode to hang forever by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2394](https://github.com/gradio-app/gradio/pull/2394)
+- Fix bug where new typeable slider doesn't respect the minimum and maximum values [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2380](https://github.com/gradio-app/gradio/pull/2380)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.4
+
+### New Features:
+
+###### 1. Gallery Captions 🖼️
+
+You can now pass captions to images in the Gallery component. To do so you need to pass a {List} of (image, {str} caption) tuples. This is optional and the component also accepts just a list of the images.
+
+Here's an example:
+
+```python
+import gradio as gr
+
+images_with_captions = [
+ ("https://images.unsplash.com/photo-1551969014-7d2c4cddf0b6", "Cheetah by David Groves"),
+ ("https://images.unsplash.com/photo-1546182990-dffeafbe841d", "Lion by Francesco"),
+ ("https://images.unsplash.com/photo-1561731216-c3a4d99437d5", "Tiger by Mike Marrah")
+ ]
+
+with gr.Blocks() as demo:
+ gr.Gallery(value=images_with_captions)
+
+demo.launch()
+```
+
+
+
+###### 2. Type Values into the Slider 🔢
+
+You can now type values directly on the Slider component! Here's what it looks like:
+
+![type-slider](https://user-images.githubusercontent.com/9021060/192399877-76b662a1-fede-4417-a932-fc15f0da7360.gif)
+
+###### 3. Better Sketching and Inpainting 🎨
+
+We've made a lot of changes to our Image component so that it can support better sketching and inpainting.
+
+Now supports:
+
+- A standalone black-and-white sketch
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Sketchpad(), gr.Image())
+demo.launch()
+```
+
+![bw](https://user-images.githubusercontent.com/9021060/192410264-b08632b5-7b2a-4f86-afb0-5760e7b474cf.gif)
+
+- A standalone color sketch
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Paint(), gr.Image())
+demo.launch()
+```
+
+![color-sketch](https://user-images.githubusercontent.com/9021060/192410500-3c8c3e64-a5fd-4df2-a991-f0a5cef93728.gif)
+
+- An uploadable image with black-and-white or color sketching
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Image(source='upload', tool='color-sketch'), gr.Image()) # for black and white, tool = 'sketch'
+demo.launch()
+```
+
+![sketch-new](https://user-images.githubusercontent.com/9021060/192402422-e53cb7b6-024e-448c-87eb-d6a35a63c476.gif)
+
+- Webcam with black-and-white or color sketching
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Image(source='webcam', tool='color-sketch'), gr.Image()) # for black and white, tool = 'sketch'
+demo.launch()
+```
+
+![webcam-sketch](https://user-images.githubusercontent.com/9021060/192410820-0ffaf324-776e-4e1f-9de6-0fdbbf4940fa.gif)
+
+As well as other fixes
+
+### Bug Fixes:
+
+1. Fix bug where max concurrency count is not respected in queue by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2286](https://github.com/gradio-app/gradio/pull/2286)
+2. fix : queue could be blocked by [@SkyTNT](https://github.com/SkyTNT) in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+3. Supports `gr.update()` in example caching by [@abidlabs](https://github.com/abidlabs) in [PR 2309](https://github.com/gradio-app/gradio/pull/2309)
+4. Clipboard fix for iframes by [@abidlabs](https://github.com/abidlabs) in [PR 2321](https://github.com/gradio-app/gradio/pull/2321)
+5. Fix: Dataframe column headers are reset when you add a new column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2318](https://github.com/gradio-app/gradio/pull/2318)
+6. Added support for URLs for Video, Audio, and Image by [@abidlabs](https://github.com/abidlabs) in [PR 2256](https://github.com/gradio-app/gradio/pull/2256)
+7. Add documentation about how to create and use the Gradio FastAPI app by [@abidlabs](https://github.com/abidlabs) in [PR 2263](https://github.com/gradio-app/gradio/pull/2263)
+
+### Documentation Changes:
+
+1. Adding a Playground Tab to the Website by [@aliabd](https://github.com/aliabd) in [PR 1860](https://github.com/gradio-app/gradio/pull/1860)
+2. Gradio for Tabular Data Science Workflows Guide by [@merveenoyan](https://github.com/merveenoyan) in [PR 2199](https://github.com/gradio-app/gradio/pull/2199)
+3. Promotes `postprocess` and `preprocess` to documented parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2293](https://github.com/gradio-app/gradio/pull/2293)
+4. Update 2)key_features.md by [@voidxd](https://github.com/voidxd) in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+5. Add docs to blocks context postprocessing function by [@Ian-GL](https://github.com/Ian-GL) in [PR 2332](https://github.com/gradio-app/gradio/pull/2332)
+
+### Testing and Infrastructure Changes
+
+1. Website fixes and refactoring by [@aliabd](https://github.com/aliabd) in [PR 2280](https://github.com/gradio-app/gradio/pull/2280)
+2. Don't deploy to spaces on release by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2313](https://github.com/gradio-app/gradio/pull/2313)
+
+### Full Changelog:
+
+- Website fixes and refactoring by [@aliabd](https://github.com/aliabd) in [PR 2280](https://github.com/gradio-app/gradio/pull/2280)
+- Fix bug where max concurrency count is not respected in queue by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2286](https://github.com/gradio-app/gradio/pull/2286)
+- Promotes `postprocess` and `preprocess` to documented parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2293](https://github.com/gradio-app/gradio/pull/2293)
+- Raise warning when trying to cache examples but not all inputs have examples by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2279](https://github.com/gradio-app/gradio/pull/2279)
+- fix : queue could be blocked by [@SkyTNT](https://github.com/SkyTNT) in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+- Don't deploy to spaces on release by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2313](https://github.com/gradio-app/gradio/pull/2313)
+- Supports `gr.update()` in example caching by [@abidlabs](https://github.com/abidlabs) in [PR 2309](https://github.com/gradio-app/gradio/pull/2309)
+- Respect Upstream Queue when loading interfaces/blocks from Spaces by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2294](https://github.com/gradio-app/gradio/pull/2294)
+- Clipboard fix for iframes by [@abidlabs](https://github.com/abidlabs) in [PR 2321](https://github.com/gradio-app/gradio/pull/2321)
+- Sketching + Inpainting Capabilities to Gradio by [@abidlabs](https://github.com/abidlabs) in [PR 2144](https://github.com/gradio-app/gradio/pull/2144)
+- Update 2)key_features.md by [@voidxd](https://github.com/voidxd) in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+- release 3.4b3 by [@abidlabs](https://github.com/abidlabs) in [PR 2328](https://github.com/gradio-app/gradio/pull/2328)
+- Fix: Dataframe column headers are reset when you add a new column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2318](https://github.com/gradio-app/gradio/pull/2318)
+- Start queue when gradio is a sub application by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2319](https://github.com/gradio-app/gradio/pull/2319)
+- Fix Web Tracker Script by [@aliabd](https://github.com/aliabd) in [PR 2308](https://github.com/gradio-app/gradio/pull/2308)
+- Add docs to blocks context postprocessing function by [@Ian-GL](https://github.com/Ian-GL) in [PR 2332](https://github.com/gradio-app/gradio/pull/2332)
+- Fix typo in iterator variable name in run_predict function by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2340](https://github.com/gradio-app/gradio/pull/2340)
+- Add captions to galleries by [@aliabid94](https://github.com/aliabid94) in [PR 2284](https://github.com/gradio-app/gradio/pull/2284)
+- Typeable value on gradio.Slider by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2329](https://github.com/gradio-app/gradio/pull/2329)
+
+### Contributors Shoutout:
+
+- [@SkyTNT](https://github.com/SkyTNT) made their first contribution in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+- [@voidxd](https://github.com/voidxd) made their first contribution in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+
+## 3.3
+
+### New Features:
+
+###### 1. Iterative Outputs ⏳
+
+You can now create an iterative output simply by having your function return a generator!
+
+Here's (part of) an example that was used to generate the interface below it. [See full code](https://colab.research.google.com/drive/1m9bWS6B82CT7bw-m4L6AJR8za7fEK7Ov?usp=sharing).
+
+```python
+def predict(steps, seed):
+ generator = torch.manual_seed(seed)
+ for i in range(1,steps):
+ yield pipeline(generator=generator, num_inference_steps=i)["sample"][0]
+```
+
+![example](https://user-images.githubusercontent.com/9021060/189086273-f5e7087d-71fa-4158-90a9-08e84da0421c.mp4)
+
+###### 2. Accordion Layout 🆕
+
+This version of Gradio introduces a new layout component to Blocks: the Accordion. Wrap your elements in a neat, expandable layout that allows users to toggle them as needed.
+
+Usage: ([Read the docs](https://gradio.app/docs/#accordion))
+
+```python
+with gr.Accordion("open up"):
+# components here
+```
+
+![accordion](https://user-images.githubusercontent.com/9021060/189088465-f0ffd7f0-fc6a-42dc-9249-11c5e1e0529b.gif)
+
+###### 3. Skops Integration 📈
+
+Our new integration with [skops](https://huggingface.co/blog/skops) allows you to load tabular classification and regression models directly from the [hub](https://huggingface.co/models).
+
+Here's a classification example showing how quick it is to set up an interface for a [model](https://huggingface.co/scikit-learn/tabular-playground).
+
+```python
+import gradio as gr
+gr.Interface.load("models/scikit-learn/tabular-playground").launch()
+```
+
+![187936493-5c90c01d-a6dd-400f-aa42-833a096156a1](https://user-images.githubusercontent.com/9021060/189090519-328fbcb4-120b-43c8-aa54-d6fccfa6b7e8.png)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- safari fixes by [@pngwn](https://github.com/pngwn) in [PR 2138](https://github.com/gradio-app/gradio/pull/2138)
+- Fix roundedness and form borders by [@aliabid94](https://github.com/aliabid94) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- Better processing of example data prior to creating dataset component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- Show error on Connection drops by [@aliabid94](https://github.com/aliabid94) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- 3.2 release! by [@abidlabs](https://github.com/abidlabs) in [PR 2139](https://github.com/gradio-app/gradio/pull/2139)
+- Fixed Named API Requests by [@abidlabs](https://github.com/abidlabs) in [PR 2151](https://github.com/gradio-app/gradio/pull/2151)
+- Quick Fix: Cannot upload Model3D image after clearing it by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2168](https://github.com/gradio-app/gradio/pull/2168)
+- Fixed misleading log when server_name is '0.0.0.0' by [@lamhoangtung](https://github.com/lamhoangtung) in [PR 2176](https://github.com/gradio-app/gradio/pull/2176)
+- Keep embedded PngInfo metadata by [@cobryan05](https://github.com/cobryan05) in [PR 2170](https://github.com/gradio-app/gradio/pull/2170)
+- Skops integration: Load tabular classification and regression models from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2126](https://github.com/gradio-app/gradio/pull/2126)
+- Respect original filename when cached example files are downloaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2145](https://github.com/gradio-app/gradio/pull/2145)
+- Add manual trigger to deploy to pypi by [@abidlabs](https://github.com/abidlabs) in [PR 2192](https://github.com/gradio-app/gradio/pull/2192)
+- Fix bugs with gr.update by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2157](https://github.com/gradio-app/gradio/pull/2157)
+- Make queue per app by [@aliabid94](https://github.com/aliabid94) in [PR 2193](https://github.com/gradio-app/gradio/pull/2193)
+- Preserve Labels In Interpretation Components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2166](https://github.com/gradio-app/gradio/pull/2166)
+- Quick Fix: Multiple file download not working by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2169](https://github.com/gradio-app/gradio/pull/2169)
+- use correct MIME type for js-script file by [@daspartho](https://github.com/daspartho) in [PR 2200](https://github.com/gradio-app/gradio/pull/2200)
+- Add accordion component by [@aliabid94](https://github.com/aliabid94) in [PR 2208](https://github.com/gradio-app/gradio/pull/2208)
+
+### Contributors Shoutout:
+
+- [@lamhoangtung](https://github.com/lamhoangtung) made their first contribution in [PR 2176](https://github.com/gradio-app/gradio/pull/2176)
+- [@cobryan05](https://github.com/cobryan05) made their first contribution in [PR 2170](https://github.com/gradio-app/gradio/pull/2170)
+- [@daspartho](https://github.com/daspartho) made their first contribution in [PR 2200](https://github.com/gradio-app/gradio/pull/2200)
+
+## 3.2
+
+### New Features:
+
+###### 1. Improvements to Queuing 🥇
+
+We've implemented a brand new queuing system based on **web sockets** instead of HTTP long polling. Among other things, this allows us to manage queue sizes better on Hugging Face Spaces. There are also additional queue-related parameters you can add:
+
+- Now supports concurrent workers (parallelization)
+
+```python
+demo = gr.Interface(...)
+demo.queue(concurrency_count=3)
+demo.launch()
+```
+
+- Configure a maximum queue size
+
+```python
+demo = gr.Interface(...)
+demo.queue(max_size=100)
+demo.launch()
+```
+
+- If a user closes their tab / browser, they leave the queue, which means the demo will run faster for everyone else
+
+###### 2. Fixes to Examples
+
+- Dataframe examples will render properly, and look much clearer in the UI: (thanks to PR #2125)
+
+![Screen Shot 2022-08-30 at 8 29 58 PM](https://user-images.githubusercontent.com/9021060/187586561-d915bafb-f968-4966-b9a2-ef41119692b2.png)
+
+- Image and Video thumbnails are cropped to look neater and more uniform: (thanks to PR #2109)
+
+![Screen Shot 2022-08-30 at 8 32 15 PM](https://user-images.githubusercontent.com/9021060/187586890-56e1e4f0-1b84-42d9-a82f-911772c41030.png)
+
+- Other fixes in PR #2131 and #2064 make it easier to design and use Examples
+
+###### 3. Component Fixes 🧱
+
+- Specify the width and height of an image in its style tag (thanks to PR #2133)
+
+```python
+components.Image().style(height=260, width=300)
+```
+
+- Automatic conversion of videos so they are playable in the browser (thanks to PR #2003). Gradio will check if a video's format is playable in the browser and, if it isn't, will automatically convert it to a format that is (mp4).
+- Pass in a json filepath to the Label component (thanks to PR #2083)
+- Randomize the default value of a Slider (thanks to PR #1935)
+
+![slider-random](https://user-images.githubusercontent.com/9021060/187596230-3db9697f-9f4d-42f5-9387-d77573513448.gif)
+
+- Improvements to State in PR #2100
+
+###### 4. Ability to Randomize Input Sliders and Reload Data whenever the Page Loads
+
+- In some cases, you want to be able to show a different set of input data to every user as they load the page app. For example, you might want to randomize the value of a "seed" `Slider` input. Or you might want to show a `Textbox` with the current date. We now supporting passing _functions_ as the default value in input components. When you pass in a function, it gets **re-evaluated** every time someone loads the demo, allowing you to reload / change data for different users.
+
+Here's an example loading the current date time into an input Textbox:
+
+```python
+import gradio as gr
+import datetime
+
+with gr.Blocks() as demo:
+ gr.Textbox(datetime.datetime.now)
+
+demo.launch()
+```
+
+Note that we don't evaluate the function -- `datetime.datetime.now()` -- we pass in the function itself to get this behavior -- `datetime.datetime.now`
+
+Because randomizing the initial value of `Slider` is a common use case, we've added a `randomize` keyword argument you can use to randomize its initial value:
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x:x, gr.Slider(0, 10, randomize=True), "number")
+demo.launch()
+```
+
+###### 5. New Guide 🖊️
+
+- [Gradio and W&B Integration](https://gradio.app/Gradio_and_Wandb_Integration/)
+
+### Full Changelog:
+
+- Reset components to original state by setting value to None by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2044](https://github.com/gradio-app/gradio/pull/2044)
+- Cleaning up the way data is processed for components by [@abidlabs](https://github.com/abidlabs) in [PR 1967](https://github.com/gradio-app/gradio/pull/1967)
+- version 3.1.8b by [@abidlabs](https://github.com/abidlabs) in [PR 2063](https://github.com/gradio-app/gradio/pull/2063)
+- Wandb guide by [@AK391](https://github.com/AK391) in [PR 1898](https://github.com/gradio-app/gradio/pull/1898)
+- Add a flagging callback to save json files to a hugging face dataset by [@chrisemezue](https://github.com/chrisemezue) in [PR 1821](https://github.com/gradio-app/gradio/pull/1821)
+- Add data science demos to landing page by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2067](https://github.com/gradio-app/gradio/pull/2067)
+- Hide time series + xgboost demos by default by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2079](https://github.com/gradio-app/gradio/pull/2079)
+- Encourage people to keep trying when queue full by [@apolinario](https://github.com/apolinario) in [PR 2076](https://github.com/gradio-app/gradio/pull/2076)
+- Updated our analytics on creation of Blocks/Interface by [@abidlabs](https://github.com/abidlabs) in [PR 2082](https://github.com/gradio-app/gradio/pull/2082)
+- `Label` component now accepts file paths to `.json` files by [@abidlabs](https://github.com/abidlabs) in [PR 2083](https://github.com/gradio-app/gradio/pull/2083)
+- Fix issues related to demos in Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 2086](https://github.com/gradio-app/gradio/pull/2086)
+- Fix TimeSeries examples not properly displayed in UI by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2064](https://github.com/gradio-app/gradio/pull/2064)
+- Fix infinite requests when doing tab item select by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2070](https://github.com/gradio-app/gradio/pull/2070)
+- Accept deprecated `file` route as well by [@abidlabs](https://github.com/abidlabs) in [PR 2099](https://github.com/gradio-app/gradio/pull/2099)
+- Allow frontend method execution on Block.load event by [@codedealer](https://github.com/codedealer) in [PR 2108](https://github.com/gradio-app/gradio/pull/2108)
+- Improvements to `State` by [@abidlabs](https://github.com/abidlabs) in [PR 2100](https://github.com/gradio-app/gradio/pull/2100)
+- Catch IndexError, KeyError in video_is_playable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2113](https://github.com/gradio-app/gradio/pull/2113)
+- Fix: Download button does not respect the filepath returned by the function by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2073](https://github.com/gradio-app/gradio/pull/2073)
+- Refactoring Layout: Adding column widths, forms, and more. by [@aliabid94](https://github.com/aliabid94) in [PR 2097](https://github.com/gradio-app/gradio/pull/2097)
+- Update CONTRIBUTING.md by [@abidlabs](https://github.com/abidlabs) in [PR 2118](https://github.com/gradio-app/gradio/pull/2118)
+- 2092 df ex by [@pngwn](https://github.com/pngwn) in [PR 2125](https://github.com/gradio-app/gradio/pull/2125)
+- feat(samples table/gallery): Crop thumbs to square by [@ronvoluted](https://github.com/ronvoluted) in [PR 2109](https://github.com/gradio-app/gradio/pull/2109)
+- Some enhancements to `gr.Examples` by [@abidlabs](https://github.com/abidlabs) in [PR 2131](https://github.com/gradio-app/gradio/pull/2131)
+- Image size fix by [@aliabid94](https://github.com/aliabid94) in [PR 2133](https://github.com/gradio-app/gradio/pull/2133)
+
+### Contributors Shoutout:
+
+- [@chrisemezue](https://github.com/chrisemezue) made their first contribution in [PR 1821](https://github.com/gradio-app/gradio/pull/1821)
+- [@apolinario](https://github.com/apolinario) made their first contribution in [PR 2076](https://github.com/gradio-app/gradio/pull/2076)
+- [@codedealer](https://github.com/codedealer) made their first contribution in [PR 2108](https://github.com/gradio-app/gradio/pull/2108)
+
+## 3.1
+
+### New Features:
+
+###### 1. Embedding Demos on Any Website 💻
+
+With PR #1444, Gradio is now distributed as a web component. This means demos can be natively embedded on websites. You'll just need to add two lines: one to load the gradio javascript, and one to link to the demos backend.
+
+Here's a simple example that embeds the demo from a Hugging Face space:
+
+```html
+
+
+```
+
+But you can also embed demos that are running anywhere, you just need to link the demo to `src` instead of `space`. In fact, all the demos on the gradio website are embedded this way:
+
+
+
+Read more in the [Embedding Gradio Demos](https://gradio.app/embedding_gradio_demos) guide.
+
+###### 2. Reload Mode 👨💻
+
+Reload mode helps developers create gradio demos faster by automatically reloading the demo whenever the code changes. It can support development on Python IDEs (VS Code, PyCharm, etc), the terminal, as well as Jupyter notebooks.
+
+If your demo code is in a script named `app.py`, instead of running `python app.py` you can now run `gradio app.py` and that will launch the demo in reload mode:
+
+```bash
+Launching in reload mode on: http://127.0.0.1:7860 (Press CTRL+C to quit)
+Watching...
+WARNING: The --reload flag should not be used in production on Windows.
+```
+
+If you're working from a Jupyter or Colab Notebook, use these magic commands instead: `%load_ext gradio` when you import gradio, and `%%blocks` in the top of the cell with the demo code. Here's an example that shows how much faster the development becomes:
+
+![Blocks](https://user-images.githubusercontent.com/9021060/178986488-ed378cc8-5141-4330-ba41-672b676863d0.gif)
+
+###### 3. Inpainting Support on `gr.Image()` 🎨
+
+We updated the Image component to add support for inpainting demos. It works by adding `tool="sketch"` as a parameter, that passes both an image and a sketchable mask to your prediction function.
+
+Here's an example from the [LAMA space](https://huggingface.co/spaces/akhaliq/lama):
+
+![FXApVlFVsAALSD-](https://user-images.githubusercontent.com/9021060/178989479-549867c8-7fb0-436a-a97d-1e91c9f5e611.jpeg)
+
+###### 4. Markdown and HTML support in Dataframes 🔢
+
+We upgraded the Dataframe component in PR #1684 to support rendering Markdown and HTML inside the cells.
+
+This means you can build Dataframes that look like the following:
+
+![image (8)](https://user-images.githubusercontent.com/9021060/178991233-41cb07a5-e7a3-433e-89b8-319bc78eb9c2.png)
+
+###### 5. `gr.Examples()` for Blocks 🧱
+
+We've added the `gr.Examples` component helper to allow you to add examples to any Blocks demo. This class is a wrapper over the `gr.Dataset` component.
+
+
+
+gr.Examples takes two required parameters:
+
+- `examples` which takes in a nested list
+- `inputs` which takes in a component or list of components
+
+You can read more in the [Examples docs](https://gradio.app/docs/#examples) or the [Adding Examples to your Demos guide](https://gradio.app/adding_examples_to_your_app/).
+
+###### 6. Fixes to Audio Streaming
+
+With [PR 1828](https://github.com/gradio-app/gradio/pull/1828) we now hide the status loading animation, as well as remove the echo in streaming. Check out the [stream_audio](https://github.com/gradio-app/gradio/blob/main/demo/stream_audio/run.py) demo for more or read through our [Real Time Speech Recognition](https://gradio.app/real_time_speech_recognition/) guide.
+
+
+
+### Full Changelog:
+
+- File component: list multiple files and allow for download #1446 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1681](https://github.com/gradio-app/gradio/pull/1681)
+- Add ColorPicker to docs by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1768](https://github.com/gradio-app/gradio/pull/1768)
+- Mock out requests in TestRequest unit tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1794](https://github.com/gradio-app/gradio/pull/1794)
+- Add requirements.txt and test_files to source dist by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1817](https://github.com/gradio-app/gradio/pull/1817)
+- refactor: f-string for tunneling.py by [@nhankiet](https://github.com/nhankiet) in [PR 1819](https://github.com/gradio-app/gradio/pull/1819)
+- Miscellaneous formatting improvements to website by [@aliabd](https://github.com/aliabd) in [PR 1754](https://github.com/gradio-app/gradio/pull/1754)
+- `integrate()` method moved to `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 1776](https://github.com/gradio-app/gradio/pull/1776)
+- Add python-3.7 tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1818](https://github.com/gradio-app/gradio/pull/1818)
+- Copy test dir in website dockers by [@aliabd](https://github.com/aliabd) in [PR 1827](https://github.com/gradio-app/gradio/pull/1827)
+- Add info to docs on how to set default values for components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1788](https://github.com/gradio-app/gradio/pull/1788)
+- Embedding Components on Docs by [@aliabd](https://github.com/aliabd) in [PR 1726](https://github.com/gradio-app/gradio/pull/1726)
+- Remove usage of deprecated gr.inputs and gr.outputs from website by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1796](https://github.com/gradio-app/gradio/pull/1796)
+- Some cleanups to the docs page by [@abidlabs](https://github.com/abidlabs) in [PR 1822](https://github.com/gradio-app/gradio/pull/1822)
+
+### Contributors Shoutout:
+
+- [@nhankiet](https://github.com/nhankiet) made their first contribution in [PR 1819](https://github.com/gradio-app/gradio/pull/1819)
+
+## 3.0
+
+###### 🔥 Gradio 3.0 is the biggest update to the library, ever.
+
+### New Features:
+
+###### 1. Blocks 🧱
+
+Blocks is a new, low-level API that allows you to have full control over the data flows and layout of your application. It allows you to build very complex, multi-step applications. For example, you might want to:
+
+- Group together related demos as multiple tabs in one web app
+- Change the layout of your demo instead of just having all of the inputs on the left and outputs on the right
+- Have multi-step interfaces, in which the output of one model becomes the input to the next model, or have more flexible data flows in general
+- Change a component's properties (for example, the choices in a Dropdown) or its visibility based on user input
+
+Here's a simple example that creates the demo below it:
+
+```python
+import gradio as gr
+
+def update(name):
+ return f"Welcome to Gradio, {name}!"
+
+demo = gr.Blocks()
+
+with demo:
+ gr.Markdown(
+ """
+ # Hello World!
+ Start typing below to see the output.
+ """)
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+
+ inp.change(fn=update,
+ inputs=inp,
+ outputs=out)
+
+demo.launch()
+```
+
+![hello-blocks](https://user-images.githubusercontent.com/9021060/168684108-78cbd24b-e6bd-4a04-a8d9-20d535203434.gif)
+
+Read our [Introduction to Blocks](http://gradio.app/introduction_to_blocks/) guide for more, and join the 🎈 [Gradio Blocks Party](https://huggingface.co/spaces/Gradio-Blocks/README)!
+
+###### 2. Our Revamped Design 🎨
+
+We've upgraded our design across the entire library: from components, and layouts all the way to dark mode.
+
+![kitchen_sink](https://user-images.githubusercontent.com/9021060/168686333-7a6e3096-3e23-4309-abf2-5cd7736e0463.gif)
+
+###### 3. A New Website 💻
+
+We've upgraded [gradio.app](https://gradio.app) to make it cleaner, faster and easier to use. Our docs now come with components and demos embedded directly on the page. So you can quickly get up to speed with what you're looking for.
+
+![website](https://user-images.githubusercontent.com/9021060/168687191-10d6a3bd-101f-423a-8193-48f47a5e077d.gif)
+
+###### 4. New Components: Model3D, Dataset, and More..
+
+We've introduced a lot of new components in `3.0`, including `Model3D`, `Dataset`, `Markdown`, `Button` and `Gallery`. You can find all the components and play around with them [here](https://gradio.app/docs/#components).
+
+![Model3d](https://user-images.githubusercontent.com/9021060/168689062-6ad77151-8cc5-467d-916c-f7c78e52ec0c.gif)
+
+### Full Changelog:
+
+- Gradio dash fe by [@pngwn](https://github.com/pngwn) in [PR 807](https://github.com/gradio-app/gradio/pull/807)
+- Blocks components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 765](https://github.com/gradio-app/gradio/pull/765)
+- Blocks components V2 by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 843](https://github.com/gradio-app/gradio/pull/843)
+- Blocks-Backend-Events by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 844](https://github.com/gradio-app/gradio/pull/844)
+- Interfaces from Blocks by [@aliabid94](https://github.com/aliabid94) in [PR 849](https://github.com/gradio-app/gradio/pull/849)
+- Blocks dev by [@aliabid94](https://github.com/aliabid94) in [PR 853](https://github.com/gradio-app/gradio/pull/853)
+- Started updating demos to use the new `gradio.components` syntax by [@abidlabs](https://github.com/abidlabs) in [PR 848](https://github.com/gradio-app/gradio/pull/848)
+- add test infra + add browser tests to CI by [@pngwn](https://github.com/pngwn) in [PR 852](https://github.com/gradio-app/gradio/pull/852)
+- 854 textbox by [@pngwn](https://github.com/pngwn) in [PR 859](https://github.com/gradio-app/gradio/pull/859)
+- Getting old Python unit tests to pass on `blocks-dev` by [@abidlabs](https://github.com/abidlabs) in [PR 861](https://github.com/gradio-app/gradio/pull/861)
+- initialise chatbot with empty array of messages by [@pngwn](https://github.com/pngwn) in [PR 867](https://github.com/gradio-app/gradio/pull/867)
+- add test for output to input by [@pngwn](https://github.com/pngwn) in [PR 866](https://github.com/gradio-app/gradio/pull/866)
+- More Interface -> Blocks features by [@aliabid94](https://github.com/aliabid94) in [PR 864](https://github.com/gradio-app/gradio/pull/864)
+- Fixing external.py in blocks-dev to reflect the new HF Spaces paths by [@abidlabs](https://github.com/abidlabs) in [PR 879](https://github.com/gradio-app/gradio/pull/879)
+- backend_default_value_refactoring by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 871](https://github.com/gradio-app/gradio/pull/871)
+- fix default_value by [@pngwn](https://github.com/pngwn) in [PR 869](https://github.com/gradio-app/gradio/pull/869)
+- fix buttons by [@aliabid94](https://github.com/aliabid94) in [PR 883](https://github.com/gradio-app/gradio/pull/883)
+- Checking and updating more demos to use 3.0 syntax by [@abidlabs](https://github.com/abidlabs) in [PR 892](https://github.com/gradio-app/gradio/pull/892)
+- Blocks Tests by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 902](https://github.com/gradio-app/gradio/pull/902)
+- Interface fix by [@pngwn](https://github.com/pngwn) in [PR 901](https://github.com/gradio-app/gradio/pull/901)
+- Quick fix: Issue 893 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 907](https://github.com/gradio-app/gradio/pull/907)
+- 3d Image Component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 775](https://github.com/gradio-app/gradio/pull/775)
+- fix endpoint url in prod by [@pngwn](https://github.com/pngwn) in [PR 911](https://github.com/gradio-app/gradio/pull/911)
+- rename Model3d to Image3D by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 912](https://github.com/gradio-app/gradio/pull/912)
+- update pypi to 2.9.1 by [@abidlabs](https://github.com/abidlabs) in [PR 916](https://github.com/gradio-app/gradio/pull/916)
+- blocks-with-fix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 917](https://github.com/gradio-app/gradio/pull/917)
+- Restore Interpretation, Live, Auth, Queueing by [@aliabid94](https://github.com/aliabid94) in [PR 915](https://github.com/gradio-app/gradio/pull/915)
+- Allow `Blocks` instances to be used like a `Block` in other `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 919](https://github.com/gradio-app/gradio/pull/919)
+- Redesign 1 by [@pngwn](https://github.com/pngwn) in [PR 918](https://github.com/gradio-app/gradio/pull/918)
+- blocks-components-tests by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 904](https://github.com/gradio-app/gradio/pull/904)
+- fix unit + browser tests by [@pngwn](https://github.com/pngwn) in [PR 926](https://github.com/gradio-app/gradio/pull/926)
+- blocks-move-test-data by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 927](https://github.com/gradio-app/gradio/pull/927)
+- remove debounce from form inputs by [@pngwn](https://github.com/pngwn) in [PR 932](https://github.com/gradio-app/gradio/pull/932)
+- reimplement webcam video by [@pngwn](https://github.com/pngwn) in [PR 928](https://github.com/gradio-app/gradio/pull/928)
+- blocks-move-test-data by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 941](https://github.com/gradio-app/gradio/pull/941)
+- allow audio components to take a string value by [@pngwn](https://github.com/pngwn) in [PR 930](https://github.com/gradio-app/gradio/pull/930)
+- static mode for textbox by [@pngwn](https://github.com/pngwn) in [PR 929](https://github.com/gradio-app/gradio/pull/929)
+- fix file upload text by [@pngwn](https://github.com/pngwn) in [PR 931](https://github.com/gradio-app/gradio/pull/931)
+- tabbed-interface-rewritten by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 958](https://github.com/gradio-app/gradio/pull/958)
+- Gan demo fix by [@abidlabs](https://github.com/abidlabs) in [PR 965](https://github.com/gradio-app/gradio/pull/965)
+- Blocks analytics by [@abidlabs](https://github.com/abidlabs) in [PR 947](https://github.com/gradio-app/gradio/pull/947)
+- Blocks page load by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 963](https://github.com/gradio-app/gradio/pull/963)
+- add frontend for page load events by [@pngwn](https://github.com/pngwn) in [PR 967](https://github.com/gradio-app/gradio/pull/967)
+- fix i18n and some tweaks by [@pngwn](https://github.com/pngwn) in [PR 966](https://github.com/gradio-app/gradio/pull/966)
+- add jinja2 to reqs by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 969](https://github.com/gradio-app/gradio/pull/969)
+- Cleaning up `Launchable()` by [@abidlabs](https://github.com/abidlabs) in [PR 968](https://github.com/gradio-app/gradio/pull/968)
+- Fix #944 by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 971](https://github.com/gradio-app/gradio/pull/971)
+- New Blocks Demo: neural instrument cloning by [@abidlabs](https://github.com/abidlabs) in [PR 975](https://github.com/gradio-app/gradio/pull/975)
+- Add huggingface_hub client library by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 973](https://github.com/gradio-app/gradio/pull/973)
+- State and variables by [@aliabid94](https://github.com/aliabid94) in [PR 977](https://github.com/gradio-app/gradio/pull/977)
+- update-components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 986](https://github.com/gradio-app/gradio/pull/986)
+- ensure dataframe updates as expected by [@pngwn](https://github.com/pngwn) in [PR 981](https://github.com/gradio-app/gradio/pull/981)
+- test-guideline by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 990](https://github.com/gradio-app/gradio/pull/990)
+- Issue #785: add footer by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 972](https://github.com/gradio-app/gradio/pull/972)
+- indentation fix by [@abidlabs](https://github.com/abidlabs) in [PR 993](https://github.com/gradio-app/gradio/pull/993)
+- missing quote by [@aliabd](https://github.com/aliabd) in [PR 996](https://github.com/gradio-app/gradio/pull/996)
+- added interactive parameter to components by [@abidlabs](https://github.com/abidlabs) in [PR 992](https://github.com/gradio-app/gradio/pull/992)
+- custom-components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 985](https://github.com/gradio-app/gradio/pull/985)
+- Refactor component shortcuts by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 995](https://github.com/gradio-app/gradio/pull/995)
+- Plot Component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 805](https://github.com/gradio-app/gradio/pull/805)
+- updated PyPi version to 2.9.2 by [@abidlabs](https://github.com/abidlabs) in [PR 1002](https://github.com/gradio-app/gradio/pull/1002)
+- Release 2.9.3 by [@abidlabs](https://github.com/abidlabs) in [PR 1003](https://github.com/gradio-app/gradio/pull/1003)
+- Image3D Examples Fix by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1001](https://github.com/gradio-app/gradio/pull/1001)
+- release 2.9.4 by [@abidlabs](https://github.com/abidlabs) in [PR 1006](https://github.com/gradio-app/gradio/pull/1006)
+- templates import hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1008](https://github.com/gradio-app/gradio/pull/1008)
+- Progress indicator bar by [@aliabid94](https://github.com/aliabid94) in [PR 997](https://github.com/gradio-app/gradio/pull/997)
+- Fixed image input for absolute path by [@JefferyChiang](https://github.com/JefferyChiang) in [PR 1004](https://github.com/gradio-app/gradio/pull/1004)
+- Model3D + Plot Components by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1010](https://github.com/gradio-app/gradio/pull/1010)
+- Gradio Guides: Creating CryptoPunks with GANs by [@NimaBoscarino](https://github.com/NimaBoscarino) in [PR 1000](https://github.com/gradio-app/gradio/pull/1000)
+- [BIG PR] Gradio blocks & redesigned components by [@abidlabs](https://github.com/abidlabs) in [PR 880](https://github.com/gradio-app/gradio/pull/880)
+- fixed failing test on main by [@abidlabs](https://github.com/abidlabs) in [PR 1023](https://github.com/gradio-app/gradio/pull/1023)
+- Use smaller ASR model in external test by [@abidlabs](https://github.com/abidlabs) in [PR 1024](https://github.com/gradio-app/gradio/pull/1024)
+- updated PyPi version to 2.9.0b by [@abidlabs](https://github.com/abidlabs) in [PR 1026](https://github.com/gradio-app/gradio/pull/1026)
+- Fixing import issues so that the package successfully installs on colab notebooks by [@abidlabs](https://github.com/abidlabs) in [PR 1027](https://github.com/gradio-app/gradio/pull/1027)
+- Update website tracker slackbot by [@aliabd](https://github.com/aliabd) in [PR 1037](https://github.com/gradio-app/gradio/pull/1037)
+- textbox-autoheight by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1009](https://github.com/gradio-app/gradio/pull/1009)
+- Model3D Examples fixes by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1035](https://github.com/gradio-app/gradio/pull/1035)
+- GAN Gradio Guide: Adjustments to iframe heights by [@NimaBoscarino](https://github.com/NimaBoscarino) in [PR 1042](https://github.com/gradio-app/gradio/pull/1042)
+- added better default labels to form components by [@abidlabs](https://github.com/abidlabs) in [PR 1040](https://github.com/gradio-app/gradio/pull/1040)
+- Slackbot web tracker fix by [@aliabd](https://github.com/aliabd) in [PR 1043](https://github.com/gradio-app/gradio/pull/1043)
+- Plot fixes by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1044](https://github.com/gradio-app/gradio/pull/1044)
+- Small fixes to the demos by [@abidlabs](https://github.com/abidlabs) in [PR 1030](https://github.com/gradio-app/gradio/pull/1030)
+- fixing demo issue with website by [@aliabd](https://github.com/aliabd) in [PR 1047](https://github.com/gradio-app/gradio/pull/1047)
+- [hotfix] HighlightedText by [@aliabid94](https://github.com/aliabid94) in [PR 1046](https://github.com/gradio-app/gradio/pull/1046)
+- Update text by [@ronvoluted](https://github.com/ronvoluted) in [PR 1050](https://github.com/gradio-app/gradio/pull/1050)
+- Update CONTRIBUTING.md by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1052](https://github.com/gradio-app/gradio/pull/1052)
+- fix(ui): Increase contrast for footer by [@ronvoluted](https://github.com/ronvoluted) in [PR 1048](https://github.com/gradio-app/gradio/pull/1048)
+- UI design update by [@gary149](https://github.com/gary149) in [PR 1041](https://github.com/gradio-app/gradio/pull/1041)
+- updated PyPi version to 2.9.0b8 by [@abidlabs](https://github.com/abidlabs) in [PR 1059](https://github.com/gradio-app/gradio/pull/1059)
+- Running, testing, and fixing demos by [@abidlabs](https://github.com/abidlabs) in [PR 1060](https://github.com/gradio-app/gradio/pull/1060)
+- Form layout by [@pngwn](https://github.com/pngwn) in [PR 1054](https://github.com/gradio-app/gradio/pull/1054)
+- inputless-interfaces by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1038](https://github.com/gradio-app/gradio/pull/1038)
+- Update PULL_REQUEST_TEMPLATE.md by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1068](https://github.com/gradio-app/gradio/pull/1068)
+- Upgrading node memory to 4gb in website Docker by [@aliabd](https://github.com/aliabd) in [PR 1069](https://github.com/gradio-app/gradio/pull/1069)
+- Website reload error by [@aliabd](https://github.com/aliabd) in [PR 1079](https://github.com/gradio-app/gradio/pull/1079)
+- fixed favicon issue by [@abidlabs](https://github.com/abidlabs) in [PR 1064](https://github.com/gradio-app/gradio/pull/1064)
+- remove-queue-from-events by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1056](https://github.com/gradio-app/gradio/pull/1056)
+- Enable vertex colors for OBJs files by [@radames](https://github.com/radames) in [PR 1074](https://github.com/gradio-app/gradio/pull/1074)
+- Dark text by [@ronvoluted](https://github.com/ronvoluted) in [PR 1049](https://github.com/gradio-app/gradio/pull/1049)
+- Scroll to output by [@pngwn](https://github.com/pngwn) in [PR 1077](https://github.com/gradio-app/gradio/pull/1077)
+- Explicitly list pnpm version 6 in contributing guide by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1085](https://github.com/gradio-app/gradio/pull/1085)
+- hotfix for encrypt issue by [@abidlabs](https://github.com/abidlabs) in [PR 1096](https://github.com/gradio-app/gradio/pull/1096)
+- Release 2.9b9 by [@abidlabs](https://github.com/abidlabs) in [PR 1098](https://github.com/gradio-app/gradio/pull/1098)
+- tweak node circleci settings by [@pngwn](https://github.com/pngwn) in [PR 1091](https://github.com/gradio-app/gradio/pull/1091)
+- Website Reload Error by [@aliabd](https://github.com/aliabd) in [PR 1099](https://github.com/gradio-app/gradio/pull/1099)
+- Website Reload: README in demos docker by [@aliabd](https://github.com/aliabd) in [PR 1100](https://github.com/gradio-app/gradio/pull/1100)
+- Flagging fixes by [@abidlabs](https://github.com/abidlabs) in [PR 1081](https://github.com/gradio-app/gradio/pull/1081)
+- Backend for optional labels by [@abidlabs](https://github.com/abidlabs) in [PR 1080](https://github.com/gradio-app/gradio/pull/1080)
+- Optional labels fe by [@pngwn](https://github.com/pngwn) in [PR 1105](https://github.com/gradio-app/gradio/pull/1105)
+- clean-deprecated-parameters by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1090](https://github.com/gradio-app/gradio/pull/1090)
+- Blocks rendering fix by [@abidlabs](https://github.com/abidlabs) in [PR 1102](https://github.com/gradio-app/gradio/pull/1102)
+- Redos #1106 by [@abidlabs](https://github.com/abidlabs) in [PR 1112](https://github.com/gradio-app/gradio/pull/1112)
+- Interface types: handle input-only, output-only, and unified interfaces by [@abidlabs](https://github.com/abidlabs) in [PR 1108](https://github.com/gradio-app/gradio/pull/1108)
+- Hotfix + New pypi release 2.9b11 by [@abidlabs](https://github.com/abidlabs) in [PR 1118](https://github.com/gradio-app/gradio/pull/1118)
+- issue-checkbox by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1122](https://github.com/gradio-app/gradio/pull/1122)
+- issue-checkbox-hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1127](https://github.com/gradio-app/gradio/pull/1127)
+- Fix demos in website by [@aliabd](https://github.com/aliabd) in [PR 1130](https://github.com/gradio-app/gradio/pull/1130)
+- Guide for Gradio ONNX model zoo on Huggingface by [@AK391](https://github.com/AK391) in [PR 1073](https://github.com/gradio-app/gradio/pull/1073)
+- ONNX guide fixes by [@aliabd](https://github.com/aliabd) in [PR 1131](https://github.com/gradio-app/gradio/pull/1131)
+- Stacked form inputs css by [@gary149](https://github.com/gary149) in [PR 1134](https://github.com/gradio-app/gradio/pull/1134)
+- made default value in textbox empty string by [@abidlabs](https://github.com/abidlabs) in [PR 1135](https://github.com/gradio-app/gradio/pull/1135)
+- Examples UI by [@gary149](https://github.com/gary149) in [PR 1121](https://github.com/gradio-app/gradio/pull/1121)
+- Chatbot custom color support by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1092](https://github.com/gradio-app/gradio/pull/1092)
+- highlighted text colors by [@pngwn](https://github.com/pngwn) in [PR 1119](https://github.com/gradio-app/gradio/pull/1119)
+- pin to pnpm 6 for now by [@pngwn](https://github.com/pngwn) in [PR 1147](https://github.com/gradio-app/gradio/pull/1147)
+- Restore queue in Blocks by [@aliabid94](https://github.com/aliabid94) in [PR 1137](https://github.com/gradio-app/gradio/pull/1137)
+- add select event for tabitems by [@pngwn](https://github.com/pngwn) in [PR 1154](https://github.com/gradio-app/gradio/pull/1154)
+- max_lines + autoheight for textbox by [@pngwn](https://github.com/pngwn) in [PR 1153](https://github.com/gradio-app/gradio/pull/1153)
+- use color palette for chatbot by [@pngwn](https://github.com/pngwn) in [PR 1152](https://github.com/gradio-app/gradio/pull/1152)
+- Timeseries improvements by [@pngwn](https://github.com/pngwn) in [PR 1149](https://github.com/gradio-app/gradio/pull/1149)
+- move styling for interface panels to frontend by [@pngwn](https://github.com/pngwn) in [PR 1146](https://github.com/gradio-app/gradio/pull/1146)
+- html tweaks by [@pngwn](https://github.com/pngwn) in [PR 1145](https://github.com/gradio-app/gradio/pull/1145)
+- Issue #768: Support passing none to resize and crop image by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1144](https://github.com/gradio-app/gradio/pull/1144)
+- image gallery component + img css by [@aliabid94](https://github.com/aliabid94) in [PR 1140](https://github.com/gradio-app/gradio/pull/1140)
+- networking tweak by [@abidlabs](https://github.com/abidlabs) in [PR 1143](https://github.com/gradio-app/gradio/pull/1143)
+- Allow enabling queue per event listener by [@aliabid94](https://github.com/aliabid94) in [PR 1155](https://github.com/gradio-app/gradio/pull/1155)
+- config hotfix and v. 2.9b23 by [@abidlabs](https://github.com/abidlabs) in [PR 1158](https://github.com/gradio-app/gradio/pull/1158)
+- Custom JS calls by [@aliabid94](https://github.com/aliabid94) in [PR 1082](https://github.com/gradio-app/gradio/pull/1082)
+- Small fixes: queue default fix, ffmpeg installation message by [@abidlabs](https://github.com/abidlabs) in [PR 1159](https://github.com/gradio-app/gradio/pull/1159)
+- formatting by [@abidlabs](https://github.com/abidlabs) in [PR 1161](https://github.com/gradio-app/gradio/pull/1161)
+- enable flex grow for gr-box by [@radames](https://github.com/radames) in [PR 1165](https://github.com/gradio-app/gradio/pull/1165)
+- 1148 loading by [@pngwn](https://github.com/pngwn) in [PR 1164](https://github.com/gradio-app/gradio/pull/1164)
+- Put enable_queue kwarg back in launch() by [@aliabid94](https://github.com/aliabid94) in [PR 1167](https://github.com/gradio-app/gradio/pull/1167)
+- A few small fixes by [@abidlabs](https://github.com/abidlabs) in [PR 1171](https://github.com/gradio-app/gradio/pull/1171)
+- Hotfix for dropdown component by [@abidlabs](https://github.com/abidlabs) in [PR 1172](https://github.com/gradio-app/gradio/pull/1172)
+- use secondary buttons in interface by [@pngwn](https://github.com/pngwn) in [PR 1173](https://github.com/gradio-app/gradio/pull/1173)
+- 1183 component height by [@pngwn](https://github.com/pngwn) in [PR 1185](https://github.com/gradio-app/gradio/pull/1185)
+- 962 dataframe by [@pngwn](https://github.com/pngwn) in [PR 1186](https://github.com/gradio-app/gradio/pull/1186)
+- update-contributing by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1188](https://github.com/gradio-app/gradio/pull/1188)
+- Table tweaks by [@pngwn](https://github.com/pngwn) in [PR 1195](https://github.com/gradio-app/gradio/pull/1195)
+- wrap tab content in column by [@pngwn](https://github.com/pngwn) in [PR 1200](https://github.com/gradio-app/gradio/pull/1200)
+- WIP: Add dark mode support by [@gary149](https://github.com/gary149) in [PR 1187](https://github.com/gradio-app/gradio/pull/1187)
+- Restored /api/predict/ endpoint for Interfaces by [@abidlabs](https://github.com/abidlabs) in [PR 1199](https://github.com/gradio-app/gradio/pull/1199)
+- hltext-label by [@pngwn](https://github.com/pngwn) in [PR 1204](https://github.com/gradio-app/gradio/pull/1204)
+- add copy functionality to json by [@pngwn](https://github.com/pngwn) in [PR 1205](https://github.com/gradio-app/gradio/pull/1205)
+- Update component config by [@aliabid94](https://github.com/aliabid94) in [PR 1089](https://github.com/gradio-app/gradio/pull/1089)
+- fix placeholder prompt by [@pngwn](https://github.com/pngwn) in [PR 1215](https://github.com/gradio-app/gradio/pull/1215)
+- ensure webcam video value is propagated correctly by [@pngwn](https://github.com/pngwn) in [PR 1218](https://github.com/gradio-app/gradio/pull/1218)
+- Automatic word-break in highlighted text, combine_adjacent support by [@aliabid94](https://github.com/aliabid94) in [PR 1209](https://github.com/gradio-app/gradio/pull/1209)
+- async-function-support by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1190](https://github.com/gradio-app/gradio/pull/1190)
+- Sharing fix for assets by [@aliabid94](https://github.com/aliabid94) in [PR 1208](https://github.com/gradio-app/gradio/pull/1208)
+- Hotfixes for course demos by [@abidlabs](https://github.com/abidlabs) in [PR 1222](https://github.com/gradio-app/gradio/pull/1222)
+- Allow Custom CSS by [@aliabid94](https://github.com/aliabid94) in [PR 1170](https://github.com/gradio-app/gradio/pull/1170)
+- share-hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1226](https://github.com/gradio-app/gradio/pull/1226)
+- tweaks by [@pngwn](https://github.com/pngwn) in [PR 1229](https://github.com/gradio-app/gradio/pull/1229)
+- white space for class concatenation by [@radames](https://github.com/radames) in [PR 1228](https://github.com/gradio-app/gradio/pull/1228)
+- Tweaks by [@pngwn](https://github.com/pngwn) in [PR 1230](https://github.com/gradio-app/gradio/pull/1230)
+- css tweaks by [@pngwn](https://github.com/pngwn) in [PR 1235](https://github.com/gradio-app/gradio/pull/1235)
+- ensure defaults height match for media inputs by [@pngwn](https://github.com/pngwn) in [PR 1236](https://github.com/gradio-app/gradio/pull/1236)
+- Default Label label value by [@radames](https://github.com/radames) in [PR 1239](https://github.com/gradio-app/gradio/pull/1239)
+- update-shortcut-syntax by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1234](https://github.com/gradio-app/gradio/pull/1234)
+- Update version.txt by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1244](https://github.com/gradio-app/gradio/pull/1244)
+- Layout bugs by [@pngwn](https://github.com/pngwn) in [PR 1246](https://github.com/gradio-app/gradio/pull/1246)
+- Update demo by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1253](https://github.com/gradio-app/gradio/pull/1253)
+- Button default name by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1243](https://github.com/gradio-app/gradio/pull/1243)
+- Labels spacing by [@gary149](https://github.com/gary149) in [PR 1254](https://github.com/gradio-app/gradio/pull/1254)
+- add global loader for gradio app by [@pngwn](https://github.com/pngwn) in [PR 1251](https://github.com/gradio-app/gradio/pull/1251)
+- ui apis for dalle-mini by [@pngwn](https://github.com/pngwn) in [PR 1258](https://github.com/gradio-app/gradio/pull/1258)
+- Add precision to Number, backend only by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1125](https://github.com/gradio-app/gradio/pull/1125)
+- Website Design Changes by [@abidlabs](https://github.com/abidlabs) in [PR 1015](https://github.com/gradio-app/gradio/pull/1015)
+- Small fixes for multiple demos compatible with 3.0 by [@radames](https://github.com/radames) in [PR 1257](https://github.com/gradio-app/gradio/pull/1257)
+- Issue #1160: Model 3D component not destroyed correctly by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1219](https://github.com/gradio-app/gradio/pull/1219)
+- Fixes to components by [@abidlabs](https://github.com/abidlabs) in [PR 1260](https://github.com/gradio-app/gradio/pull/1260)
+- layout docs by [@abidlabs](https://github.com/abidlabs) in [PR 1263](https://github.com/gradio-app/gradio/pull/1263)
+- Static forms by [@pngwn](https://github.com/pngwn) in [PR 1264](https://github.com/gradio-app/gradio/pull/1264)
+- Cdn assets by [@pngwn](https://github.com/pngwn) in [PR 1265](https://github.com/gradio-app/gradio/pull/1265)
+- update logo by [@gary149](https://github.com/gary149) in [PR 1266](https://github.com/gradio-app/gradio/pull/1266)
+- fix slider by [@aliabid94](https://github.com/aliabid94) in [PR 1268](https://github.com/gradio-app/gradio/pull/1268)
+- maybe fix auth in iframes by [@pngwn](https://github.com/pngwn) in [PR 1261](https://github.com/gradio-app/gradio/pull/1261)
+- Improves "Getting Started" guide by [@abidlabs](https://github.com/abidlabs) in [PR 1269](https://github.com/gradio-app/gradio/pull/1269)
+- Add embedded demos to website by [@aliabid94](https://github.com/aliabid94) in [PR 1270](https://github.com/gradio-app/gradio/pull/1270)
+- Label hotfixes by [@abidlabs](https://github.com/abidlabs) in [PR 1281](https://github.com/gradio-app/gradio/pull/1281)
+- General tweaks by [@pngwn](https://github.com/pngwn) in [PR 1276](https://github.com/gradio-app/gradio/pull/1276)
+- only affect links within the document by [@pngwn](https://github.com/pngwn) in [PR 1282](https://github.com/gradio-app/gradio/pull/1282)
+- release 3.0b9 by [@abidlabs](https://github.com/abidlabs) in [PR 1283](https://github.com/gradio-app/gradio/pull/1283)
+- Dm by [@pngwn](https://github.com/pngwn) in [PR 1284](https://github.com/gradio-app/gradio/pull/1284)
+- Website fixes by [@aliabd](https://github.com/aliabd) in [PR 1286](https://github.com/gradio-app/gradio/pull/1286)
+- Create Streamables by [@aliabid94](https://github.com/aliabid94) in [PR 1279](https://github.com/gradio-app/gradio/pull/1279)
+- ensure table works on mobile by [@pngwn](https://github.com/pngwn) in [PR 1277](https://github.com/gradio-app/gradio/pull/1277)
+- changes by [@aliabid94](https://github.com/aliabid94) in [PR 1287](https://github.com/gradio-app/gradio/pull/1287)
+- demo alignment on landing page by [@aliabd](https://github.com/aliabd) in [PR 1288](https://github.com/gradio-app/gradio/pull/1288)
+- New meta img by [@aliabd](https://github.com/aliabd) in [PR 1289](https://github.com/gradio-app/gradio/pull/1289)
+- updated PyPi version to 3.0 by [@abidlabs](https://github.com/abidlabs) in [PR 1290](https://github.com/gradio-app/gradio/pull/1290)
+- Fix site by [@aliabid94](https://github.com/aliabid94) in [PR 1291](https://github.com/gradio-app/gradio/pull/1291)
+- Mobile responsive guides by [@aliabd](https://github.com/aliabd) in [PR 1293](https://github.com/gradio-app/gradio/pull/1293)
+- Update readme by [@abidlabs](https://github.com/abidlabs) in [PR 1292](https://github.com/gradio-app/gradio/pull/1292)
+- gif by [@abidlabs](https://github.com/abidlabs) in [PR 1296](https://github.com/gradio-app/gradio/pull/1296)
+- Allow decoding headerless b64 string [@1lint](https://github.com/1lint) in [PR 4031](https://github.com/gradio-app/gradio/pull/4031)
+
+### Contributors Shoutout:
+
+- [@JefferyChiang](https://github.com/JefferyChiang) made their first contribution in [PR 1004](https://github.com/gradio-app/gradio/pull/1004)
+- [@NimaBoscarino](https://github.com/NimaBoscarino) made their first contribution in [PR 1000](https://github.com/gradio-app/gradio/pull/1000)
+- [@ronvoluted](https://github.com/ronvoluted) made their first contribution in [PR 1050](https://github.com/gradio-app/gradio/pull/1050)
+- [@radames](https://github.com/radames) made their first contribution in [PR 1074](https://github.com/gradio-app/gradio/pull/1074)
+- [@freddyaboulton](https://github.com/freddyaboulton) made their first contribution in [PR 1085](https://github.com/gradio-app/gradio/pull/1085)
+- [@liteli1987gmail](https://github.com/liteli1987gmail) & [@chenglu](https://github.com/chenglu) made their first contribution in [PR 4767](https://github.com/gradio-app/gradio/pull/4767)
\ No newline at end of file
diff --git a/CITATION.cff b/CITATION.cff
new file mode 100644
index 0000000000000000000000000000000000000000..0768f8c42506e23405e4c66661b327ed32028208
--- /dev/null
+++ b/CITATION.cff
@@ -0,0 +1,45 @@
+cff-version: 1.2.0
+message: Please cite this project using these metadata.
+title: "Gradio: Hassle-free sharing and testing of ML models in the wild"
+abstract: >-
+ Accessibility is a major challenge of machine learning (ML).
+ Typical ML models are built by specialists and require
+ specialized hardware/software as well as ML experience to
+ validate. This makes it challenging for non-technical
+ collaborators and endpoint users (e.g. physicians) to easily
+ provide feedback on model development and to gain trust in
+ ML. The accessibility challenge also makes collaboration
+ more difficult and limits the ML researcher's exposure to
+ realistic data and scenarios that occur in the wild. To
+ improve accessibility and facilitate collaboration, we
+ developed an open-source Python package, Gradio, which
+ allows researchers to rapidly generate a visual interface
+ for their ML models. Gradio makes accessing any ML model as
+ easy as sharing a URL. Our development of Gradio is informed
+ by interviews with a number of machine learning researchers
+ who participate in interdisciplinary collaborations. Their
+ feedback identified that Gradio should support a variety of
+ interfaces and frameworks, allow for easy sharing of the
+ interface, allow for input manipulation and interactive
+ inference by the domain expert, as well as allow embedding
+ the interface in iPython notebooks. We developed these
+ features and carried out a case study to understand Gradio's
+ usefulness and usability in the setting of a machine
+ learning collaboration between a researcher and a
+ cardiologist.
+authors:
+ - family-names: Abid
+ given-names: Abubakar
+ - family-names: Abdalla
+ given-names: Ali
+ - family-names: Abid
+ given-names: Ali
+ - family-names: Khan
+ given-names: Dawood
+ - family-names: Alfozan
+ given-names: Abdulrahman
+ - family-names: Zou
+ given-names: James
+doi: 10.48550/arXiv.1906.02569
+date-released: 2019-06-06
+url: https://arxiv.org/abs/1906.02569
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..8c16f67fb76c501e77a6430172117021b0464c99
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,266 @@
+# Contributing to Gradio
+
+![GitHub issues by-label](https://img.shields.io/github/issues/gradio-app/gradio/good%20first%20issue?color=fe7c01&link=https%3A%2F%2Fgithub.com%2Fgradio-app%2Fgradio%2Fissues%3Fq%3Dis%253Aopen%2Bis%253Aissue%2Blabel%253A%2522good%2Bfirst%2Bissue%2522)
+
+
+More than 200 awesome developers have contributed to the `gradio` library, and we'd be thrilled if you would like to be the next contributor!
+
+Prerequisites:
+
+- [Python 3.8+](https://www.python.org/downloads/)
+- [Node.js v16.14+](https://nodejs.dev/en/download/package-manager/) (only needed if you are making changes to the frontend)
+- [pnpm 8.1+](https://pnpm.io/8.x/installation) (only needed if you are making changes to the frontend)
+
+## 🏡 Setup for local development
+
+There are a few ways to install and run Gradio.
+
+### 🛠️ Install Gradio locally from `main`
+
+- Clone this repo
+- Navigate to the repo directory and (from the root directory) run
+
+```bash
+bash scripts/install_gradio.sh
+```
+
+- Build the front end
+
+```
+bash scripts/build_frontend.sh
+```
+
+- Install development requirements
+
+(Note that it is highly recommended to use a virtual environment running **Python 3.9** since the versions of Gradio's dependencies are pinned)
+
+```
+bash scripts/install_test_requirements.sh
+```
+
+If you have a different Python version and conflicting packages during the installation, please first run:
+
+```
+bash scripts/create_test_requirements.sh
+```
+
+### 📦 Using dev containers
+
+You can alternatively use dev containers. This is supported on all platforms (macOS/Windows/Linux), as well as on GitHub Codespaces.
+
+Prerequisites:
+
+- An editor which supports dev containers, like VS Code
+- Docker support on the host computer:
+ - macOS: [Docker Desktop 2.0+](https://www.docker.com/products/docker-desktop/)
+ - Windows: [Docker Desktop 2.0+](https://www.docker.com/products/docker-desktop/)
+ - Linux: [Docker CE/EE 18.06+](https://docs.docker.com/get-docker/) and [Docker Compose 1.21+](https://docs.docker.com/compose/install/)
+- If using VS Code, the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension
+
+Steps:
+
+- Clone repository
+- Open it in your editor
+- For VS Code, execute `Dev Containers: Reopen in container` command
+
+For detailed instructions, please see the [Dev Containers tutorial](https://code.visualstudio.com/docs/devcontainers/tutorial).
+
+## 🧱 Structure of the Repository
+
+If you're a newcomer to Gradio, we recommend getting familiar with the overall structure of the repository so that you can focus on the part of the source code you'd like to contribute to.
+
+- `/gradio`: contains the Python source code for the library
+ - `/gradio/interface.py`: contains the Python source code for the core `Interface` class
+ - `/gradio/blocks.py`: contains the Python source code for the core `Blocks` class
+ - `/gradio/components/`: the directory that contains the Python source code for all of the Gradio components.
+- `/js`: contains the HTML/JS/CSS source code for the library ([start here for frontend changes](/js/README.md))
+ - `/js/_website`: contains the code for the Gradio website (www.gradio.app). See the README in the `/js/_website` folder for more details
+- `/test`: contains Python unit tests for the library
+- `/demo`: contains demos that are used in the documentation, you can find `Gradio` examples over here.
+
+
+## 🚀 Run a Gradio app
+
+You can get started by creating an `app.py` file in the root:
+
+```
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Button()
+
+if __name__ == "__main__":
+ demo.launch()
+```
+
+then run:
+
+```
+gradio app.py
+```
+
+This will start the backend server in reload mode, which will watch for changes in the `gradio` folder and reload the app if changes are made. By default, Gradio will launch on port 7860. You can also just use `python app.py`, but this won't automatically trigger updates.
+
+
+If you're making frontend changes, start the frontend server:
+
+```
+pnpm dev
+```
+
+This will open a separate browser tab. By default, Gradio will launch this on port 9876. Any changes to the frontend will also reload automatically in the browser. For more information about developing in the frontend, you can refer to [js/README.md](js/README.md).
+
+We also have demos of all our components in the `/gradio/demo` directory. To get our simple gradio Chatbot running locally:
+
+```
+gradio demo/chatbot_simple/run.py
+```
+
+
+## 🧪 Testing
+
+We use Pytest, Playwright and Vitest to test our code.
+
+- The Python tests are located in `/test`. To run these tests:
+
+```
+bash scripts/run_all_tests.sh
+```
+
+- The frontend unit tests are any defined with the filename `*.test.ts`. To run them:
+
+```
+pnpm test
+```
+
+- Browser tests are located in `js/app/test` and are defined as `*spec.ts` files. To run browser tests:
+
+```
+pnpm test:browser
+```
+
+To build the frontend code before running browser tests:
+
+```
+pnpm test:browser:full
+```
+
+You can also run browser tests in the UI mode by adding the `--ui` flag:
+
+```
+pnpm test:browser --ui
+```
+
+If you have made any significant visual changes to a component, we encourage you to add a new Storybook story or amend an existing one to reflect them. You can create a new story with a `*.stories.svelte` file. You can run the storybook locally:
+
+```
+pnpm storybook
+```
+
+## 🕸️ Gradio Website
+
+We also welcome any contributions to our [website](https://www.gradio.app).
+
+First, build the website:
+
+```
+pnpm build:cdn-local
+```
+then serve the website build:
+```
+pnpm preview:cdn-local
+```
+
+This will serve a build of `gradio.js` on port `4321`. You can then navigate to `js/_website/src/routes/+layout.svelte` and replace the source of the website build from:
+```
+
+```
+to
+```
+
+```
+
+You should now be able to view a local version of the website at `http://localhost:4321`.
+
+## 🌎 Gradio-Lite
+
+Gradio-Lite is a Pyodide-based library that lets you run Gradio serverless (in other words, directly in your browser).
+
+You can start the development server by running:
+```
+bash scripts/run_lite.sh
+```
+
+If you make changes to the Python code during development, you will need to rebuild the Python packages loaded to Graio-Lite. To do this, run:
+```
+pnpm --filter @gradio/app pybuild
+```
+
+To generate the release build, run:
+```
+bash scripts/build_lite.sh
+```
+The release build will be located in the `dist` directory in the `js/lite` project.
+To test it, you can run a local server in the `js/lite` directory:
+```
+python -m http.server --directory js/lite
+```
+and navigate to `http://localhost:8000` in your browser. The demo page `index.html` located in the `js/lite` directory will be loaded.
+
+## 📮 Submitting PRs
+
+All PRs should be against `main`, and ideally should address an open issue, unless the change is small. Direct commits to main are blocked, and PRs require an approving review to merge into main. By convention, the Gradio maintainers will review PRs when:
+
+- An initial review has been requested
+- A clear, descriptive title has been assigned to the PR
+- A maintainer (@abidlabs, @aliabid94, @aliabd, @AK391, @dawoodkhan82, @pngwn, @freddyaboulton, @hannahblair, @hysts, @whitphx) is tagged in the PR comments and asked to complete a review
+
+ 🧹 We ask that you make sure initial CI checks are passing before requesting a review. One of the Gradio maintainers will merge the PR when all the checks are passing. You can safely ignore the Vercel and Spaces checks, which only run under maintainers' pull requests.
+
+Don't forget the format your code before pushing:
+
+```
+bash scripts/format_backend.sh
+```
+
+And if you made changes to the frontend:
+
+```
+bash scripts/format_frontend.sh
+```
+
+Thank you for taking the time to contribute to Gradio!
+
+
+## ❓ Need help getting started?
+
+- Browse [issues](https://github.com/gradio-app/gradio/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) with the "good first issue" label. These are issues we think are good for newcomers.
+- Ask the Gradio community in our [Discord](https://discord.com/invite/feTf9x3ZSB)
+- Raise an issue for a feature or a bug you want to tackle
+
+## 🚧 Troubleshooting
+`ERROR: Error loading ASGI app. Could not import module ""`
+
+Verify that you've used the correct filename of your gradio app, and that you're in the directory of the file.
+
+---
+
+```ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @gradio/app@1.0.0 build:local: vite build --mode production:local --emptyOutDir "--emptyOutDir"```
+
+Delete `/node_modules` and `pnpm-lock.yaml`:
+
+```
+rm -rf node_modules/
+rm pnpm-lock.yaml
+```
+
+and run the install scripts:
+
+```
+bash scripts/install_gradio.sh
+bash scripts/build_frontend.sh
+```
+---
+
+_Could these guidelines be clearer? Feel free to open a PR to help us facilitate open-source contributions!_
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index e665514f546b5d0c7ca6e00611516fb8765c7a02..5f4fc24082ce1efca10274873a6341b2a3f03c3e 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,205 @@
---
-title: Gradio
-emoji: 📈
-colorFrom: purple
-colorTo: purple
-sdk: gradio
-sdk_version: 4.16.0
+title: gradio
app_file: app.py
-pinned: false
+sdk: gradio
+sdk_version: 3.50.2
---
+
+
+
+
+[
](https://gradio.app)
+
+[![gradio-backend](https://github.com/gradio-app/gradio/actions/workflows/backend.yml/badge.svg)](https://github.com/gradio-app/gradio/actions/workflows/backend.yml)
+[![gradio-ui](https://github.com/gradio-app/gradio/actions/workflows/ui.yml/badge.svg)](https://github.com/gradio-app/gradio/actions/workflows/ui.yml)
+ [![PyPI](https://img.shields.io/pypi/v/gradio)](https://pypi.org/project/gradio/)
+[![PyPI downloads](https://img.shields.io/pypi/dm/gradio)](https://pypi.org/project/gradio/)
+![Python version](https://img.shields.io/badge/python-3.8+-important)
+[![Twitter follow](https://img.shields.io/twitter/follow/gradio?style=social&label=follow)](https://twitter.com/gradio)
+
+[Website](https://gradio.app)
+| [Documentation](https://gradio.app/docs/)
+| [Guides](https://gradio.app/guides/)
+| [Getting Started](https://gradio.app/getting_started/)
+| [Examples](demo/)
+| [中文](readme_files/zh-cn#readme)
+
+
+
+# Gradio: Build Machine Learning Web Apps — in Python
+
+
+
+Gradio is an open-source Python package that allows you to quickly **build** a demo or web application for your machine learning model, API, or any arbitrary Python function. You can then **share** a link to your demo or web application in just a few seconds using Gradio's built-in sharing features. *No JavaScript, CSS, or web hosting experience needed!*
+
+
+
+It just takes a few lines of Python to create a beautiful demo like the one above, so let's get started 💫
+
+### Installation
+
+**Prerequisite**: Gradio requires [Python 3.8 or higher](https://www.python.org/downloads/)
+
+
+We recommend installing Gradio using `pip`, which is included by default in Python. Run this in your terminal or command prompt:
+
+```
+pip install gradio
+```
+
+
+> [!TIP]
+ > It is best to install Gradio in a virtual environment. Detailed installation instructions for all common operating systems are provided here .
+
+### Building Your First Demo
+
+You can run Gradio in your favorite code editor, Jupyter notebook, Google Colab, or anywhere else you write Python. Let's write your first Gradio app:
+
+
+```python
+import gradio as gr
+
+def greet(name, intensity):
+ return "Hello " * intensity + name + "!"
+
+demo = gr.Interface(
+ fn=greet,
+ inputs=["text", "slider"],
+ outputs=["text"],
+)
+
+demo.launch()
+```
+
+
+
+> [!TIP]
+ > We shorten the imported name from gradio
to gr
for better readability of code. This is a widely adopted convention that you should follow so that anyone working with your code can easily understand it.
+
+Now, run your code. If you've written the Python code in a file named, for example, `app.py`, then you would run `python app.py` from the terminal.
+
+The demo below will open in a browser on [http://localhost:7860](http://localhost:7860) if running from a file. If you are running within a notebook, the demo will appear embedded within the notebook.
+
+![`hello_world_4` demo](demo/hello_world_4/screenshot.gif)
+
+Type your name in the textbox on the left, drag the slider, and then press the Submit button. You should see a friendly greeting on the right.
+
+> [!TIP]
+ > When developing locally, you can run your Gradio app in hot reload mode , which automatically reloads the Gradio app whenever you make changes to the file. To do this, simply type in gradio
before the name of the file instead of python
. In the example above, you would type: `gradio app.py` in your terminal. Learn more about hot reloading in the Hot Reloading Guide .
+
+
+**Understanding the `Interface` Class**
+
+You'll notice that in order to make your first demo, you created an instance of the `gr.Interface` class. The `Interface` class is designed to create demos for machine learning models which accept one or more inputs, and return one or more outputs.
+
+The `Interface` class has three core arguments:
+
+- `fn`: the function to wrap a user interface (UI) around
+- `inputs`: the Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.
+- `outputs`: the Gradio component(s) to use for the output. The number of components should match the number of return values from your function.
+
+The `fn` argument is very flexible -- you can pass *any* Python function that you want to wrap with a UI. In the example above, we saw a relatively simple function, but the function could be anything from a music generator to a tax calculator to the prediction function of a pretrained machine learning model.
+
+The `input` and `output` arguments take one or more Gradio components. As we'll see, Gradio includes more than [30 built-in components](https://www.gradio.app/docs/components) (such as the `gr.Textbox()`, `gr.Image()`, and `gr.HTML()` components) that are designed for machine learning applications.
+
+> [!TIP]
+ > For the `inputs` and `outputs` arguments, you can pass in the name of these components as a string (`"textbox"`) or an instance of the class (`gr.Textbox()`).
+
+If your function accepts more than one argument, as is the case above, pass a list of input components to `inputs`, with each input component corresponding to one of the arguments of the function, in order. The same holds true if your function returns more than one value: simply pass in a list of components to `outputs`. This flexibility makes the `Interface` class a very powerful way to create demos.
+
+We'll dive deeper into the `gr.Interface` on our series on [building Interfaces](https://www.gradio.app/main/guides/the-interface-class).
+
+### Sharing Your Demo
+
+What good is a beautiful demo if you can't share it? Gradio lets you easily share a machine learning demo without having to worry about the hassle of hosting on a web server. Simply set `share=True` in `launch()`, and a publicly accessible URL will be created for your demo. Let's revisit our example demo, but change the last line as follows:
+
+```python
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
+
+demo.launch(share=True) # Share your demo with just 1 extra parameter 🚀
+```
+
+When you run this code, a public URL will be generated for your demo in a matter of seconds, something like:
+
+👉 `https://a23dsf231adb.gradio.live`
+
+Now, anyone around the world can try your Gradio demo from their browser, while the machine learning model and all computation continues to run locally on your computer.
+
+To learn more about sharing your demo, read our dedicated guide on [sharing your Gradio application](https://www.gradio.app/guides/sharing-your-app).
+
+
+### An Overview of Gradio
+
+So far, we've been discussing the `Interface` class, which is a high-level class that lets to build demos quickly with Gradio. But what else does Gradio do?
+
+#### Chatbots with `gr.ChatInterface`
+
+Gradio includes another high-level class, `gr.ChatInterface`, which is specifically designed to create Chatbot UIs. Similar to `Interface`, you supply a function and Gradio creates a fully working Chatbot UI. If you're interested in creating a chatbot, you can jump straight [our dedicated guide on `gr.ChatInterface`](https://www.gradio.app/guides/creating-a-chatbot-fast).
+
+#### Custom Demos with `gr.Blocks`
+
+Gradio also offers a low-level approach for designing web apps with more flexible layouts and data flows with the `gr.Blocks` class. Blocks allows you to do things like control where components appear on the page, handle complex data flows (e.g. outputs can serve as inputs to other functions), and update properties/visibility of components based on user interaction — still all in Python.
+
+You can build very custom and complex applications using `gr.Blocks()`. For example, the popular image generation [Automatic1111 Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) is built using Gradio Blocks. We dive deeper into the `gr.Blocks` on our series on [building with Blocks](https://www.gradio.app/guides/blocks-and-event-listeners).
+
+
+#### The Gradio Python & JavaScript Ecosystem
+
+That's the gist of the core `gradio` Python library, but Gradio is actually so much more! Its an entire ecosystem of Python and JavaScript libraries that let you build machine learning applications, or query them programmatically, in Python or JavaScript. Here are other related parts of the Gradio ecosystem:
+
+* [Gradio Python Client](https://www.gradio.app/guides/getting-started-with-the-python-client) (`gradio_client`): query any Gradio app programmatically in Python.
+* [Gradio JavaScript Client](https://www.gradio.app/guides/getting-started-with-the-js-client) (`@gradio/client`): query any Gradio app programmatically in JavaScript.
+* [Gradio-Lite](https://www.gradio.app/guides/gradio-lite) (`@gradio/lite`): write Gradio apps in Python that run entirely in the browser (no server needed!), thanks to Pyodide.
+* [Hugging Face Spaces](https://huggingface.co/spaces): the most popular place to host Gradio applications — for free!
+
+### What's Next?
+
+Keep learning about Gradio sequentially using the Gradio Guides, which include explanations as well as example code and embedded interactive demos. Next up: [key features about Gradio demos](https://www.gradio.app/guides/key-features).
+
+Or, if you already know the basics and are looking for something specific, you can search the more [technical API documentation](https://www.gradio.app/docs/).
+
+
+
+
+## Questions?
+
+If you'd like to report a bug or have a feature request, please create an [issue on GitHub](https://github.com/gradio-app/gradio/issues/new/choose). For general questions about usage, we are available on [our Discord server](https://discord.com/invite/feTf9x3ZSB) and happy to help.
+
+If you like Gradio, please leave us a ⭐ on GitHub!
+
+## Open Source Stack
+
+Gradio is built on top of many wonderful open-source libraries!
+
+[ ](https://huggingface.co)
+[ ](https://www.python.org)
+[ ](https://fastapi.tiangolo.com)
+[ ](https://www.encode.io)
+[ ](https://svelte.dev)
+[ ](https://vitejs.dev)
+[ ](https://pnpm.io)
+[ ](https://tailwindcss.com)
+[ ](https://storybook.js.org/)
+[ ](https://www.chromatic.com/)
+
+## License
+
+Gradio is licensed under the Apache License 2.0 found in the [LICENSE](LICENSE) file in the root directory of this repository.
+
+## Citation
+
+Also check out the paper _[Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild](https://arxiv.org/abs/1906.02569), ICML HILL 2019_, and please cite it if you use Gradio in your work.
-Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
+```
+@article{abid2019gradio,
+ title = {Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild},
+ author = {Abid, Abubakar and Abdalla, Ali and Abid, Ali and Khan, Dawood and Alfozan, Abdulrahman and Zou, James},
+ journal = {arXiv preprint arXiv:1906.02569},
+ year = {2019},
+}
+```
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000000000000000000000000000000000..d5619fb774c461d8a7f6ec806b92a6efa28004ca
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,5 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability, we would be very grateful if you could email us at team@gradio.app. This is the preferred approach instead of opening a public issue. We take all vulnerability reports seriously, and will work to patch the vulnerability immediately. Whenever possible, we will credit the person or people who report the security vulnerabilities after it has been patched.
diff --git a/app.py b/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..382bbf262efe6fab00536a6c3165486d752d510b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,8 @@
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+iface = gr.Interface(fn=greet, inputs="text", outputs="text")
+iface.launch(share=True)
+
diff --git a/build_pypi.sh b/build_pypi.sh
new file mode 100644
index 0000000000000000000000000000000000000000..32c76e1f58cdf269623c011d9b066dc504993689
--- /dev/null
+++ b/build_pypi.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+
+cd "$(dirname ${0})"
+
+# You should update the version in package.json before running this script
+FILE="gradio/package.json"
+new_version=$(python -c "import json; f = open('$FILE', 'r'); data = json.load(f); print(data['version']); f.close();")
+GRADIO_VERSION=$new_version
+
+rm -rf gradio/templates/frontend
+pnpm i --frozen-lockfile --ignore-scripts
+GRADIO_VERSION=$new_version pnpm build
+aws s3 cp gradio/templates/frontend "s3://gradio/${new_version}/" --recursive --region us-west-2
+
+rm -rf dist/*
+rm -rf build/*
+python3 -m build
diff --git a/client/js/CHANGELOG.md b/client/js/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..7c0b67c8e3baf5b3e1c6289f1ffdb6149ce1fc43
--- /dev/null
+++ b/client/js/CHANGELOG.md
@@ -0,0 +1,239 @@
+# @gradio/client
+
+## 0.10.1
+
+### Fixes
+
+- [#7055](https://github.com/gradio-app/gradio/pull/7055) [`3c3cf86`](https://github.com/gradio-app/gradio/commit/3c3cf8618a8cad1ef66a7f96664923d2c9f5e0e2) - Fix UI freeze on rapid generators. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.10.0
+
+### Features
+
+- [#6931](https://github.com/gradio-app/gradio/pull/6931) [`6c863af`](https://github.com/gradio-app/gradio/commit/6c863af92fa9ceb5c638857eb22cc5ddb718d549) - Fix functional tests. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6820](https://github.com/gradio-app/gradio/pull/6820) [`649cd4d`](https://github.com/gradio-app/gradio/commit/649cd4d68041d11fcbe31f8efa455345ac49fc74) - Use `EventSource_factory` in `open_stream()` for Wasm. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 0.9.4
+
+### Fixes
+
+- [#6863](https://github.com/gradio-app/gradio/pull/6863) [`d406855`](https://github.com/gradio-app/gradio/commit/d4068557953746662235d595ec435c42ceb24414) - Fix JS Client when app is running behind a proxy. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.9.3
+
+### Features
+
+- [#6814](https://github.com/gradio-app/gradio/pull/6814) [`828fb9e`](https://github.com/gradio-app/gradio/commit/828fb9e6ce15b6ea08318675a2361117596a1b5d) - Refactor queue so that there are separate queues for each concurrency id. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.9.2
+
+### Features
+
+- [#6798](https://github.com/gradio-app/gradio/pull/6798) [`245d58e`](https://github.com/gradio-app/gradio/commit/245d58eff788e8d44a59d37a2d9b26d0f08a62b4) - Improve how server/js client handle unexpected errors. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.9.1
+
+### Fixes
+
+- [#6693](https://github.com/gradio-app/gradio/pull/6693) [`34f9431`](https://github.com/gradio-app/gradio/commit/34f943101bf7dd6b8a8974a6131c1ed7c4a0dac0) - Python client properly handles hearbeat and log messages. Also handles responses longer than 65k. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.9.0
+
+### Features
+
+- [#6398](https://github.com/gradio-app/gradio/pull/6398) [`67ddd40`](https://github.com/gradio-app/gradio/commit/67ddd40b4b70d3a37cb1637c33620f8d197dbee0) - Lite v4. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#6556](https://github.com/gradio-app/gradio/pull/6556) [`d76bcaa`](https://github.com/gradio-app/gradio/commit/d76bcaaaf0734aaf49a680f94ea9d4d22a602e70) - Fix api event drops. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.8.2
+
+### Features
+
+- [#6511](https://github.com/gradio-app/gradio/pull/6511) [`71f1a1f99`](https://github.com/gradio-app/gradio/commit/71f1a1f9931489d465c2c1302a5c8d768a3cd23a) - Mark `FileData.orig_name` optional on the frontend aligning the type definition on the Python side. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 0.8.1
+
+### Fixes
+
+- [#6383](https://github.com/gradio-app/gradio/pull/6383) [`324867f63`](https://github.com/gradio-app/gradio/commit/324867f63c920113d89a565892aa596cf8b1e486) - Fix event target. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.8.0
+
+### Features
+
+- [#6307](https://github.com/gradio-app/gradio/pull/6307) [`f1409f95e`](https://github.com/gradio-app/gradio/commit/f1409f95ed39c5565bed6a601e41f94e30196a57) - Provide status updates on file uploads. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.7.2
+
+### Fixes
+
+- [#6327](https://github.com/gradio-app/gradio/pull/6327) [`bca6c2c80`](https://github.com/gradio-app/gradio/commit/bca6c2c80f7e5062427019de45c282238388af95) - Restore query parameters in request. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.1
+
+### Features
+
+- [#6137](https://github.com/gradio-app/gradio/pull/6137) [`2ba14b284`](https://github.com/gradio-app/gradio/commit/2ba14b284f908aa13859f4337167a157075a68eb) - JS Param. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 0.7.0
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Swap websockets for SSE. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.7.0-beta.1
+
+### Features
+
+- [#6143](https://github.com/gradio-app/gradio/pull/6143) [`e4f7b4b40`](https://github.com/gradio-app/gradio/commit/e4f7b4b409323b01aa01b39e15ce6139e29aa073) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6069](https://github.com/gradio-app/gradio/pull/6069) [`bf127e124`](https://github.com/gradio-app/gradio/commit/bf127e1241a41401e144874ea468dff8474eb505) - Swap websockets for SSE. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.0-beta.0
+
+### Features
+
+- [#6016](https://github.com/gradio-app/gradio/pull/6016) [`83e947676`](https://github.com/gradio-app/gradio/commit/83e947676d327ca2ab6ae2a2d710c78961c771a0) - Format js in v4 branch. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#6046](https://github.com/gradio-app/gradio/pull/6046) [`dbb7de5e0`](https://github.com/gradio-app/gradio/commit/dbb7de5e02c53fee05889d696d764d212cb96c74) - fix tests. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.6.0
+
+### Features
+
+- [#5972](https://github.com/gradio-app/gradio/pull/5972) [`11a300791`](https://github.com/gradio-app/gradio/commit/11a3007916071f0791844b0a37f0fb4cec69cea3) - Lite: Support opening the entrypoint HTML page directly in browser via the `file:` protocol. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 0.5.2
+
+### Fixes
+
+- [#5840](https://github.com/gradio-app/gradio/pull/5840) [`4e62b8493`](https://github.com/gradio-app/gradio/commit/4e62b8493dfce50bafafe49f1a5deb929d822103) - Ensure websocket polyfill doesn't load if there is already a `global.Webocket` property set. Thanks [@Jay2theWhy](https://github.com/Jay2theWhy)!
+
+## 0.5.1
+
+### Fixes
+
+- [#5816](https://github.com/gradio-app/gradio/pull/5816) [`796145e2c`](https://github.com/gradio-app/gradio/commit/796145e2c48c4087bec17f8ec0be4ceee47170cb) - Fix calls to the component server so that `gr.FileExplorer` works on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.5.0
+
+### Highlights
+
+#### new `FileExplorer` component ([#5672](https://github.com/gradio-app/gradio/pull/5672) [`e4a307ed6`](https://github.com/gradio-app/gradio/commit/e4a307ed6cde3bbdf4ff2f17655739addeec941e))
+
+Thanks to a new capability that allows components to communicate directly with the server _without_ passing data via the value, we have created a new `FileExplorer` component.
+
+This component allows you to populate the explorer by passing a glob, but only provides the selected file(s) in your prediction function.
+
+Users can then navigate the virtual filesystem and select files which will be accessible in your predict function. This component will allow developers to build more complex spaces, with more flexible input options.
+
+![output](https://github.com/pngwn/MDsveX/assets/12937446/ef108f0b-0e84-4292-9984-9dc66b3e144d)
+
+For more information check the [`FileExplorer` documentation](https://gradio.app/docs/fileexplorer).
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5787](https://github.com/gradio-app/gradio/pull/5787) [`caeee8bf7`](https://github.com/gradio-app/gradio/commit/caeee8bf7821fd5fe2f936ed82483bed00f613ec) - ensure the client does not depend on `window` when running in a node environment. Thanks [@gibiee](https://github.com/gibiee)!
+
+### Fixes
+
+- [#5776](https://github.com/gradio-app/gradio/pull/5776) [`c0fef4454`](https://github.com/gradio-app/gradio/commit/c0fef44541bfa61568bdcfcdfc7d7d79869ab1df) - Revert replica proxy logic and instead implement using the `root` variable. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.4.2
+
+### Features
+
+- [#5124](https://github.com/gradio-app/gradio/pull/5124) [`6e56a0d9b`](https://github.com/gradio-app/gradio/commit/6e56a0d9b0c863e76c69e1183d9d40196922b4cd) - Lite: Websocket queueing. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 0.4.1
+
+### Fixes
+
+- [#5705](https://github.com/gradio-app/gradio/pull/5705) [`78e7cf516`](https://github.com/gradio-app/gradio/commit/78e7cf5163e8d205e8999428fce4c02dbdece25f) - ensure internal data has updated before dispatching `success` or `then` events. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.4.0
+
+### Features
+
+- [#5682](https://github.com/gradio-app/gradio/pull/5682) [`c57f1b75e`](https://github.com/gradio-app/gradio/commit/c57f1b75e272c76b0af4d6bd0c7f44743ff34f26) - Fix functional tests. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5681](https://github.com/gradio-app/gradio/pull/5681) [`40de3d217`](https://github.com/gradio-app/gradio/commit/40de3d2178b61ebe424b6f6228f94c0c6f679bea) - add query parameters to the `gr.Request` object through the `query_params` attribute. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5653](https://github.com/gradio-app/gradio/pull/5653) [`ea0e00b20`](https://github.com/gradio-app/gradio/commit/ea0e00b207b4b90a10e9d054c4202d4e705a29ba) - Prevent Clients from accessing API endpoints that set `api_name=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.3.1
+
+### Fixes
+
+- [#5412](https://github.com/gradio-app/gradio/pull/5412) [`26fef8c7`](https://github.com/gradio-app/gradio/commit/26fef8c7f85a006c7e25cdbed1792df19c512d02) - Skip view_api request in js client when auth enabled. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.3.0
+
+### Features
+
+- [#5267](https://github.com/gradio-app/gradio/pull/5267) [`119c8343`](https://github.com/gradio-app/gradio/commit/119c834331bfae60d4742c8f20e9cdecdd67e8c2) - Faster reload mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.2.1
+
+### Features
+
+- [#5173](https://github.com/gradio-app/gradio/pull/5173) [`730f0c1d`](https://github.com/gradio-app/gradio/commit/730f0c1d54792eb11359e40c9f2326e8a6e39203) - Ensure gradio client works as expected for functions that return nothing. Thanks [@raymondtri](https://github.com/raymondtri)!
+
+## 0.2.0
+
+### Features
+
+- [#5133](https://github.com/gradio-app/gradio/pull/5133) [`61129052`](https://github.com/gradio-app/gradio/commit/61129052ed1391a75c825c891d57fa0ad6c09fc8) - Update dependency esbuild to ^0.19.0. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5035](https://github.com/gradio-app/gradio/pull/5035) [`8b4eb8ca`](https://github.com/gradio-app/gradio/commit/8b4eb8cac9ea07bde31b44e2006ca2b7b5f4de36) - JS Client: Fixes cannot read properties of null (reading 'is_file'). Thanks [@raymondtri](https://github.com/raymondtri)!
+
+### Fixes
+
+- [#5075](https://github.com/gradio-app/gradio/pull/5075) [`67265a58`](https://github.com/gradio-app/gradio/commit/67265a58027ef1f9e4c0eb849a532f72eaebde48) - Allow supporting >1000 files in `gr.File()` and `gr.UploadButton()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.1.4
+
+### Patch Changes
+
+- [#4717](https://github.com/gradio-app/gradio/pull/4717) [`ab5d1ea0`](https://github.com/gradio-app/gradio/commit/ab5d1ea0de87ed888779b66fd2a705583bd29e02) Thanks [@whitphx](https://github.com/whitphx)! - Fix the package description
+
+## 0.1.3
+
+### Patch Changes
+
+- [#4357](https://github.com/gradio-app/gradio/pull/4357) [`0dbd8f7f`](https://github.com/gradio-app/gradio/commit/0dbd8f7fee4b4877f783fa7bc493f98bbfc3d01d) Thanks [@pngwn](https://github.com/pngwn)! - Various internal refactors and cleanups.
+
+## 0.1.2
+
+### Patch Changes
+
+- [#4273](https://github.com/gradio-app/gradio/pull/4273) [`1d0f0a9d`](https://github.com/gradio-app/gradio/commit/1d0f0a9db096552e67eb2197c932342587e9e61e) Thanks [@pngwn](https://github.com/pngwn)! - Ensure websocket error messages are correctly handled.
+
+- [#4315](https://github.com/gradio-app/gradio/pull/4315) [`b525b122`](https://github.com/gradio-app/gradio/commit/b525b122dd8569bbaf7e06db5b90d622d2e9073d) Thanks [@whitphx](https://github.com/whitphx)! - Refacor types.
+
+- [#4271](https://github.com/gradio-app/gradio/pull/4271) [`1151c525`](https://github.com/gradio-app/gradio/commit/1151c5253554cb87ebd4a44a8a470ac215ff782b) Thanks [@pngwn](https://github.com/pngwn)! - Ensure the full root path is always respected when making requests to a gradio app server.
+
+## 0.1.1
+
+### Patch Changes
+
+- [#4201](https://github.com/gradio-app/gradio/pull/4201) [`da5b4ee1`](https://github.com/gradio-app/gradio/commit/da5b4ee11721175858ded96e5710225369097f74) Thanks [@pngwn](https://github.com/pngwn)! - Ensure semiver is bundled so CDN links work correctly.
+
+- [#4202](https://github.com/gradio-app/gradio/pull/4202) [`a26e9afd`](https://github.com/gradio-app/gradio/commit/a26e9afde319382993e6ddc77cc4e56337a31248) Thanks [@pngwn](https://github.com/pngwn)! - Ensure all URLs returned by the client are complete URLs with the correct host instead of an absolute path relative to a server.
+
+## 0.1.0
+
+### Minor Changes
+
+- [#4185](https://github.com/gradio-app/gradio/pull/4185) [`67239ca9`](https://github.com/gradio-app/gradio/commit/67239ca9b2fe3796853fbf7bf865c9e4b383200d) Thanks [@pngwn](https://github.com/pngwn)! - Update client for initial release
+
+### Patch Changes
+
+- [#3692](https://github.com/gradio-app/gradio/pull/3692) [`48e8b113`](https://github.com/gradio-app/gradio/commit/48e8b113f4b55e461d9da4f153bf72aeb4adf0f1) Thanks [@pngwn](https://github.com/pngwn)! - Ensure client works in node, create ESM bundle and generate typescript declaration files.
+
+- [#3605](https://github.com/gradio-app/gradio/pull/3605) [`ae4277a9`](https://github.com/gradio-app/gradio/commit/ae4277a9a83d49bdadfe523b0739ba988128e73b) Thanks [@pngwn](https://github.com/pngwn)! - Update readme.
\ No newline at end of file
diff --git a/client/js/README.md b/client/js/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ddf80eb862ad5d36ec53cdef0f470d2aa67c41da
--- /dev/null
+++ b/client/js/README.md
@@ -0,0 +1,339 @@
+## JavaScript Client Library
+
+A javascript (and typescript) client to call Gradio APIs.
+
+## Installation
+
+The Gradio JavaScript client is available on npm as `@gradio/client`. You can install it as below:
+
+```sh
+npm i @gradio/client
+```
+
+## Usage
+
+The JavaScript Gradio Client exposes two named imports, `client` and `duplicate`.
+
+### `client`
+
+The client function connects to the API of a hosted Gradio space and returns an object that allows you to make calls to that API.
+
+The simplest example looks like this:
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const result = await app.predict("/predict");
+```
+
+This function accepts two arguments: `source` and `options`:
+
+#### `source`
+
+This is the url or name of the gradio app whose API you wish to connect to. This parameter is required and should always be a string. For example:
+
+```ts
+client("user/space-name");
+```
+
+#### `options`
+
+The options object can optionally be passed a second parameter. This object has two properties, `hf_token` and `status_callback`.
+
+##### `hf_token`
+
+This should be a Hugging Face personal access token and is required if you wish to make calls to a private gradio api. This option is optional and should be a string starting with `"hf_"`.
+
+Example:
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name", { hf_token: "hf_..." });
+```
+
+##### `status_callback`
+
+This should be a function which will notify your of the status of a space if it is not running. If the gradio API you are connecting to is awake and running or is not hosted on Hugging Face space then this function will do nothing.
+
+**Additional context**
+
+Applications hosted on Hugging Face spaces can be in a number of different states. As spaces are a GitOps tool and will rebuild when new changes are pushed to the repository, they have various building, running and error states. If a space is not 'running' then the function passed as the `status_callback` will notify you of the current state of the space and the status of the space as it changes. Spaces that are building or sleeping can take longer than usual to respond, so you can use this information to give users feedback about the progress of their action.
+
+```ts
+import { client, type SpaceStatus } from "@gradio/client";
+
+const app = await client("user/space-name", {
+ // The space_status parameter does not need to be manually annotated, this is just for illustration.
+ space_status: (space_status: SpaceStatus) => console.log(space_status)
+});
+```
+
+```ts
+interface SpaceStatusNormal {
+ status: "sleeping" | "running" | "building" | "error" | "stopped";
+ detail:
+ | "SLEEPING"
+ | "RUNNING"
+ | "RUNNING_BUILDING"
+ | "BUILDING"
+ | "NOT_FOUND";
+ load_status: "pending" | "error" | "complete" | "generating";
+ message: string;
+}
+
+interface SpaceStatusError {
+ status: "space_error";
+ detail: "NO_APP_FILE" | "CONFIG_ERROR" | "BUILD_ERROR" | "RUNTIME_ERROR";
+ load_status: "error";
+ message: string;
+ discussions_enabled: boolean;
+
+type SpaceStatus = SpaceStatusNormal | SpaceStatusError;
+```
+
+The gradio client returns an object with a number of methods and properties:
+
+#### `predict`
+
+The `predict` method allows you to call an api endpoint and get a prediction result:
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const result = await app.predict("/predict");
+```
+
+`predict` accepts two parameters, `endpoint` and `payload`. It returns a promise that resolves to the prediction result.
+
+##### `endpoint`
+
+This is the endpoint for an api request and is required. The default endpoint for a `gradio.Interface` is `"/predict"`. Explicitly named endpoints have a custom name. The endpoint names can be found on the "View API" page of a space.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const result = await app.predict("/predict");
+```
+
+##### `payload`
+
+The `payload` argument is generally optional but this depends on the API itself. If the API endpoint depends on values being passed in then it is required for the API request to succeed. The data that should be passed in is detailed on the "View API" page of a space, or accessible via the `view_api()` method of the client.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const result = await app.predict("/predict", [1, "Hello", "friends"]);
+```
+
+#### `submit`
+
+The `submit` method provides a more flexible way to call an API endpoint, providing you with status updates about the current progress of the prediction as well as supporting more complex endpoint types.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const submission = app.submit("/predict", payload);
+```
+
+The `submit` method accepts the same [`endpoint`](#endpoint) and [`payload`](#payload) arguments as `predict`.
+
+The `submit` method does not return a promise and should not be awaited, instead it returns an object with a `on`, `off`, and `cancel` methods.
+
+##### `on`
+
+The `on` method allows you to subscribe to events related to the submitted API request. There are two types of event that can be subscribed to: `"data"` updates and `"status"` updates.
+
+`"data"` updates are issued when the API computes a value, the callback provided as the second argument will be called when such a value is sent to the client. The shape of the data depends on the way the API itself is constructed. This event may fire more than once if that endpoint supports emmitting new values over time.
+
+`"status` updates are issued when the status of a request changes. This information allows you to offer feedback to users when the queue position of the request changes, or when the request changes from queued to processing.
+
+The status payload look like this:
+
+```ts
+interface Status {
+ queue: boolean;
+ code?: string;
+ success?: boolean;
+ stage: "pending" | "error" | "complete" | "generating";
+ size?: number;
+ position?: number;
+ eta?: number;
+ message?: string;
+ progress_data?: Array<{
+ progress: number | null;
+ index: number | null;
+ length: number | null;
+ unit: string | null;
+ desc: string | null;
+ }>;
+ time?: Date;
+}
+```
+
+Usage of these subscribe callback looks like this:
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const submission = app
+ .submit("/predict", payload)
+ .on("data", (data) => console.log(data))
+ .on("status", (status: Status) => console.log(status));
+```
+
+##### `off`
+
+The `off` method unsubscribes from a specific event of the submitted job and works similarly to `document.removeEventListener`; both the event name and the original callback must be passed in to successfully unsubscribe:
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const handle_data = (data) => console.log(data);
+
+const submission = app.submit("/predict", payload).on("data", handle_data);
+
+// later
+submission.off("/predict", handle_data);
+```
+
+##### `destroy`
+
+The `destroy` method will remove all subscriptions to a job, regardless of whether or not they are `"data"` or `"status"` events. This is a convenience method for when you do not want to unsubscribe use the `off` method.
+
+```js
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const handle_data = (data) => console.log(data);
+
+const submission = app.submit("/predict", payload).on("data", handle_data);
+
+// later
+submission.destroy();
+```
+
+##### `cancel`
+
+Certain types of gradio function can run repeatedly and in some cases indefinitely. the `cancel` method will stop such an endpoints and prevent the API from issuing additional updates.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const submission = app
+ .submit("/predict", payload)
+ .on("data", (data) => console.log(data));
+
+// later
+
+submission.cancel();
+```
+
+#### `view_api`
+
+The `view_api` method provides details about the API you are connected to. It returns a JavaScript object of all named endpoints, unnamed endpoints and what values they accept and return. This method does not accept arguments.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+const api_info = await app.view_api();
+
+console.log(api_info);
+```
+
+#### `config`
+
+The `config` property contains the configuration for the gradio application you are connected to. This object may contain useful meta information about the application.
+
+```ts
+import { client } from "@gradio/client";
+
+const app = await client("user/space-name");
+console.log(app.config);
+```
+
+### `duplicate`
+
+The duplicate function will attempt to duplicate the space that is referenced and return an instance of `client` connected to that space. If the space has already been duplicated then it will not create a new duplicate and will instead connect to the existing duplicated space. The huggingface token that is passed in will dictate the user under which the space is created.
+
+`duplicate` accepts the same arguments as `client` with the addition of a `private` options property dictating whether the duplicated space should be private or public. A huggingface token is required for duplication to work.
+
+```ts
+import { duplicate } from "@gradio/client";
+
+const app = await duplicate("user/space-name", {
+ hf_token: "hf_..."
+});
+```
+
+This function accepts two arguments: `source` and `options`:
+
+#### `source`
+
+The space to duplicate and connect to. [See `client`'s `source` parameter](#source).
+
+#### `options`
+
+Accepts all options that `client` accepts, except `hf_token` is required. [See `client`'s `options` parameter](#source).
+
+`duplicate` also accepts one additional `options` property.
+
+##### `private`
+
+This is an optional property specific to `duplicate`'s options object and will determine whether the space should be public or private. Spaces duplicated via the `duplicate` method are public by default.
+
+```ts
+import { duplicate } from "@gradio/client";
+
+const app = await duplicate("user/space-name", {
+ hf_token: "hf_...",
+ private: true
+});
+```
+
+##### `timeout`
+
+This is an optional property specific to `duplicate`'s options object and will set the timeout in minutes before the duplicated space will go to sleep.
+
+```ts
+import { duplicate } from "@gradio/client";
+
+const app = await duplicate("user/space-name", {
+ hf_token: "hf_...",
+ private: true,
+ timeout: 5
+});
+```
+
+##### `hardware`
+
+This is an optional property specific to `duplicate`'s options object and will set the hardware for the duplicated space. By default the hardware used will match that of the original space. If this cannot be obtained it will default to `"cpu-basic"`. For hardware upgrades (beyond the basic CPU tier), you may be required to provide [billing information on Hugging Face](https://huggingface.co/settings/billing).
+
+Possible hardware options are:
+
+- `"cpu-basic"`
+- `"cpu-upgrade"`
+- `"t4-small"`
+- `"t4-medium"`
+- `"a10g-small"`
+- `"a10g-large"`
+- `"a100-large"`
+
+```ts
+import { duplicate } from "@gradio/client";
+
+const app = await duplicate("user/space-name", {
+ hf_token: "hf_...",
+ private: true,
+ hardware: "a10g-small"
+});
+```
diff --git a/client/js/package.json b/client/js/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..3601d4723800c92c9e50a172d6032e956690e287
--- /dev/null
+++ b/client/js/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "@gradio/client",
+ "version": "0.10.1",
+ "description": "Gradio API client",
+ "type": "module",
+ "main": "dist/index.js",
+ "author": "",
+ "license": "ISC",
+ "exports": {
+ ".": {
+ "import": "./dist/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "dependencies": {
+ "bufferutil": "^4.0.7",
+ "semiver": "^1.1.0",
+ "ws": "^8.13.0"
+ },
+ "devDependencies": {
+ "@types/ws": "^8.5.4",
+ "esbuild": "^0.19.0"
+ },
+ "scripts": {
+ "bundle": "vite build --ssr",
+ "generate_types": "tsc",
+ "build": "pnpm bundle && pnpm generate_types"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "main_changeset": true
+}
diff --git a/client/js/src/client.node-test.ts b/client/js/src/client.node-test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9964583b4558d55a62b0fbf78a440e572e5a204f
--- /dev/null
+++ b/client/js/src/client.node-test.ts
@@ -0,0 +1,172 @@
+import { test, describe, assert } from "vitest";
+import { readFileSync } from "fs";
+import { join, dirname } from "path";
+import { fileURLToPath } from "url";
+import { Blob } from "node:buffer";
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const image_path = join(
+ __dirname,
+ "..",
+ "..",
+ "..",
+ "demo",
+ "kitchen_sink",
+ "files",
+ "lion.jpg"
+);
+
+import { walk_and_store_blobs, client, handle_blob } from "./client";
+
+describe.skip("extract blob parts", () => {
+ test("convert Buffer to Blob", async () => {
+ const image = readFileSync(image_path);
+ await client("gradio/hello_world_main");
+ const parts = walk_and_store_blobs({
+ data: {
+ image
+ }
+ });
+
+ assert.isTrue(parts[0].blob instanceof Blob);
+ });
+
+ test("leave node Blob as Blob", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ await client("gradio/hello_world_main");
+ const parts = walk_and_store_blobs({
+ data: {
+ image
+ }
+ });
+
+ assert.isTrue(parts[0].blob instanceof Blob);
+ });
+
+ test("handle deep structures", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ await client("gradio/hello_world_main");
+ const parts = walk_and_store_blobs({
+ a: {
+ b: {
+ data: {
+ image
+ }
+ }
+ }
+ });
+
+ assert.isTrue(parts[0].blob instanceof Blob);
+ });
+
+ test("handle deep structures with arrays", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ await client("gradio/hello_world_main");
+ const parts = walk_and_store_blobs({
+ a: [
+ {
+ b: [
+ {
+ data: [
+ {
+ image
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ });
+
+ assert.isTrue(parts[0].blob instanceof Blob);
+ });
+
+ test("handle deep structures with arrays 2", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ await client("gradio/hello_world_main");
+ const obj = {
+ a: [
+ {
+ b: [
+ {
+ data: [[image], image, [image, [image]]]
+ }
+ ]
+ }
+ ]
+ };
+ const parts = walk_and_store_blobs(obj);
+
+ function map_path(
+ obj: Record,
+ parts: { path: string[]; blob: any }[]
+ ) {
+ const { path, blob } = parts[parts.length - 1];
+ let ref = obj;
+ path.forEach((p) => (ref = ref[p]));
+
+ return ref === blob;
+ }
+
+ assert.isTrue(parts[0].blob instanceof Blob);
+ // assert.isTrue(map_path(obj, parts));
+ });
+});
+
+describe("handle_blob", () => {
+ test("handle blobs", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ const app = await client("gradio/hello_world_main");
+ const obj = [
+ {
+ a: [
+ {
+ b: [
+ {
+ data: [[image], image, [image, [image]]]
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ const parts = await handle_blob(app.config.root, obj, undefined);
+ //@ts-ignore
+ // assert.isString(parts.data[0].a[0].b[0].data[0][0]);
+ });
+});
+
+describe.skip("private space", () => {
+ test("can access a private space", async () => {
+ const image = new Blob([readFileSync(image_path)]);
+
+ const app = await client("pngwn/hello_world", {
+ hf_token: "hf_"
+ });
+
+ console.log(app);
+ const obj = [
+ {
+ a: [
+ {
+ b: [
+ {
+ data: [[image], image, [image, [image]]]
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ const parts = await handle_blob(app.config.root, obj, "hf_");
+ //@ts-ignore
+ assert.isString(parts.data[0].a[0].b[0].data[0][0]);
+ });
+});
diff --git a/client/js/src/client.ts b/client/js/src/client.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6355d5a04cadee5dcb057a73eefd2b7e0eeabbf5
--- /dev/null
+++ b/client/js/src/client.ts
@@ -0,0 +1,1727 @@
+//@ts-nocheck
+
+import semiver from "semiver";
+
+import {
+ process_endpoint,
+ RE_SPACE_NAME,
+ map_names_to_ids,
+ discussions_enabled,
+ get_space_hardware,
+ set_space_hardware,
+ set_space_timeout,
+ hardware_types,
+ resolve_root
+} from "./utils.js";
+
+import type {
+ EventType,
+ EventListener,
+ ListenerMap,
+ Event,
+ Payload,
+ PostResponse,
+ UploadResponse,
+ Status,
+ SpaceStatus,
+ SpaceStatusCallback
+} from "./types.js";
+
+import { FileData, normalise_file } from "./upload";
+
+import type { Config } from "./types.js";
+
+type event = (
+ eventType: K,
+ listener: EventListener
+) => SubmitReturn;
+type predict = (
+ endpoint: string | number,
+ data?: unknown[],
+ event_data?: unknown
+) => Promise;
+
+type client_return = {
+ predict: predict;
+ config: Config;
+ submit: (
+ endpoint: string | number,
+ data?: unknown[],
+ event_data?: unknown,
+ trigger_id?: number | null
+ ) => SubmitReturn;
+ component_server: (
+ component_id: number,
+ fn_name: string,
+ data: unknown[]
+ ) => any;
+ view_api: (c?: Config) => Promise>;
+};
+
+type SubmitReturn = {
+ on: event;
+ off: event;
+ cancel: () => Promise;
+ destroy: () => void;
+};
+
+const QUEUE_FULL_MSG = "This application is too busy. Keep trying!";
+const BROKEN_CONNECTION_MSG = "Connection errored out.";
+
+export let NodeBlob;
+
+export async function duplicate(
+ app_reference: string,
+ options: {
+ hf_token: `hf_${string}`;
+ private?: boolean;
+ status_callback: SpaceStatusCallback;
+ hardware?: (typeof hardware_types)[number];
+ timeout?: number;
+ }
+): Promise {
+ const { hf_token, private: _private, hardware, timeout } = options;
+
+ if (hardware && !hardware_types.includes(hardware)) {
+ throw new Error(
+ `Invalid hardware type provided. Valid types are: ${hardware_types
+ .map((v) => `"${v}"`)
+ .join(",")}.`
+ );
+ }
+ const headers = {
+ Authorization: `Bearer ${hf_token}`
+ };
+
+ const user = (
+ await (
+ await fetch(`https://huggingface.co/api/whoami-v2`, {
+ headers
+ })
+ ).json()
+ ).name;
+
+ const space_name = app_reference.split("/")[1];
+ const body: {
+ repository: string;
+ private?: boolean;
+ } = {
+ repository: `${user}/${space_name}`
+ };
+
+ if (_private) {
+ body.private = true;
+ }
+
+ try {
+ const response = await fetch(
+ `https://huggingface.co/api/spaces/${app_reference}/duplicate`,
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json", ...headers },
+ body: JSON.stringify(body)
+ }
+ );
+
+ if (response.status === 409) {
+ return client(`${user}/${space_name}`, options);
+ }
+ const duplicated_space = await response.json();
+
+ let original_hardware;
+
+ if (!hardware) {
+ original_hardware = await get_space_hardware(app_reference, hf_token);
+ }
+
+ const requested_hardware = hardware || original_hardware || "cpu-basic";
+ await set_space_hardware(
+ `${user}/${space_name}`,
+ requested_hardware,
+ hf_token
+ );
+
+ await set_space_timeout(`${user}/${space_name}`, timeout || 300, hf_token);
+ return client(duplicated_space.url, options);
+ } catch (e: any) {
+ throw new Error(e);
+ }
+}
+
+interface Client {
+ post_data: (
+ url: string,
+ body: unknown,
+ token?: `hf_${string}`
+ ) => Promise<[PostResponse, number]>;
+ upload_files: (
+ root: string,
+ files: File[],
+ token?: `hf_${string}`,
+ upload_id?: string
+ ) => Promise;
+ client: (
+ app_reference: string,
+ options: {
+ hf_token?: `hf_${string}`;
+ status_callback?: SpaceStatusCallback;
+ normalise_files?: boolean;
+ }
+ ) => Promise;
+ handle_blob: (
+ endpoint: string,
+ data: unknown[],
+ api_info: ApiInfo,
+ token?: `hf_${string}`
+ ) => Promise;
+}
+
+export function api_factory(
+ fetch_implementation: typeof fetch,
+ EventSource_factory: (url: URL) => EventSource
+): Client {
+ return { post_data, upload_files, client, handle_blob };
+
+ async function post_data(
+ url: string,
+ body: unknown,
+ token?: `hf_${string}`
+ ): Promise<[PostResponse, number]> {
+ const headers: {
+ Authorization?: string;
+ "Content-Type": "application/json";
+ } = { "Content-Type": "application/json" };
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+ try {
+ var response = await fetch_implementation(url, {
+ method: "POST",
+ body: JSON.stringify(body),
+ headers
+ });
+ } catch (e) {
+ return [{ error: BROKEN_CONNECTION_MSG }, 500];
+ }
+ let output: PostResponse;
+ let status: int;
+ try {
+ output = await response.json();
+ status = response.status;
+ } catch (e) {
+ output = { error: `Could not parse server response: ${e}` };
+ status = 500;
+ }
+ return [output, status];
+ }
+
+ async function upload_files(
+ root: string,
+ files: (Blob | File)[],
+ token?: `hf_${string}`,
+ upload_id?: string
+ ): Promise {
+ const headers: {
+ Authorization?: string;
+ } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+ const chunkSize = 1000;
+ const uploadResponses = [];
+ for (let i = 0; i < files.length; i += chunkSize) {
+ const chunk = files.slice(i, i + chunkSize);
+ const formData = new FormData();
+ chunk.forEach((file) => {
+ formData.append("files", file);
+ });
+ try {
+ const upload_url = upload_id
+ ? `${root}/upload?upload_id=${upload_id}`
+ : `${root}/upload`;
+ var response = await fetch_implementation(upload_url, {
+ method: "POST",
+ body: formData,
+ headers
+ });
+ } catch (e) {
+ return { error: BROKEN_CONNECTION_MSG };
+ }
+ const output: UploadResponse["files"] = await response.json();
+ uploadResponses.push(...output);
+ }
+ return { files: uploadResponses };
+ }
+
+ async function client(
+ app_reference: string,
+ options: {
+ hf_token?: `hf_${string}`;
+ status_callback?: SpaceStatusCallback;
+ normalise_files?: boolean;
+ } = { normalise_files: true }
+ ): Promise {
+ return new Promise(async (res) => {
+ const { status_callback, hf_token, normalise_files } = options;
+ const return_obj = {
+ predict,
+ submit,
+ view_api,
+ component_server
+ };
+
+ const transform_files = normalise_files ?? true;
+ if (
+ (typeof window === "undefined" || !("WebSocket" in window)) &&
+ !global.Websocket
+ ) {
+ const ws = await import("ws");
+ NodeBlob = (await import("node:buffer")).Blob;
+ //@ts-ignore
+ global.WebSocket = ws.WebSocket;
+ }
+
+ const { ws_protocol, http_protocol, host, space_id } =
+ await process_endpoint(app_reference, hf_token);
+
+ const session_hash = Math.random().toString(36).substring(2);
+ const last_status: Record = {};
+ let stream_open = false;
+ let pending_stream_messages: Record = {}; // Event messages may be received by the SSE stream before the initial data POST request is complete. To resolve this race condition, we store the messages in a dictionary and process them when the POST request is complete.
+ let event_stream: EventSource | null = null;
+ const event_callbacks: Record Promise> = {};
+ const unclosed_events: Set = new Set();
+ let config: Config;
+ let api_map: Record = {};
+
+ let jwt: false | string = false;
+
+ if (hf_token && space_id) {
+ jwt = await get_jwt(space_id, hf_token);
+ }
+
+ async function config_success(_config: Config): Promise {
+ config = _config;
+ api_map = map_names_to_ids(_config?.dependencies || []);
+ if (config.auth_required) {
+ return {
+ config,
+ ...return_obj
+ };
+ }
+ try {
+ api = await view_api(config);
+ } catch (e) {
+ console.error(`Could not get api details: ${e.message}`);
+ }
+
+ return {
+ config,
+ ...return_obj
+ };
+ }
+ let api: ApiInfo;
+ async function handle_space_sucess(status: SpaceStatus): Promise {
+ if (status_callback) status_callback(status);
+ if (status.status === "running")
+ try {
+ config = await resolve_config(
+ fetch_implementation,
+ `${http_protocol}//${host}`,
+ hf_token
+ );
+
+ const _config = await config_success(config);
+ res(_config);
+ } catch (e) {
+ console.error(e);
+ if (status_callback) {
+ status_callback({
+ status: "error",
+ message: "Could not load this space.",
+ load_status: "error",
+ detail: "NOT_FOUND"
+ });
+ }
+ }
+ }
+
+ try {
+ config = await resolve_config(
+ fetch_implementation,
+ `${http_protocol}//${host}`,
+ hf_token
+ );
+
+ const _config = await config_success(config);
+ res(_config);
+ } catch (e) {
+ console.error(e);
+ if (space_id) {
+ check_space_status(
+ space_id,
+ RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
+ handle_space_sucess
+ );
+ } else {
+ if (status_callback)
+ status_callback({
+ status: "error",
+ message: "Could not load this space.",
+ load_status: "error",
+ detail: "NOT_FOUND"
+ });
+ }
+ }
+
+ function predict(
+ endpoint: string,
+ data: unknown[],
+ event_data?: unknown
+ ): Promise {
+ let data_returned = false;
+ let status_complete = false;
+ let dependency;
+ if (typeof endpoint === "number") {
+ dependency = config.dependencies[endpoint];
+ } else {
+ const trimmed_endpoint = endpoint.replace(/^\//, "");
+ dependency = config.dependencies[api_map[trimmed_endpoint]];
+ }
+
+ if (dependency.types.continuous) {
+ throw new Error(
+ "Cannot call predict on this function as it may run forever. Use submit instead"
+ );
+ }
+
+ return new Promise((res, rej) => {
+ const app = submit(endpoint, data, event_data);
+ let result;
+
+ app
+ .on("data", (d) => {
+ // if complete message comes before data, resolve here
+ if (status_complete) {
+ app.destroy();
+ res(d);
+ }
+ data_returned = true;
+ result = d;
+ })
+ .on("status", (status) => {
+ if (status.stage === "error") rej(status);
+ if (status.stage === "complete") {
+ status_complete = true;
+ // if complete message comes after data, resolve here
+ if (data_returned) {
+ app.destroy();
+ res(result);
+ }
+ }
+ });
+ });
+ }
+
+ function submit(
+ endpoint: string | number,
+ data: unknown[],
+ event_data?: unknown,
+ trigger_id: number | null = null
+ ): SubmitReturn {
+ let fn_index: number;
+ let api_info;
+
+ if (typeof endpoint === "number") {
+ fn_index = endpoint;
+ api_info = api.unnamed_endpoints[fn_index];
+ } else {
+ const trimmed_endpoint = endpoint.replace(/^\//, "");
+
+ fn_index = api_map[trimmed_endpoint];
+ api_info = api.named_endpoints[endpoint.trim()];
+ }
+
+ if (typeof fn_index !== "number") {
+ throw new Error(
+ "There is no endpoint matching that name of fn_index matching that number."
+ );
+ }
+
+ let websocket: WebSocket;
+ let eventSource: EventSource;
+ let protocol = config.protocol ?? "ws";
+
+ const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
+ let payload: Payload;
+ let event_id: string | null = null;
+ let complete: false | Record = false;
+ const listener_map: ListenerMap = {};
+ let url_params = "";
+ if (typeof window !== "undefined") {
+ url_params = new URLSearchParams(window.location.search).toString();
+ }
+
+ handle_blob(`${config.root}`, data, api_info, hf_token).then(
+ (_payload) => {
+ payload = {
+ data: _payload || [],
+ event_data,
+ fn_index,
+ trigger_id
+ };
+ if (skip_queue(fn_index, config)) {
+ fire_event({
+ type: "status",
+ endpoint: _endpoint,
+ stage: "pending",
+ queue: false,
+ fn_index,
+ time: new Date()
+ });
+
+ post_data(
+ `${config.root}/run${
+ _endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`
+ }${url_params ? "?" + url_params : ""}`,
+ {
+ ...payload,
+ session_hash
+ },
+ hf_token
+ )
+ .then(([output, status_code]) => {
+ const data = transform_files
+ ? transform_output(
+ output.data,
+ api_info,
+ config.root,
+ config.root_url
+ )
+ : output.data;
+ if (status_code == 200) {
+ fire_event({
+ type: "data",
+ endpoint: _endpoint,
+ fn_index,
+ data: data,
+ time: new Date()
+ });
+
+ fire_event({
+ type: "status",
+ endpoint: _endpoint,
+ fn_index,
+ stage: "complete",
+ eta: output.average_duration,
+ queue: false,
+ time: new Date()
+ });
+ } else {
+ fire_event({
+ type: "status",
+ stage: "error",
+ endpoint: _endpoint,
+ fn_index,
+ message: output.error,
+ queue: false,
+ time: new Date()
+ });
+ }
+ })
+ .catch((e) => {
+ fire_event({
+ type: "status",
+ stage: "error",
+ message: e.message,
+ endpoint: _endpoint,
+ fn_index,
+ queue: false,
+ time: new Date()
+ });
+ });
+ } else if (protocol == "ws") {
+ fire_event({
+ type: "status",
+ stage: "pending",
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ let url = new URL(`${ws_protocol}://${resolve_root(
+ host,
+ config.path,
+ true
+ )}
+ /queue/join${url_params ? "?" + url_params : ""}`);
+
+ if (jwt) {
+ url.searchParams.set("__sign", jwt);
+ }
+
+ websocket = new WebSocket(url);
+
+ websocket.onclose = (evt) => {
+ if (!evt.wasClean) {
+ fire_event({
+ type: "status",
+ stage: "error",
+ broken: true,
+ message: BROKEN_CONNECTION_MSG,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ }
+ };
+
+ websocket.onmessage = function (event) {
+ const _data = JSON.parse(event.data);
+ const { type, status, data } = handle_message(
+ _data,
+ last_status[fn_index]
+ );
+
+ if (type === "update" && status && !complete) {
+ // call 'status' listeners
+ fire_event({
+ type: "status",
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date(),
+ ...status
+ });
+ if (status.stage === "error") {
+ websocket.close();
+ }
+ } else if (type === "hash") {
+ websocket.send(JSON.stringify({ fn_index, session_hash }));
+ return;
+ } else if (type === "data") {
+ websocket.send(JSON.stringify({ ...payload, session_hash }));
+ } else if (type === "complete") {
+ complete = status;
+ } else if (type === "log") {
+ fire_event({
+ type: "log",
+ log: data.log,
+ level: data.level,
+ endpoint: _endpoint,
+ fn_index
+ });
+ } else if (type === "generating") {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...status,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ }
+ if (data) {
+ fire_event({
+ type: "data",
+ time: new Date(),
+ data: transform_files
+ ? transform_output(
+ data.data,
+ api_info,
+ config.root,
+ config.root_url
+ )
+ : data.data,
+ endpoint: _endpoint,
+ fn_index
+ });
+
+ if (complete) {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...complete,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ websocket.close();
+ }
+ }
+ };
+
+ // different ws contract for gradio versions older than 3.6.0
+ //@ts-ignore
+ if (semiver(config.version || "2.0.0", "3.6") < 0) {
+ addEventListener("open", () =>
+ websocket.send(JSON.stringify({ hash: session_hash }))
+ );
+ }
+ } else if (protocol == "sse") {
+ fire_event({
+ type: "status",
+ stage: "pending",
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ var params = new URLSearchParams({
+ fn_index: fn_index.toString(),
+ session_hash: session_hash
+ }).toString();
+ let url = new URL(
+ `${config.root}/queue/join?${
+ url_params ? url_params + "&" : ""
+ }${params}`
+ );
+
+ eventSource = EventSource_factory(url);
+
+ eventSource.onmessage = async function (event) {
+ const _data = JSON.parse(event.data);
+ const { type, status, data } = handle_message(
+ _data,
+ last_status[fn_index]
+ );
+
+ if (type === "update" && status && !complete) {
+ // call 'status' listeners
+ fire_event({
+ type: "status",
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date(),
+ ...status
+ });
+ if (status.stage === "error") {
+ eventSource.close();
+ }
+ } else if (type === "data") {
+ event_id = _data.event_id as string;
+ let [_, status] = await post_data(
+ `${config.root}/queue/data`,
+ {
+ ...payload,
+ session_hash,
+ event_id
+ },
+ hf_token
+ );
+ if (status !== 200) {
+ fire_event({
+ type: "status",
+ stage: "error",
+ message: BROKEN_CONNECTION_MSG,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ eventSource.close();
+ }
+ } else if (type === "complete") {
+ complete = status;
+ } else if (type === "log") {
+ fire_event({
+ type: "log",
+ log: data.log,
+ level: data.level,
+ endpoint: _endpoint,
+ fn_index
+ });
+ } else if (type === "generating") {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...status,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ }
+ if (data) {
+ fire_event({
+ type: "data",
+ time: new Date(),
+ data: transform_files
+ ? transform_output(
+ data.data,
+ api_info,
+ config.root,
+ config.root_url
+ )
+ : data.data,
+ endpoint: _endpoint,
+ fn_index
+ });
+
+ if (complete) {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...complete,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ eventSource.close();
+ }
+ }
+ };
+ } else if (protocol == "sse_v1") {
+ fire_event({
+ type: "status",
+ stage: "pending",
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+
+ post_data(
+ `${config.root}/queue/join?${url_params}`,
+ {
+ ...payload,
+ session_hash
+ },
+ hf_token
+ ).then(([response, status]) => {
+ if (status === 503) {
+ fire_event({
+ type: "status",
+ stage: "error",
+ message: QUEUE_FULL_MSG,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ } else if (status !== 200) {
+ fire_event({
+ type: "status",
+ stage: "error",
+ message: BROKEN_CONNECTION_MSG,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ } else {
+ event_id = response.event_id as string;
+ let callback = async function (_data: object): void {
+ try {
+ const { type, status, data } = handle_message(
+ _data,
+ last_status[fn_index]
+ );
+
+ if (type == "heartbeat") {
+ return;
+ }
+
+ if (type === "update" && status && !complete) {
+ // call 'status' listeners
+ fire_event({
+ type: "status",
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date(),
+ ...status
+ });
+ } else if (type === "complete") {
+ complete = status;
+ } else if (type == "unexpected_error") {
+ console.error("Unexpected error", status?.message);
+ fire_event({
+ type: "status",
+ stage: "error",
+ message:
+ status?.message || "An Unexpected Error Occurred!",
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ } else if (type === "log") {
+ fire_event({
+ type: "log",
+ log: data.log,
+ level: data.level,
+ endpoint: _endpoint,
+ fn_index
+ });
+ return;
+ } else if (type === "generating") {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...status,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ }
+ if (data) {
+ fire_event({
+ type: "data",
+ time: new Date(),
+ data: transform_files
+ ? transform_output(
+ data.data,
+ api_info,
+ config.root,
+ config.root_url
+ )
+ : data.data,
+ endpoint: _endpoint,
+ fn_index
+ });
+
+ if (complete) {
+ fire_event({
+ type: "status",
+ time: new Date(),
+ ...complete,
+ stage: status?.stage!,
+ queue: true,
+ endpoint: _endpoint,
+ fn_index
+ });
+ }
+ }
+
+ if (
+ status?.stage === "complete" ||
+ status?.stage === "error"
+ ) {
+ if (event_callbacks[event_id]) {
+ delete event_callbacks[event_id];
+ }
+ }
+ } catch (e) {
+ console.error("Unexpected client exception", e);
+ fire_event({
+ type: "status",
+ stage: "error",
+ message: "An Unexpected Error Occurred!",
+ queue: true,
+ endpoint: _endpoint,
+ fn_index,
+ time: new Date()
+ });
+ close_stream();
+ }
+ };
+ if (event_id in pending_stream_messages) {
+ pending_stream_messages[event_id].forEach((msg) =>
+ callback(msg)
+ );
+ delete pending_stream_messages[event_id];
+ }
+ event_callbacks[event_id] = callback;
+ unclosed_events.add(event_id);
+ if (!stream_open) {
+ open_stream();
+ }
+ }
+ });
+ }
+ }
+ );
+
+ function fire_event(event: Event): void {
+ const narrowed_listener_map: ListenerMap = listener_map;
+ const listeners = narrowed_listener_map[event.type] || [];
+ listeners?.forEach((l) => l(event));
+ }
+
+ function on(
+ eventType: K,
+ listener: EventListener
+ ): SubmitReturn {
+ const narrowed_listener_map: ListenerMap = listener_map;
+ const listeners = narrowed_listener_map[eventType] || [];
+ narrowed_listener_map[eventType] = listeners;
+ listeners?.push(listener);
+
+ return { on, off, cancel, destroy };
+ }
+
+ function off(
+ eventType: K,
+ listener: EventListener
+ ): SubmitReturn {
+ const narrowed_listener_map: ListenerMap = listener_map;
+ let listeners = narrowed_listener_map[eventType] || [];
+ listeners = listeners?.filter((l) => l !== listener);
+ narrowed_listener_map[eventType] = listeners;
+
+ return { on, off, cancel, destroy };
+ }
+
+ async function cancel(): Promise {
+ const _status: Status = {
+ stage: "complete",
+ queue: false,
+ time: new Date()
+ };
+ complete = _status;
+ fire_event({
+ ..._status,
+ type: "status",
+ endpoint: _endpoint,
+ fn_index: fn_index
+ });
+
+ let cancel_request = {};
+ if (protocol === "ws") {
+ if (websocket && websocket.readyState === 0) {
+ websocket.addEventListener("open", () => {
+ websocket.close();
+ });
+ } else {
+ websocket.close();
+ }
+ cancel_request = { fn_index, session_hash };
+ } else {
+ eventSource.close();
+ cancel_request = { event_id };
+ }
+
+ try {
+ await fetch_implementation(`${config.root}/reset`, {
+ headers: { "Content-Type": "application/json" },
+ method: "POST",
+ body: JSON.stringify(cancel_request)
+ });
+ } catch (e) {
+ console.warn(
+ "The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
+ );
+ }
+ }
+
+ function destroy(): void {
+ for (const event_type in listener_map) {
+ listener_map[event_type as "data" | "status"].forEach((fn) => {
+ off(event_type as "data" | "status", fn);
+ });
+ }
+ }
+
+ return {
+ on,
+ off,
+ cancel,
+ destroy
+ };
+ }
+
+ function open_stream(): void {
+ stream_open = true;
+ let params = new URLSearchParams({
+ session_hash: session_hash
+ }).toString();
+ let url = new URL(`${config.root}/queue/data?${params}`);
+ event_stream = EventSource_factory(url);
+ event_stream.onmessage = async function (event) {
+ let _data = JSON.parse(event.data);
+ const event_id = _data.event_id;
+ if (!event_id) {
+ await Promise.all(
+ Object.keys(event_callbacks).map((event_id) =>
+ event_callbacks[event_id](_data)
+ )
+ );
+ } else if (event_callbacks[event_id]) {
+ if (_data.msg === "process_completed") {
+ unclosed_events.delete(event_id);
+ if (unclosed_events.size === 0) {
+ close_stream();
+ }
+ }
+ let fn = event_callbacks[event_id];
+ window.setTimeout(fn, 0, _data); // need to do this to put the event on the end of the event loop, so the browser can refresh between callbacks and not freeze in case of quick generations. See https://github.com/gradio-app/gradio/pull/7055
+ } else {
+ if (!pending_stream_messages[event_id]) {
+ pending_stream_messages[event_id] = [];
+ }
+ pending_stream_messages[event_id].push(_data);
+ }
+ };
+ event_stream.onerror = async function (event) {
+ await Promise.all(
+ Object.keys(event_callbacks).map((event_id) =>
+ event_callbacks[event_id]({
+ msg: "unexpected_error",
+ message: BROKEN_CONNECTION_MSG
+ })
+ )
+ );
+ close_stream();
+ };
+ }
+
+ function close_stream(): void {
+ stream_open = false;
+ event_stream?.close();
+ }
+
+ async function component_server(
+ component_id: number,
+ fn_name: string,
+ data: unknown[]
+ ): Promise {
+ const headers: {
+ Authorization?: string;
+ "Content-Type": "application/json";
+ } = { "Content-Type": "application/json" };
+ if (hf_token) {
+ headers.Authorization = `Bearer ${hf_token}`;
+ }
+ let root_url: string;
+ let component = config.components.find(
+ (comp) => comp.id === component_id
+ );
+ if (component?.props?.root_url) {
+ root_url = component.props.root_url;
+ } else {
+ root_url = config.root;
+ }
+ const response = await fetch_implementation(
+ `${root_url}/component_server/`,
+ {
+ method: "POST",
+ body: JSON.stringify({
+ data: data,
+ component_id: component_id,
+ fn_name: fn_name,
+ session_hash: session_hash
+ }),
+ headers
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(
+ "Could not connect to component server: " + response.statusText
+ );
+ }
+
+ const output = await response.json();
+ return output;
+ }
+
+ async function view_api(config?: Config): Promise> {
+ if (api) return api;
+
+ const headers: {
+ Authorization?: string;
+ "Content-Type": "application/json";
+ } = { "Content-Type": "application/json" };
+ if (hf_token) {
+ headers.Authorization = `Bearer ${hf_token}`;
+ }
+ let response: Response;
+ // @ts-ignore
+ if (semiver(config.version || "2.0.0", "3.30") < 0) {
+ response = await fetch_implementation(
+ "https://gradio-space-api-fetcher-v2.hf.space/api",
+ {
+ method: "POST",
+ body: JSON.stringify({
+ serialize: false,
+ config: JSON.stringify(config)
+ }),
+ headers
+ }
+ );
+ } else {
+ response = await fetch_implementation(`${config.root}/info`, {
+ headers
+ });
+ }
+
+ if (!response.ok) {
+ throw new Error(BROKEN_CONNECTION_MSG);
+ }
+
+ let api_info = (await response.json()) as
+ | ApiInfo
+ | { api: ApiInfo };
+ if ("api" in api_info) {
+ api_info = api_info.api;
+ }
+
+ if (
+ api_info.named_endpoints["/predict"] &&
+ !api_info.unnamed_endpoints["0"]
+ ) {
+ api_info.unnamed_endpoints[0] = api_info.named_endpoints["/predict"];
+ }
+
+ const x = transform_api_info(api_info, config, api_map);
+ return x;
+ }
+ });
+ }
+
+ async function handle_blob(
+ endpoint: string,
+ data: unknown[],
+ api_info: ApiInfo,
+ token?: `hf_${string}`
+ ): Promise {
+ const blob_refs = await walk_and_store_blobs(
+ data,
+ undefined,
+ [],
+ true,
+ api_info
+ );
+
+ return Promise.all(
+ blob_refs.map(async ({ path, blob, type }) => {
+ if (blob) {
+ const file_url = (await upload_files(endpoint, [blob], token))
+ .files[0];
+ return { path, file_url, type, name: blob?.name };
+ }
+ return { path, type };
+ })
+ ).then((r) => {
+ r.forEach(({ path, file_url, type, name }) => {
+ if (type === "Gallery") {
+ update_object(data, file_url, path);
+ } else if (file_url) {
+ const file = new FileData({ path: file_url, orig_name: name });
+ update_object(data, file, path);
+ }
+ });
+
+ return data;
+ });
+ }
+}
+
+export const { post_data, upload_files, client, handle_blob } = api_factory(
+ fetch,
+ (...args) => new EventSource(...args)
+);
+
+function transform_output(
+ data: any[],
+ api_info: any,
+ root_url: string,
+ remote_url?: string
+): unknown[] {
+ return data.map((d, i) => {
+ if (api_info?.returns?.[i]?.component === "File") {
+ return normalise_file(d, root_url, remote_url);
+ } else if (api_info?.returns?.[i]?.component === "Gallery") {
+ return d.map((img) => {
+ return Array.isArray(img)
+ ? [normalise_file(img[0], root_url, remote_url), img[1]]
+ : [normalise_file(img, root_url, remote_url), null];
+ });
+ } else if (typeof d === "object" && d.path) {
+ return normalise_file(d, root_url, remote_url);
+ }
+ return d;
+ });
+}
+
+interface ApiData {
+ label: string;
+ type: {
+ type: any;
+ description: string;
+ };
+ component: string;
+ example_input?: any;
+}
+
+interface JsApiData {
+ label: string;
+ type: string;
+ component: string;
+ example_input: any;
+}
+
+interface EndpointInfo {
+ parameters: T[];
+ returns: T[];
+}
+interface ApiInfo {
+ named_endpoints: {
+ [key: string]: EndpointInfo;
+ };
+ unnamed_endpoints: {
+ [key: string]: EndpointInfo;
+ };
+}
+
+function get_type(
+ type: { [key: string]: any },
+ component: string,
+ serializer: string,
+ signature_type: "return" | "parameter"
+): string {
+ switch (type.type) {
+ case "string":
+ return "string";
+ case "boolean":
+ return "boolean";
+ case "number":
+ return "number";
+ }
+
+ if (
+ serializer === "JSONSerializable" ||
+ serializer === "StringSerializable"
+ ) {
+ return "any";
+ } else if (serializer === "ListStringSerializable") {
+ return "string[]";
+ } else if (component === "Image") {
+ return signature_type === "parameter" ? "Blob | File | Buffer" : "string";
+ } else if (serializer === "FileSerializable") {
+ if (type?.type === "array") {
+ return signature_type === "parameter"
+ ? "(Blob | File | Buffer)[]"
+ : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]`;
+ }
+ return signature_type === "parameter"
+ ? "Blob | File | Buffer"
+ : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
+ } else if (serializer === "GallerySerializable") {
+ return signature_type === "parameter"
+ ? "[(Blob | File | Buffer), (string | null)][]"
+ : `[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]`;
+ }
+}
+
+function get_description(
+ type: { type: any; description: string },
+ serializer: string
+): string {
+ if (serializer === "GallerySerializable") {
+ return "array of [file, label] tuples";
+ } else if (serializer === "ListStringSerializable") {
+ return "array of strings";
+ } else if (serializer === "FileSerializable") {
+ return "array of files or single file";
+ }
+ return type.description;
+}
+
+function transform_api_info(
+ api_info: ApiInfo,
+ config: Config,
+ api_map: Record
+): ApiInfo {
+ const new_data = {
+ named_endpoints: {},
+ unnamed_endpoints: {}
+ };
+ for (const key in api_info) {
+ const cat = api_info[key];
+
+ for (const endpoint in cat) {
+ const dep_index = config.dependencies[endpoint]
+ ? endpoint
+ : api_map[endpoint.replace("/", "")];
+
+ const info = cat[endpoint];
+ new_data[key][endpoint] = {};
+ new_data[key][endpoint].parameters = {};
+ new_data[key][endpoint].returns = {};
+ new_data[key][endpoint].type = config.dependencies[dep_index].types;
+ new_data[key][endpoint].parameters = info.parameters.map(
+ ({ label, component, type, serializer }) => ({
+ label,
+ component,
+ type: get_type(type, component, serializer, "parameter"),
+ description: get_description(type, serializer)
+ })
+ );
+
+ new_data[key][endpoint].returns = info.returns.map(
+ ({ label, component, type, serializer }) => ({
+ label,
+ component,
+ type: get_type(type, component, serializer, "return"),
+ description: get_description(type, serializer)
+ })
+ );
+ }
+ }
+
+ return new_data;
+}
+
+async function get_jwt(
+ space: string,
+ token: `hf_${string}`
+): Promise {
+ try {
+ const r = await fetch(`https://huggingface.co/api/spaces/${space}/jwt`, {
+ headers: {
+ Authorization: `Bearer ${token}`
+ }
+ });
+
+ const jwt = (await r.json()).token;
+
+ return jwt || false;
+ } catch (e) {
+ console.error(e);
+ return false;
+ }
+}
+
+function update_object(object, newValue, stack): void {
+ while (stack.length > 1) {
+ object = object[stack.shift()];
+ }
+
+ object[stack.shift()] = newValue;
+}
+
+export async function walk_and_store_blobs(
+ param,
+ type = undefined,
+ path = [],
+ root = false,
+ api_info = undefined
+): Promise<
+ {
+ path: string[];
+ type: string;
+ blob: Blob | false;
+ }[]
+> {
+ if (Array.isArray(param)) {
+ let blob_refs = [];
+
+ await Promise.all(
+ param.map(async (v, i) => {
+ let new_path = path.slice();
+ new_path.push(i);
+
+ const array_refs = await walk_and_store_blobs(
+ param[i],
+ root ? api_info?.parameters[i]?.component || undefined : type,
+ new_path,
+ false,
+ api_info
+ );
+
+ blob_refs = blob_refs.concat(array_refs);
+ })
+ );
+
+ return blob_refs;
+ } else if (globalThis.Buffer && param instanceof globalThis.Buffer) {
+ const is_image = type === "Image";
+ return [
+ {
+ path: path,
+ blob: is_image ? false : new NodeBlob([param]),
+ type
+ }
+ ];
+ } else if (typeof param === "object") {
+ let blob_refs = [];
+ for (let key in param) {
+ if (param.hasOwnProperty(key)) {
+ let new_path = path.slice();
+ new_path.push(key);
+ blob_refs = blob_refs.concat(
+ await walk_and_store_blobs(
+ param[key],
+ undefined,
+ new_path,
+ false,
+ api_info
+ )
+ );
+ }
+ }
+ return blob_refs;
+ }
+ return [];
+}
+
+function image_to_data_uri(blob: Blob): Promise {
+ return new Promise((resolve, _) => {
+ const reader = new FileReader();
+ reader.onloadend = () => resolve(reader.result);
+ reader.readAsDataURL(blob);
+ });
+}
+
+function skip_queue(id: number, config: Config): boolean {
+ return (
+ !(config?.dependencies?.[id]?.queue === null
+ ? config.enable_queue
+ : config?.dependencies?.[id]?.queue) || false
+ );
+}
+
+async function resolve_config(
+ fetch_implementation: typeof fetch,
+ endpoint?: string,
+ token?: `hf_${string}`
+): Promise {
+ const headers: { Authorization?: string } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+ if (
+ typeof window !== "undefined" &&
+ window.gradio_config &&
+ location.origin !== "http://localhost:9876" &&
+ !window.gradio_config.dev_mode
+ ) {
+ const path = window.gradio_config.root;
+ const config = window.gradio_config;
+ config.root = resolve_root(endpoint, config.root, false);
+ return { ...config, path: path };
+ } else if (endpoint) {
+ let response = await fetch_implementation(`${endpoint}/config`, {
+ headers
+ });
+
+ if (response.status === 200) {
+ const config = await response.json();
+ config.path = config.path ?? "";
+ config.root = endpoint;
+ return config;
+ }
+ throw new Error("Could not get config.");
+ }
+
+ throw new Error("No config or app endpoint found");
+}
+
+async function check_space_status(
+ id: string,
+ type: "subdomain" | "space_name",
+ status_callback: SpaceStatusCallback
+): Promise {
+ let endpoint =
+ type === "subdomain"
+ ? `https://huggingface.co/api/spaces/by-subdomain/${id}`
+ : `https://huggingface.co/api/spaces/${id}`;
+ let response;
+ let _status;
+ try {
+ response = await fetch(endpoint);
+ _status = response.status;
+ if (_status !== 200) {
+ throw new Error();
+ }
+ response = await response.json();
+ } catch (e) {
+ status_callback({
+ status: "error",
+ load_status: "error",
+ message: "Could not get space status",
+ detail: "NOT_FOUND"
+ });
+ return;
+ }
+
+ if (!response || _status !== 200) return;
+ const {
+ runtime: { stage },
+ id: space_name
+ } = response;
+
+ switch (stage) {
+ case "STOPPED":
+ case "SLEEPING":
+ status_callback({
+ status: "sleeping",
+ load_status: "pending",
+ message: "Space is asleep. Waking it up...",
+ detail: stage
+ });
+
+ setTimeout(() => {
+ check_space_status(id, type, status_callback);
+ }, 1000); // poll for status
+ break;
+ case "PAUSED":
+ status_callback({
+ status: "paused",
+ load_status: "error",
+ message:
+ "This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",
+ detail: stage,
+ discussions_enabled: await discussions_enabled(space_name)
+ });
+ break;
+ case "RUNNING":
+ case "RUNNING_BUILDING":
+ status_callback({
+ status: "running",
+ load_status: "complete",
+ message: "",
+ detail: stage
+ });
+ // load_config(source);
+ // launch
+ break;
+ case "BUILDING":
+ status_callback({
+ status: "building",
+ load_status: "pending",
+ message: "Space is building...",
+ detail: stage
+ });
+
+ setTimeout(() => {
+ check_space_status(id, type, status_callback);
+ }, 1000);
+ break;
+ default:
+ status_callback({
+ status: "space_error",
+ load_status: "error",
+ message: "This space is experiencing an issue.",
+ detail: stage,
+ discussions_enabled: await discussions_enabled(space_name)
+ });
+ break;
+ }
+}
+
+function handle_message(
+ data: any,
+ last_status: Status["stage"]
+): {
+ type: "hash" | "data" | "update" | "complete" | "generating" | "log" | "none";
+ data?: any;
+ status?: Status;
+} {
+ const queue = true;
+ switch (data.msg) {
+ case "send_data":
+ return { type: "data" };
+ case "send_hash":
+ return { type: "hash" };
+ case "queue_full":
+ return {
+ type: "update",
+ status: {
+ queue,
+ message: QUEUE_FULL_MSG,
+ stage: "error",
+ code: data.code,
+ success: data.success
+ }
+ };
+ case "heartbeat":
+ return {
+ type: "heartbeat"
+ };
+ case "unexpected_error":
+ return {
+ type: "unexpected_error",
+ status: {
+ queue,
+ message: data.message,
+ stage: "error",
+ success: false
+ }
+ };
+ case "estimation":
+ return {
+ type: "update",
+ status: {
+ queue,
+ stage: last_status || "pending",
+ code: data.code,
+ size: data.queue_size,
+ position: data.rank,
+ eta: data.rank_eta,
+ success: data.success
+ }
+ };
+ case "progress":
+ return {
+ type: "update",
+ status: {
+ queue,
+ stage: "pending",
+ code: data.code,
+ progress_data: data.progress_data,
+ success: data.success
+ }
+ };
+ case "log":
+ return { type: "log", data: data };
+ case "process_generating":
+ return {
+ type: "generating",
+ status: {
+ queue,
+ message: !data.success ? data.output.error : null,
+ stage: data.success ? "generating" : "error",
+ code: data.code,
+ progress_data: data.progress_data,
+ eta: data.average_duration
+ },
+ data: data.success ? data.output : null
+ };
+ case "process_completed":
+ if ("error" in data.output) {
+ return {
+ type: "update",
+ status: {
+ queue,
+ message: data.output.error as string,
+ stage: "error",
+ code: data.code,
+ success: data.success
+ }
+ };
+ }
+ return {
+ type: "complete",
+ status: {
+ queue,
+ message: !data.success ? data.output.error : undefined,
+ stage: data.success ? "complete" : "error",
+ code: data.code,
+ progress_data: data.progress_data
+ },
+ data: data.success ? data.output : null
+ };
+
+ case "process_starts":
+ return {
+ type: "update",
+ status: {
+ queue,
+ stage: "pending",
+ code: data.code,
+ size: data.rank,
+ position: 0,
+ success: data.success,
+ eta: data.eta
+ }
+ };
+ }
+
+ return { type: "none", status: { stage: "error", queue } };
+}
diff --git a/client/js/src/globals.d.ts b/client/js/src/globals.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..64966293360c00b9b6c18a347259650b92c93b91
--- /dev/null
+++ b/client/js/src/globals.d.ts
@@ -0,0 +1,29 @@
+declare global {
+ interface Window {
+ __gradio_mode__: "app" | "website";
+ gradio_config: Config;
+ __is_colab__: boolean;
+ __gradio_space__: string | null;
+ }
+}
+
+export interface Config {
+ auth_required: boolean | undefined;
+ auth_message: string;
+ components: any[];
+ css: string | null;
+ dependencies: any[];
+ dev_mode: boolean;
+ enable_queue: boolean;
+ layout: any;
+ mode: "blocks" | "interface";
+ root: string;
+ theme: string;
+ title: string;
+ version: string;
+ space_id: string | null;
+ is_colab: boolean;
+ show_api: boolean;
+ stylesheets: string[];
+ path: string;
+}
diff --git a/client/js/src/index.ts b/client/js/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98e248e54cc5d72d681ff6dda03db016af70f25f
--- /dev/null
+++ b/client/js/src/index.ts
@@ -0,0 +1,15 @@
+export {
+ client,
+ post_data,
+ upload_files,
+ duplicate,
+ api_factory
+} from "./client.js";
+export type { SpaceStatus } from "./types.js";
+export {
+ normalise_file,
+ FileData,
+ upload,
+ get_fetchable_url_or_file,
+ prepare_files
+} from "./upload.js";
diff --git a/client/js/src/types.ts b/client/js/src/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2b1869855ef0a7d40d9fcda86bfc98197e733478
--- /dev/null
+++ b/client/js/src/types.ts
@@ -0,0 +1,119 @@
+export interface Config {
+ auth_required: boolean | undefined;
+ auth_message: string;
+ components: any[];
+ css: string | null;
+ js: string | null;
+ head: string | null;
+ dependencies: any[];
+ dev_mode: boolean;
+ enable_queue: boolean;
+ layout: any;
+ mode: "blocks" | "interface";
+ root: string;
+ root_url?: string;
+ theme: string;
+ title: string;
+ version: string;
+ space_id: string | null;
+ is_colab: boolean;
+ show_api: boolean;
+ stylesheets: string[];
+ path: string;
+ protocol?: "sse_v1" | "sse" | "ws";
+}
+
+export interface Payload {
+ data: unknown[];
+ fn_index?: number;
+ event_data?: unknown;
+ time?: Date;
+}
+
+export interface PostResponse {
+ error?: string;
+ [x: string]: any;
+}
+export interface UploadResponse {
+ error?: string;
+ files?: string[];
+}
+
+export interface Status {
+ queue: boolean;
+ code?: string;
+ success?: boolean;
+ stage: "pending" | "error" | "complete" | "generating";
+ broken?: boolean;
+ size?: number;
+ position?: number;
+ eta?: number;
+ message?: string;
+ progress_data?: {
+ progress: number | null;
+ index: number | null;
+ length: number | null;
+ unit: string | null;
+ desc: string | null;
+ }[];
+ time?: Date;
+}
+
+export interface LogMessage {
+ log: string;
+ level: "warning" | "info";
+}
+
+export interface SpaceStatusNormal {
+ status: "sleeping" | "running" | "building" | "error" | "stopped";
+ detail:
+ | "SLEEPING"
+ | "RUNNING"
+ | "RUNNING_BUILDING"
+ | "BUILDING"
+ | "NOT_FOUND";
+ load_status: "pending" | "error" | "complete" | "generating";
+ message: string;
+}
+export interface SpaceStatusError {
+ status: "space_error" | "paused";
+ detail:
+ | "NO_APP_FILE"
+ | "CONFIG_ERROR"
+ | "BUILD_ERROR"
+ | "RUNTIME_ERROR"
+ | "PAUSED";
+ load_status: "error";
+ message: string;
+ discussions_enabled: boolean;
+}
+export type SpaceStatus = SpaceStatusNormal | SpaceStatusError;
+
+export type status_callback_function = (a: Status) => void;
+export type SpaceStatusCallback = (a: SpaceStatus) => void;
+
+export type EventType = "data" | "status" | "log";
+
+export interface EventMap {
+ data: Payload;
+ status: Status;
+ log: LogMessage;
+}
+
+export type Event = {
+ [P in K]: EventMap[P] & { type: P; endpoint: string; fn_index: number };
+}[K];
+export type EventListener = (event: Event) => void;
+export type ListenerMap = {
+ [P in K]?: EventListener[];
+};
+export interface FileData {
+ name: string;
+ orig_name?: string;
+ size?: number;
+ data: string;
+ blob?: File;
+ is_file?: boolean;
+ mime_type?: string;
+ alt_text?: string;
+}
diff --git a/client/js/src/upload.ts b/client/js/src/upload.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f5011710ae69b994c3dedd6f43402e6f630a15c8
--- /dev/null
+++ b/client/js/src/upload.ts
@@ -0,0 +1,174 @@
+import { upload_files } from "./client";
+
+export function normalise_file(
+ file: FileData | null,
+ server_url: string,
+ proxy_url: string | null
+): FileData | null;
+
+export function normalise_file(
+ file: FileData[] | null,
+ server_url: string,
+ proxy_url: string | null
+): FileData[] | null;
+
+export function normalise_file(
+ file: FileData[] | FileData | null,
+ server_url: string, // root: string,
+ proxy_url: string | null // root_url: string | null
+): FileData[] | FileData | null;
+
+export function normalise_file(
+ file: FileData[] | FileData | null,
+ server_url: string, // root: string,
+ proxy_url: string | null // root_url: string | null
+): FileData[] | FileData | null {
+ if (file == null) {
+ return null;
+ }
+
+ if (Array.isArray(file)) {
+ const normalized_file: (FileData | null)[] = [];
+
+ for (const x of file) {
+ if (x == null) {
+ normalized_file.push(null);
+ } else {
+ normalized_file.push(normalise_file(x, server_url, proxy_url));
+ }
+ }
+
+ return normalized_file as FileData[];
+ }
+
+ if (file.is_stream) {
+ if (proxy_url == null) {
+ return new FileData({
+ ...file,
+ url: server_url + "/stream/" + file.path
+ });
+ }
+ return new FileData({
+ ...file,
+ url: "/proxy=" + proxy_url + "stream/" + file.path
+ });
+ }
+
+ return new FileData({
+ ...file,
+ url: get_fetchable_url_or_file(file.path, server_url, proxy_url)
+ });
+}
+
+function is_url(str: string): boolean {
+ try {
+ const url = new URL(str);
+ return url.protocol === "http:" || url.protocol === "https:";
+ } catch {
+ return false;
+ }
+}
+
+export function get_fetchable_url_or_file(
+ path: string | null,
+ server_url: string,
+ proxy_url: string | null
+): string {
+ if (path == null) {
+ return proxy_url ? `/proxy=${proxy_url}file=` : `${server_url}/file=`;
+ }
+ if (is_url(path)) {
+ return path;
+ }
+ return proxy_url
+ ? `/proxy=${proxy_url}file=${path}`
+ : `${server_url}/file=${path}`;
+}
+
+export async function upload(
+ file_data: FileData[],
+ root: string,
+ upload_id?: string,
+ upload_fn: typeof upload_files = upload_files
+): Promise<(FileData | null)[] | null> {
+ let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
+ (file_data) => file_data.blob!
+ );
+
+ return await Promise.all(
+ await upload_fn(root, files, undefined, upload_id).then(
+ async (response: { files?: string[]; error?: string }) => {
+ if (response.error) {
+ throw new Error(response.error);
+ } else {
+ if (response.files) {
+ return response.files.map((f, i) => {
+ const file = new FileData({ ...file_data[i], path: f });
+
+ return normalise_file(file, root, null);
+ });
+ }
+
+ return [];
+ }
+ }
+ )
+ );
+}
+
+export async function prepare_files(
+ files: File[],
+ is_stream?: boolean
+): Promise {
+ return files.map(
+ (f, i) =>
+ new FileData({
+ path: f.name,
+ orig_name: f.name,
+ blob: f,
+ size: f.size,
+ mime_type: f.type,
+ is_stream
+ })
+ );
+}
+
+export class FileData {
+ path: string;
+ url?: string;
+ orig_name?: string;
+ size?: number;
+ blob?: File;
+ is_stream?: boolean;
+ mime_type?: string;
+ alt_text?: string;
+
+ constructor({
+ path,
+ url,
+ orig_name,
+ size,
+ blob,
+ is_stream,
+ mime_type,
+ alt_text
+ }: {
+ path: string;
+ url?: string;
+ orig_name?: string;
+ size?: number;
+ blob?: File;
+ is_stream?: boolean;
+ mime_type?: string;
+ alt_text?: string;
+ }) {
+ this.path = path;
+ this.url = url;
+ this.orig_name = orig_name;
+ this.size = size;
+ this.blob = url ? undefined : blob;
+ this.is_stream = is_stream;
+ this.mime_type = mime_type;
+ this.alt_text = alt_text;
+ }
+}
diff --git a/client/js/src/utils.ts b/client/js/src/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5883cfe0b16c9cc0920c25efabe232ad5529a70c
--- /dev/null
+++ b/client/js/src/utils.ts
@@ -0,0 +1,241 @@
+import type { Config } from "./types.js";
+
+/**
+ * This function is used to resolve the URL for making requests when the app has a root path.
+ * The root path could be a path suffix like "/app" which is appended to the end of the base URL. Or
+ * it could be a full URL like "https://abidlabs-test-client-replica--gqf2x.hf.space" which is used when hosting
+ * Gradio apps on Hugging Face Spaces.
+ * @param {string} base_url The base URL at which the Gradio server is hosted
+ * @param {string} root_path The root path, which could be a path suffix (e.g. mounted in FastAPI app) or a full URL (e.g. hosted on Hugging Face Spaces)
+ * @param {boolean} prioritize_base Whether to prioritize the base URL over the root path. This is used when both the base path and root paths are full URLs. For example, for fetching files the root path should be prioritized, but for making requests, the base URL should be prioritized.
+ * @returns {string} the resolved URL
+ */
+export function resolve_root(
+ base_url: string,
+ root_path: string,
+ prioritize_base: boolean
+): string {
+ if (root_path.startsWith("http://") || root_path.startsWith("https://")) {
+ return prioritize_base ? base_url : root_path;
+ }
+ return base_url + root_path;
+}
+
+export function determine_protocol(endpoint: string): {
+ ws_protocol: "ws" | "wss";
+ http_protocol: "http:" | "https:";
+ host: string;
+} {
+ if (endpoint.startsWith("http")) {
+ const { protocol, host } = new URL(endpoint);
+
+ if (host.endsWith("hf.space")) {
+ return {
+ ws_protocol: "wss",
+ host: host,
+ http_protocol: protocol as "http:" | "https:"
+ };
+ }
+ return {
+ ws_protocol: protocol === "https:" ? "wss" : "ws",
+ http_protocol: protocol as "http:" | "https:",
+ host
+ };
+ } else if (endpoint.startsWith("file:")) {
+ // This case is only expected to be used for the Wasm mode (Gradio-lite),
+ // where users can create a local HTML file using it and open the page in a browser directly via the `file:` protocol.
+ return {
+ ws_protocol: "ws",
+ http_protocol: "http:",
+ host: "lite.local" // Special fake hostname only used for this case. This matches the hostname allowed in `is_self_host()` in `js/wasm/network/host.ts`.
+ };
+ }
+
+ // default to secure if no protocol is provided
+ return {
+ ws_protocol: "wss",
+ http_protocol: "https:",
+ host: endpoint
+ };
+}
+
+export const RE_SPACE_NAME = /^[^\/]*\/[^\/]*$/;
+export const RE_SPACE_DOMAIN = /.*hf\.space\/{0,1}$/;
+export async function process_endpoint(
+ app_reference: string,
+ token?: `hf_${string}`
+): Promise<{
+ space_id: string | false;
+ host: string;
+ ws_protocol: "ws" | "wss";
+ http_protocol: "http:" | "https:";
+}> {
+ const headers: { Authorization?: string } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+
+ const _app_reference = app_reference.trim();
+
+ if (RE_SPACE_NAME.test(_app_reference)) {
+ try {
+ const res = await fetch(
+ `https://huggingface.co/api/spaces/${_app_reference}/host`,
+ { headers }
+ );
+
+ if (res.status !== 200)
+ throw new Error("Space metadata could not be loaded.");
+ const _host = (await res.json()).host;
+
+ return {
+ space_id: app_reference,
+ ...determine_protocol(_host)
+ };
+ } catch (e: any) {
+ throw new Error("Space metadata could not be loaded." + e.message);
+ }
+ }
+
+ if (RE_SPACE_DOMAIN.test(_app_reference)) {
+ const { ws_protocol, http_protocol, host } =
+ determine_protocol(_app_reference);
+
+ return {
+ space_id: host.replace(".hf.space", ""),
+ ws_protocol,
+ http_protocol,
+ host
+ };
+ }
+
+ return {
+ space_id: false,
+ ...determine_protocol(_app_reference)
+ };
+}
+
+export function map_names_to_ids(
+ fns: Config["dependencies"]
+): Record {
+ let apis: Record = {};
+
+ fns.forEach(({ api_name }, i) => {
+ if (api_name) apis[api_name] = i;
+ });
+
+ return apis;
+}
+
+const RE_DISABLED_DISCUSSION =
+ /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
+export async function discussions_enabled(space_id: string): Promise {
+ try {
+ const r = await fetch(
+ `https://huggingface.co/api/spaces/${space_id}/discussions`,
+ {
+ method: "HEAD"
+ }
+ );
+ const error = r.headers.get("x-error-message");
+
+ if (error && RE_DISABLED_DISCUSSION.test(error)) return false;
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+export async function get_space_hardware(
+ space_id: string,
+ token: `hf_${string}`
+): Promise<(typeof hardware_types)[number]> {
+ const headers: { Authorization?: string } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+
+ try {
+ const res = await fetch(
+ `https://huggingface.co/api/spaces/${space_id}/runtime`,
+ { headers }
+ );
+
+ if (res.status !== 200)
+ throw new Error("Space hardware could not be obtained.");
+
+ const { hardware } = await res.json();
+
+ return hardware;
+ } catch (e: any) {
+ throw new Error(e.message);
+ }
+}
+
+export async function set_space_hardware(
+ space_id: string,
+ new_hardware: (typeof hardware_types)[number],
+ token: `hf_${string}`
+): Promise<(typeof hardware_types)[number]> {
+ const headers: { Authorization?: string } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+
+ try {
+ const res = await fetch(
+ `https://huggingface.co/api/spaces/${space_id}/hardware`,
+ { headers, body: JSON.stringify(new_hardware) }
+ );
+
+ if (res.status !== 200)
+ throw new Error(
+ "Space hardware could not be set. Please ensure the space hardware provided is valid and that a Hugging Face token is passed in."
+ );
+
+ const { hardware } = await res.json();
+
+ return hardware;
+ } catch (e: any) {
+ throw new Error(e.message);
+ }
+}
+
+export async function set_space_timeout(
+ space_id: string,
+ timeout: number,
+ token: `hf_${string}`
+): Promise {
+ const headers: { Authorization?: string } = {};
+ if (token) {
+ headers.Authorization = `Bearer ${token}`;
+ }
+
+ try {
+ const res = await fetch(
+ `https://huggingface.co/api/spaces/${space_id}/hardware`,
+ { headers, body: JSON.stringify({ seconds: timeout }) }
+ );
+
+ if (res.status !== 200)
+ throw new Error(
+ "Space hardware could not be set. Please ensure the space hardware provided is valid and that a Hugging Face token is passed in."
+ );
+
+ const { hardware } = await res.json();
+
+ return hardware;
+ } catch (e: any) {
+ throw new Error(e.message);
+ }
+}
+
+export const hardware_types = [
+ "cpu-basic",
+ "cpu-upgrade",
+ "t4-small",
+ "t4-medium",
+ "a10g-small",
+ "a10g-large",
+ "a100-large"
+] as const;
diff --git a/client/js/tsconfig.json b/client/js/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..132b1c6b4a220486e7d34b5f664fb8a89874be3c
--- /dev/null
+++ b/client/js/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "include": ["src/**/*"],
+ "exclude": ["src/**/*.test.ts", "src/**/*.node-test.ts"],
+ "compilerOptions": {
+ "allowJs": true,
+ "declaration": true,
+ "emitDeclarationOnly": true,
+ "outDir": "dist",
+ "declarationMap": true,
+ "module": "es2020",
+ "moduleResolution": "bundler",
+ "skipDefaultLibCheck": true
+ }
+}
diff --git a/client/js/vite.config.js b/client/js/vite.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..985554d9e5f20520c5858119392222f52f67475a
--- /dev/null
+++ b/client/js/vite.config.js
@@ -0,0 +1,38 @@
+import { defineConfig } from "vite";
+import { svelte } from "@sveltejs/vite-plugin-svelte";
+import { fileURLToPath } from "url";
+import path from "path";
+const __dirname = fileURLToPath(new URL(".", import.meta.url));
+
+export default defineConfig({
+ build: {
+ lib: {
+ entry: "src/index.ts",
+ formats: ["es"]
+ },
+ rollupOptions: {
+ input: "src/index.ts",
+ output: {
+ dir: "dist"
+ }
+ }
+ },
+ plugins: [
+ svelte()
+ // {
+ // name: "resolve-gradio-client",
+ // enforce: "pre",
+ // resolveId(id) {
+ // if (id === "@gradio/client") {
+ // return path.join(__dirname, "src", "index.ts");
+ // }
+ // }
+ // }
+ ],
+
+ ssr: {
+ target: "node",
+ format: "esm",
+ noExternal: ["ws", "semiver", "@gradio/upload"]
+ }
+});
diff --git a/client/python/CHANGELOG.md b/client/python/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..480f5544ae72b9e14bfc572f44c2109bba4230d9
--- /dev/null
+++ b/client/python/CHANGELOG.md
@@ -0,0 +1,501 @@
+# gradio_client
+
+## 0.8.1
+
+### Features
+
+- [#7075](https://github.com/gradio-app/gradio/pull/7075) [`1fc8a94`](https://github.com/gradio-app/gradio/commit/1fc8a941384775f587a6ef30365960f43353cb0d) - fix lint. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7054](https://github.com/gradio-app/gradio/pull/7054) [`64c65d8`](https://github.com/gradio-app/gradio/commit/64c65d821983961111297a969946d87e2fc4105d) - Add encoding to open/writing files on the deploy_discord function. Thanks [@WilliamHarer](https://github.com/WilliamHarer)!
+
+## 0.8.0
+
+### Fixes
+
+- [#6846](https://github.com/gradio-app/gradio/pull/6846) [`48d6534`](https://github.com/gradio-app/gradio/commit/48d6534b40f80e7e70a4061f97d9f2e23ba77fe1) - Add `show_api` parameter to events, and fix `gr.load()`. Also makes some minor improvements to the "view API" page when running on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6767](https://github.com/gradio-app/gradio/pull/6767) [`7bb561a`](https://github.com/gradio-app/gradio/commit/7bb561a294ca41d1044927cb34d8645c4175cae0) - Rewriting parts of the README and getting started guides for 4.0. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.7.3
+
+### Fixes
+
+- [#6693](https://github.com/gradio-app/gradio/pull/6693) [`34f9431`](https://github.com/gradio-app/gradio/commit/34f943101bf7dd6b8a8974a6131c1ed7c4a0dac0) - Python client properly handles hearbeat and log messages. Also handles responses longer than 65k. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.7.2
+
+### Features
+
+- [#6598](https://github.com/gradio-app/gradio/pull/6598) [`7cbf96e`](https://github.com/gradio-app/gradio/commit/7cbf96e0bdd12db7ecac7bf99694df0a912e5864) - Issue 5245: consolidate usage of requests and httpx. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6704](https://github.com/gradio-app/gradio/pull/6704) [`24e0481`](https://github.com/gradio-app/gradio/commit/24e048196e8f7bd309ef5c597d4ffc6ca4ed55d0) - Hotfix: update `huggingface_hub` dependency version. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6543](https://github.com/gradio-app/gradio/pull/6543) [`8a70e83`](https://github.com/gradio-app/gradio/commit/8a70e83db9c7751b46058cdd2514e6bddeef6210) - switch from black to ruff formatter. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+### Fixes
+
+- [#6556](https://github.com/gradio-app/gradio/pull/6556) [`d76bcaa`](https://github.com/gradio-app/gradio/commit/d76bcaaaf0734aaf49a680f94ea9d4d22a602e70) - Fix api event drops. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.1
+
+### Fixes
+
+- [#6602](https://github.com/gradio-app/gradio/pull/6602) [`b8034a1`](https://github.com/gradio-app/gradio/commit/b8034a1e72c3aac649ee0ad9178ffdbaaa60fc61) - Fix: Gradio Client work with private Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.7.0
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Add json schema unit tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Custom components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Swap websockets for SSE. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.7.0-beta.2
+
+### Features
+
+- [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6069](https://github.com/gradio-app/gradio/pull/6069) [`bf127e124`](https://github.com/gradio-app/gradio/commit/bf127e1241a41401e144874ea468dff8474eb505) - Swap websockets for SSE. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.0-beta.1
+
+### Features
+
+- [#6082](https://github.com/gradio-app/gradio/pull/6082) [`037e5af33`](https://github.com/gradio-app/gradio/commit/037e5af3363c5b321b95efc955ee8d6ec0f4504e) - WIP: Fix docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5970](https://github.com/gradio-app/gradio/pull/5970) [`0c571c044`](https://github.com/gradio-app/gradio/commit/0c571c044035989d6fe33fc01fee63d1780635cb) - Add json schema unit tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6073](https://github.com/gradio-app/gradio/pull/6073) [`abff6fb75`](https://github.com/gradio-app/gradio/commit/abff6fb758bd310053a23c938bf1dd8fbdc5d333) - Fix remaining xfail tests in backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.7.0-beta.0
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Simplify how files are handled in components in 4.0. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Rename gradio_component to gradio component. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.6.1
+
+### Fixes
+
+- [#5811](https://github.com/gradio-app/gradio/pull/5811) [`1d5b15a2d`](https://github.com/gradio-app/gradio/commit/1d5b15a2d24387154f2cfb40a36de25b331471d3) - Assert refactor in external.py. Thanks [@harry-urek](https://github.com/harry-urek)!
+
+## 0.6.0
+
+### Highlights
+
+#### new `FileExplorer` component ([#5672](https://github.com/gradio-app/gradio/pull/5672) [`e4a307ed6`](https://github.com/gradio-app/gradio/commit/e4a307ed6cde3bbdf4ff2f17655739addeec941e))
+
+Thanks to a new capability that allows components to communicate directly with the server _without_ passing data via the value, we have created a new `FileExplorer` component.
+
+This component allows you to populate the explorer by passing a glob, but only provides the selected file(s) in your prediction function.
+
+Users can then navigate the virtual filesystem and select files which will be accessible in your predict function. This component will allow developers to build more complex spaces, with more flexible input options.
+
+![output](https://github.com/pngwn/MDsveX/assets/12937446/ef108f0b-0e84-4292-9984-9dc66b3e144d)
+
+For more information check the [`FileExplorer` documentation](https://gradio.app/docs/fileexplorer).
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.5.3
+
+### Features
+
+- [#5721](https://github.com/gradio-app/gradio/pull/5721) [`84e03fe50`](https://github.com/gradio-app/gradio/commit/84e03fe506e08f1f81bac6d504c9fba7924f2d93) - Adds copy buttons to website, and better descriptions to API Docs. Thanks [@aliabd](https://github.com/aliabd)!
+
+## 0.5.2
+
+### Features
+
+- [#5653](https://github.com/gradio-app/gradio/pull/5653) [`ea0e00b20`](https://github.com/gradio-app/gradio/commit/ea0e00b207b4b90a10e9d054c4202d4e705a29ba) - Prevent Clients from accessing API endpoints that set `api_name=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.5.1
+
+### Features
+
+- [#5514](https://github.com/gradio-app/gradio/pull/5514) [`52f783175`](https://github.com/gradio-app/gradio/commit/52f7831751b432411e109bd41add4ab286023a8e) - refactor: Use package.json for version management. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+## 0.5.0
+
+### Highlights
+
+#### Enable streaming audio in python client ([#5248](https://github.com/gradio-app/gradio/pull/5248) [`390624d8`](https://github.com/gradio-app/gradio/commit/390624d8ad2b1308a5bf8384435fd0db98d8e29e))
+
+The `gradio_client` now supports streaming file outputs 🌊
+
+No new syntax! Connect to a gradio demo that supports streaming file outputs and call `predict` or `submit` as you normally would.
+
+```python
+import gradio_client as grc
+client = grc.Client("gradio/stream_audio_out")
+
+# Get the entire generated audio as a local file
+client.predict("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+job = client.submit("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+# Get the entire generated audio as a local file
+job.result()
+
+# Each individual chunk
+job.outputs()
+```
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#5295](https://github.com/gradio-app/gradio/pull/5295) [`7b8fa8aa`](https://github.com/gradio-app/gradio/commit/7b8fa8aa58f95f5046b9add64b40368bd3f1b700) - Allow caching examples with streamed output. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.4.0
+
+### Highlights
+
+#### Client.predict will now return the final output for streaming endpoints ([#5057](https://github.com/gradio-app/gradio/pull/5057) [`35856f8b`](https://github.com/gradio-app/gradio/commit/35856f8b54548cae7bd3b8d6a4de69e1748283b2))
+
+### This is a breaking change (for gradio_client only)!
+
+Previously, `Client.predict` would only return the first output of an endpoint that streamed results. This was causing confusion for developers that wanted to call these streaming demos via the client.
+
+We realize that developers using the client don't know the internals of whether a demo streams or not, so we're changing the behavior of predict to match developer expectations.
+
+Using `Client.predict` will now return the final output of a streaming endpoint. This will make it even easier to use gradio apps via the client.
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Features
+
+- [#5076](https://github.com/gradio-app/gradio/pull/5076) [`2745075a`](https://github.com/gradio-app/gradio/commit/2745075a26f80e0e16863d483401ff1b6c5ada7a) - Add deploy_discord to docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#5061](https://github.com/gradio-app/gradio/pull/5061) [`136adc9c`](https://github.com/gradio-app/gradio/commit/136adc9ccb23e5cb4d02d2e88f23f0b850041f98) - Ensure `gradio_client` is backwards compatible with `gradio==3.24.1`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.3.0
+
+### Highlights
+
+#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
+
+We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
+
+It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
+
+_🦙 Turning Llama 2 70b into a discord bot 🦙_
+
+```python
+import gradio_client as grc
+grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
+```
+
+
+
+#### Getting started with template spaces
+
+To help get you started, we have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) with template spaces you can use to turn state of the art LLMs powered by Gradio to discord bots.
+
+Currently we have template spaces for:
+
+- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
+- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
+- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
+
+But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
+
+❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
+
+Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### New Features:
+
+- Endpoints that return layout components are now properly handled in the `submit` and `view_api` methods. Output layout components are not returned by the API but all other components are (excluding `gr.State`). By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
+
+### Bug Fixes:
+
+No changes to highlight
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.9
+
+### New Features:
+
+No changes to highlight
+
+### Bug Fixes:
+
+- Fix bug determining the api name when a demo has `api_name=False` by [@freddyboulton](https://github.com/freddyaboulton) in [PR 4886](https://github.com/gradio-app/gradio/pull/4886)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
+
+# 0.2.8
+
+### New Features:
+
+- Support loading gradio apps where `api_name=False` by [@abidlabs](https://github.com/abidlabs) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+
+### Bug Fixes:
+
+- Fix bug where space duplication would error if the demo has cpu-basic hardware by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4583](https://github.com/gradio-app/gradio/pull/4583)
+- Fixes and optimizations to URL/download functions by [@akx](https://github.com/akx) in [PR 4695](https://github.com/gradio-app/gradio/pull/4695)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.7
+
+### New Features:
+
+- The output directory for files downloaded via the Client can now be set by the `output_dir` parameter in `Client` by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Bug Fixes:
+
+- The output directory for files downloaded via the Client are now set to a temporary directory by default (instead of the working directory in some cases) by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.6
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed bug file deserialization didn't preserve all file extensions by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4440](https://github.com/gradio-app/gradio/pull/4440)
+- Fixed bug where mounted apps could not be called via the client by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4435](https://github.com/gradio-app/gradio/pull/4435)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.5
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes parameter names not showing underscores by [@abidlabs](https://github.com/abidlabs) in [PR 4230](https://github.com/gradio-app/gradio/pull/4230)
+- Fixes issue in which state was not handled correctly if `serialize=False` by [@abidlabs](https://github.com/abidlabs) in [PR 4230](https://github.com/gradio-app/gradio/pull/4230)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.4
+
+### Bug Fixes:
+
+- Fixes missing serialization classes for several components: `Barplot`, `Lineplot`, `Scatterplot`, `AnnotatedImage`, `Interpretation` by [@abidlabs](https://github.com/abidlabs) in [PR 4167](https://github.com/gradio-app/gradio/pull/4167)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.2.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix example inputs for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.2.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Only send request to `/info` route if demo version is above `3.28.3` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4109](https://github.com/gradio-app/gradio/pull/4109)
+
+### Other Changes:
+
+- Fix bug in test from gradio 3.29.0 refactor by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4138](https://github.com/gradio-app/gradio/pull/4138)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+# 0.2.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+Removes extraneous `State` component info from the `Client.view_api()` method by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+Separates flaky tests from non-flaky tests by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.4
+
+### New Features:
+
+- Progress Updates from `gr.Progress()` can be accessed via `job.status().progress_data` by @freddyaboulton](https://github.com/freddyaboulton) in [PR 3924](https://github.com/gradio-app/gradio/pull/3924)
+
+### Bug Fixes:
+
+- Fixed bug where unnamed routes where displayed with `api_name` instead of `fn_index` in `view_api` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3972](https://github.com/gradio-app/gradio/pull/3972)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed bug where `Video` components in latest gradio were not able to be deserialized by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3860](https://github.com/gradio-app/gradio/pull/3860)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.2
+
+First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
+
+As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
+
+![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/whisper-screenshot.jpg)
+
+Using the `gradio_client` library, we can easily use the Gradio as an API to transcribe audio files programmatically.
+
+Here's the entire code to do it:
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/whisper")
+client.predict("audio_sample.wav")
+
+>> "This is a test of the whisper speech recognition model."
+```
+
+Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
\ No newline at end of file
diff --git a/client/python/README.md b/client/python/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0482b30d16211d9b478d51b788397ae25906f925
--- /dev/null
+++ b/client/python/README.md
@@ -0,0 +1,143 @@
+# `gradio_client`: Use a Gradio app as an API -- in 3 lines of Python
+
+This directory contains the source code for `gradio_client`, a lightweight Python library that makes it very easy to use any Gradio app as an API.
+
+As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
+
+![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/whisper-screenshot.jpg)
+
+Using the `gradio_client` library, we can easily use the Gradio as an API to transcribe audio files programmatically.
+
+Here's the entire code to do it:
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/whisper")
+client.predict("audio_sample.wav")
+
+>> "This is a test of the whisper speech recognition model."
+```
+
+The Gradio client works with any Gradio Space, whether it be an image generator, a stateful chatbot, or a tax calculator.
+
+## Installation
+
+If you already have a recent version of `gradio`, then the `gradio_client` is included as a dependency.
+
+Otherwise, the lightweight `gradio_client` package can be installed from pip (or pip3) and works with Python versions 3.8 or higher:
+
+```bash
+$ pip install gradio_client
+```
+
+## Basic Usage
+
+### Connecting to a Space or a Gradio app
+
+Start by connecting instantiating a `Client` object and connecting it to a Gradio app that is running on Spaces (or anywhere else)!
+
+**Connecting to a Space**
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/en2fr") # a Space that translates from English to French
+```
+
+You can also connect to private Spaces by passing in your HF token with the `hf_token` parameter. You can get your HF token here: https://huggingface.co/settings/tokens
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/my-private-space", hf_token="...")
+```
+
+**Duplicating a Space for private use**
+
+While you can use any public Space as an API, you may get rate limited by Hugging Face if you make too many requests. For unlimited usage of a Space, simply duplicate the Space to create a private Space,
+and then use it to make as many requests as you'd like!
+
+The `gradio_client` includes a class method: `Client.duplicate()` to make this process simple:
+
+```python
+from gradio_client import Client
+
+client = Client.duplicate("abidlabs/whisper")
+client.predict("audio_sample.wav")
+
+>> "This is a test of the whisper speech recognition model."
+```
+
+If you have previously duplicated a Space, re-running `duplicate()` will _not_ create a new Space. Instead, the Client will attach to the previously-created Space. So it is safe to re-run the `Client.duplicate()` method multiple times.
+
+**Note:** if the original Space uses GPUs, your private Space will as well, and your Hugging Face account will get billed based on the price of the GPU. To minimize charges, your Space will automatically go to sleep after 1 hour of inactivity. You can also set the hardware using the `hardware` parameter of `duplicate()`.
+
+**Connecting a general Gradio app**
+
+If your app is running somewhere else, just provide the full URL instead, including the "http://" or "https://". Here's an example of making predictions to a Gradio app that is running on a share URL:
+
+```python
+from gradio_client import Client
+
+client = Client("https://bec81a83-5b5c-471e.gradio.live")
+```
+
+### Inspecting the API endpoints
+
+Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `.view_api()` method. For the Whisper Space, we see the following:
+
+```
+Client.predict() Usage Info
+---------------------------
+Named API endpoints: 1
+
+ - predict(input_audio, api_name="/predict") -> value_0
+ Parameters:
+ - [Audio] input_audio: str (filepath or URL)
+ Returns:
+ - [Textbox] value_0: str (value)
+```
+
+This shows us that we have 1 API endpoint in this space, and shows us how to use the API endpoint to make a prediction: we should call the `.predict()` method, providing a parameter `input_audio` of type `str`, which is a `filepath or URL`.
+
+We should also provide the `api_name='/predict'` argument. Although this isn't necessary if a Gradio app has a single named endpoint, it does allow us to call different endpoints in a single app if they are available. If an app has unnamed API endpoints, these can also be displayed by running `.view_api(all_endpoints=True)`.
+
+### Making a prediction
+
+The simplest way to make a prediction is simply to call the `.predict()` function with the appropriate arguments:
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/en2fr")
+client.predict("Hello")
+
+>> Bonjour
+```
+
+If there are multiple parameters, then you should pass them as separate arguments to `.predict()`, like this:
+
+```python
+from gradio_client import Client
+
+client = Client("gradio/calculator")
+client.predict(4, "add", 5)
+
+>> 9.0
+```
+
+For certain inputs, such as images, you should pass in the filepath or URL to the file. Likewise, for the corresponding output types, you will get a filepath or URL returned.
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/whisper")
+client.predict("https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3")
+
+>> "My thought I have nobody by a beauty and will as you poured. Mr. Rochester is serve in that so don't find simpus, and devoted abode, to at might in a r—"
+```
+
+## Advanced Usage
+
+For more ways to use the Gradio Python Client, check out our dedicated Guide on the Python client, available here: https://www.gradio.app/guides/getting-started-with-the-python-client
diff --git a/client/python/build_pypi.sh b/client/python/build_pypi.sh
new file mode 100644
index 0000000000000000000000000000000000000000..00068e11da1efa3e7359f4c0ad4fca6b4462371a
--- /dev/null
+++ b/client/python/build_pypi.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+cd "$(dirname ${0})"
+
+python3 -m pip install build
+rm -rf dist/*
+rm -rf build/*
+python3 -m build
diff --git a/client/python/gradio_client/CHANGELOG.md b/client/python/gradio_client/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..480f5544ae72b9e14bfc572f44c2109bba4230d9
--- /dev/null
+++ b/client/python/gradio_client/CHANGELOG.md
@@ -0,0 +1,501 @@
+# gradio_client
+
+## 0.8.1
+
+### Features
+
+- [#7075](https://github.com/gradio-app/gradio/pull/7075) [`1fc8a94`](https://github.com/gradio-app/gradio/commit/1fc8a941384775f587a6ef30365960f43353cb0d) - fix lint. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7054](https://github.com/gradio-app/gradio/pull/7054) [`64c65d8`](https://github.com/gradio-app/gradio/commit/64c65d821983961111297a969946d87e2fc4105d) - Add encoding to open/writing files on the deploy_discord function. Thanks [@WilliamHarer](https://github.com/WilliamHarer)!
+
+## 0.8.0
+
+### Fixes
+
+- [#6846](https://github.com/gradio-app/gradio/pull/6846) [`48d6534`](https://github.com/gradio-app/gradio/commit/48d6534b40f80e7e70a4061f97d9f2e23ba77fe1) - Add `show_api` parameter to events, and fix `gr.load()`. Also makes some minor improvements to the "view API" page when running on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6767](https://github.com/gradio-app/gradio/pull/6767) [`7bb561a`](https://github.com/gradio-app/gradio/commit/7bb561a294ca41d1044927cb34d8645c4175cae0) - Rewriting parts of the README and getting started guides for 4.0. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.7.3
+
+### Fixes
+
+- [#6693](https://github.com/gradio-app/gradio/pull/6693) [`34f9431`](https://github.com/gradio-app/gradio/commit/34f943101bf7dd6b8a8974a6131c1ed7c4a0dac0) - Python client properly handles hearbeat and log messages. Also handles responses longer than 65k. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.7.2
+
+### Features
+
+- [#6598](https://github.com/gradio-app/gradio/pull/6598) [`7cbf96e`](https://github.com/gradio-app/gradio/commit/7cbf96e0bdd12db7ecac7bf99694df0a912e5864) - Issue 5245: consolidate usage of requests and httpx. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6704](https://github.com/gradio-app/gradio/pull/6704) [`24e0481`](https://github.com/gradio-app/gradio/commit/24e048196e8f7bd309ef5c597d4ffc6ca4ed55d0) - Hotfix: update `huggingface_hub` dependency version. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6543](https://github.com/gradio-app/gradio/pull/6543) [`8a70e83`](https://github.com/gradio-app/gradio/commit/8a70e83db9c7751b46058cdd2514e6bddeef6210) - switch from black to ruff formatter. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+### Fixes
+
+- [#6556](https://github.com/gradio-app/gradio/pull/6556) [`d76bcaa`](https://github.com/gradio-app/gradio/commit/d76bcaaaf0734aaf49a680f94ea9d4d22a602e70) - Fix api event drops. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.1
+
+### Fixes
+
+- [#6602](https://github.com/gradio-app/gradio/pull/6602) [`b8034a1`](https://github.com/gradio-app/gradio/commit/b8034a1e72c3aac649ee0ad9178ffdbaaa60fc61) - Fix: Gradio Client work with private Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.7.0
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Add json schema unit tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Custom components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Swap websockets for SSE. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.7.0-beta.2
+
+### Features
+
+- [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6069](https://github.com/gradio-app/gradio/pull/6069) [`bf127e124`](https://github.com/gradio-app/gradio/commit/bf127e1241a41401e144874ea468dff8474eb505) - Swap websockets for SSE. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.7.0-beta.1
+
+### Features
+
+- [#6082](https://github.com/gradio-app/gradio/pull/6082) [`037e5af33`](https://github.com/gradio-app/gradio/commit/037e5af3363c5b321b95efc955ee8d6ec0f4504e) - WIP: Fix docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5970](https://github.com/gradio-app/gradio/pull/5970) [`0c571c044`](https://github.com/gradio-app/gradio/commit/0c571c044035989d6fe33fc01fee63d1780635cb) - Add json schema unit tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6073](https://github.com/gradio-app/gradio/pull/6073) [`abff6fb75`](https://github.com/gradio-app/gradio/commit/abff6fb758bd310053a23c938bf1dd8fbdc5d333) - Fix remaining xfail tests in backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 0.7.0-beta.0
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Simplify how files are handled in components in 4.0. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Rename gradio_component to gradio component. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 0.6.1
+
+### Fixes
+
+- [#5811](https://github.com/gradio-app/gradio/pull/5811) [`1d5b15a2d`](https://github.com/gradio-app/gradio/commit/1d5b15a2d24387154f2cfb40a36de25b331471d3) - Assert refactor in external.py. Thanks [@harry-urek](https://github.com/harry-urek)!
+
+## 0.6.0
+
+### Highlights
+
+#### new `FileExplorer` component ([#5672](https://github.com/gradio-app/gradio/pull/5672) [`e4a307ed6`](https://github.com/gradio-app/gradio/commit/e4a307ed6cde3bbdf4ff2f17655739addeec941e))
+
+Thanks to a new capability that allows components to communicate directly with the server _without_ passing data via the value, we have created a new `FileExplorer` component.
+
+This component allows you to populate the explorer by passing a glob, but only provides the selected file(s) in your prediction function.
+
+Users can then navigate the virtual filesystem and select files which will be accessible in your predict function. This component will allow developers to build more complex spaces, with more flexible input options.
+
+![output](https://github.com/pngwn/MDsveX/assets/12937446/ef108f0b-0e84-4292-9984-9dc66b3e144d)
+
+For more information check the [`FileExplorer` documentation](https://gradio.app/docs/fileexplorer).
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.5.3
+
+### Features
+
+- [#5721](https://github.com/gradio-app/gradio/pull/5721) [`84e03fe50`](https://github.com/gradio-app/gradio/commit/84e03fe506e08f1f81bac6d504c9fba7924f2d93) - Adds copy buttons to website, and better descriptions to API Docs. Thanks [@aliabd](https://github.com/aliabd)!
+
+## 0.5.2
+
+### Features
+
+- [#5653](https://github.com/gradio-app/gradio/pull/5653) [`ea0e00b20`](https://github.com/gradio-app/gradio/commit/ea0e00b207b4b90a10e9d054c4202d4e705a29ba) - Prevent Clients from accessing API endpoints that set `api_name=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.5.1
+
+### Features
+
+- [#5514](https://github.com/gradio-app/gradio/pull/5514) [`52f783175`](https://github.com/gradio-app/gradio/commit/52f7831751b432411e109bd41add4ab286023a8e) - refactor: Use package.json for version management. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+## 0.5.0
+
+### Highlights
+
+#### Enable streaming audio in python client ([#5248](https://github.com/gradio-app/gradio/pull/5248) [`390624d8`](https://github.com/gradio-app/gradio/commit/390624d8ad2b1308a5bf8384435fd0db98d8e29e))
+
+The `gradio_client` now supports streaming file outputs 🌊
+
+No new syntax! Connect to a gradio demo that supports streaming file outputs and call `predict` or `submit` as you normally would.
+
+```python
+import gradio_client as grc
+client = grc.Client("gradio/stream_audio_out")
+
+# Get the entire generated audio as a local file
+client.predict("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+job = client.submit("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+# Get the entire generated audio as a local file
+job.result()
+
+# Each individual chunk
+job.outputs()
+```
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#5295](https://github.com/gradio-app/gradio/pull/5295) [`7b8fa8aa`](https://github.com/gradio-app/gradio/commit/7b8fa8aa58f95f5046b9add64b40368bd3f1b700) - Allow caching examples with streamed output. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 0.4.0
+
+### Highlights
+
+#### Client.predict will now return the final output for streaming endpoints ([#5057](https://github.com/gradio-app/gradio/pull/5057) [`35856f8b`](https://github.com/gradio-app/gradio/commit/35856f8b54548cae7bd3b8d6a4de69e1748283b2))
+
+### This is a breaking change (for gradio_client only)!
+
+Previously, `Client.predict` would only return the first output of an endpoint that streamed results. This was causing confusion for developers that wanted to call these streaming demos via the client.
+
+We realize that developers using the client don't know the internals of whether a demo streams or not, so we're changing the behavior of predict to match developer expectations.
+
+Using `Client.predict` will now return the final output of a streaming endpoint. This will make it even easier to use gradio apps via the client.
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Features
+
+- [#5076](https://github.com/gradio-app/gradio/pull/5076) [`2745075a`](https://github.com/gradio-app/gradio/commit/2745075a26f80e0e16863d483401ff1b6c5ada7a) - Add deploy_discord to docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#5061](https://github.com/gradio-app/gradio/pull/5061) [`136adc9c`](https://github.com/gradio-app/gradio/commit/136adc9ccb23e5cb4d02d2e88f23f0b850041f98) - Ensure `gradio_client` is backwards compatible with `gradio==3.24.1`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 0.3.0
+
+### Highlights
+
+#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
+
+We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
+
+It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
+
+_🦙 Turning Llama 2 70b into a discord bot 🦙_
+
+```python
+import gradio_client as grc
+grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
+```
+
+
+
+#### Getting started with template spaces
+
+To help get you started, we have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) with template spaces you can use to turn state of the art LLMs powered by Gradio to discord bots.
+
+Currently we have template spaces for:
+
+- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
+- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
+- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
+
+But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
+
+❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
+
+Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### New Features:
+
+- Endpoints that return layout components are now properly handled in the `submit` and `view_api` methods. Output layout components are not returned by the API but all other components are (excluding `gr.State`). By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
+
+### Bug Fixes:
+
+No changes to highlight
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.9
+
+### New Features:
+
+No changes to highlight
+
+### Bug Fixes:
+
+- Fix bug determining the api name when a demo has `api_name=False` by [@freddyboulton](https://github.com/freddyaboulton) in [PR 4886](https://github.com/gradio-app/gradio/pull/4886)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
+
+# 0.2.8
+
+### New Features:
+
+- Support loading gradio apps where `api_name=False` by [@abidlabs](https://github.com/abidlabs) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+
+### Bug Fixes:
+
+- Fix bug where space duplication would error if the demo has cpu-basic hardware by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4583](https://github.com/gradio-app/gradio/pull/4583)
+- Fixes and optimizations to URL/download functions by [@akx](https://github.com/akx) in [PR 4695](https://github.com/gradio-app/gradio/pull/4695)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.7
+
+### New Features:
+
+- The output directory for files downloaded via the Client can now be set by the `output_dir` parameter in `Client` by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Bug Fixes:
+
+- The output directory for files downloaded via the Client are now set to a temporary directory by default (instead of the working directory in some cases) by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.6
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed bug file deserialization didn't preserve all file extensions by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4440](https://github.com/gradio-app/gradio/pull/4440)
+- Fixed bug where mounted apps could not be called via the client by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4435](https://github.com/gradio-app/gradio/pull/4435)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.5
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes parameter names not showing underscores by [@abidlabs](https://github.com/abidlabs) in [PR 4230](https://github.com/gradio-app/gradio/pull/4230)
+- Fixes issue in which state was not handled correctly if `serialize=False` by [@abidlabs](https://github.com/abidlabs) in [PR 4230](https://github.com/gradio-app/gradio/pull/4230)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+# 0.2.4
+
+### Bug Fixes:
+
+- Fixes missing serialization classes for several components: `Barplot`, `Lineplot`, `Scatterplot`, `AnnotatedImage`, `Interpretation` by [@abidlabs](https://github.com/abidlabs) in [PR 4167](https://github.com/gradio-app/gradio/pull/4167)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.2.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix example inputs for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.2.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Only send request to `/info` route if demo version is above `3.28.3` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4109](https://github.com/gradio-app/gradio/pull/4109)
+
+### Other Changes:
+
+- Fix bug in test from gradio 3.29.0 refactor by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4138](https://github.com/gradio-app/gradio/pull/4138)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+# 0.2.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+Removes extraneous `State` component info from the `Client.view_api()` method by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+Separates flaky tests from non-flaky tests by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.4
+
+### New Features:
+
+- Progress Updates from `gr.Progress()` can be accessed via `job.status().progress_data` by @freddyaboulton](https://github.com/freddyaboulton) in [PR 3924](https://github.com/gradio-app/gradio/pull/3924)
+
+### Bug Fixes:
+
+- Fixed bug where unnamed routes where displayed with `api_name` instead of `fn_index` in `view_api` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3972](https://github.com/gradio-app/gradio/pull/3972)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed bug where `Video` components in latest gradio were not able to be deserialized by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3860](https://github.com/gradio-app/gradio/pull/3860)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+# 0.1.2
+
+First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
+
+As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
+
+![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/whisper-screenshot.jpg)
+
+Using the `gradio_client` library, we can easily use the Gradio as an API to transcribe audio files programmatically.
+
+Here's the entire code to do it:
+
+```python
+from gradio_client import Client
+
+client = Client("abidlabs/whisper")
+client.predict("audio_sample.wav")
+
+>> "This is a test of the whisper speech recognition model."
+```
+
+Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
\ No newline at end of file
diff --git a/client/python/gradio_client/__init__.py b/client/python/gradio_client/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..01d6b290be59acf63e1309e508927ddf060cfc40
--- /dev/null
+++ b/client/python/gradio_client/__init__.py
@@ -0,0 +1,7 @@
+from gradio_client.client import Client
+from gradio_client.utils import __version__
+
+__all__ = [
+ "Client",
+ "__version__",
+]
diff --git a/client/python/gradio_client/cli/__init__.py b/client/python/gradio_client/cli/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c796253489147f941b78b5bb04a82935a72edab
--- /dev/null
+++ b/client/python/gradio_client/cli/__init__.py
@@ -0,0 +1,3 @@
+from gradio_client.cli import deploy_discord
+
+__all__ = ["deploy_discord"]
diff --git a/client/python/gradio_client/cli/deploy_discord.py b/client/python/gradio_client/cli/deploy_discord.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a828a32a0655644fb44c4ac3780b1eacd8a695e
--- /dev/null
+++ b/client/python/gradio_client/cli/deploy_discord.py
@@ -0,0 +1,48 @@
+from typing import List, Optional
+
+from typer import Option
+from typing_extensions import Annotated
+
+from gradio_client import Client
+
+
+def main(
+ src: Annotated[
+ Optional[str],
+ Option(
+ help="The space id or url or gradio app you want to deploy as a gradio bot."
+ ),
+ ] = None,
+ discord_bot_token: Annotated[
+ str, Option(help="Discord bot token. Get one on the discord website.")
+ ] = None,
+ api_names: Annotated[
+ List[str], Option(help="Api names to turn into discord bots")
+ ] = None,
+ to_id: Annotated[
+ Optional[str], Option(help="Name of the space used to host the discord bot")
+ ] = None,
+ hf_token: Annotated[
+ Optional[str],
+ Option(
+ help=(
+ "Hugging Face token. Can be ommitted if you are logged in via huggingface_hub cli. "
+ "Must be provided if upstream space is private."
+ )
+ ),
+ ] = None,
+ private: Annotated[
+ bool, Option(help="Whether the discord bot space is private.")
+ ] = False,
+):
+ for i, name in enumerate(api_names):
+ if "," in name:
+ api_names[i] = tuple(name.split(","))
+
+ Client(src).deploy_discord(
+ discord_bot_token=discord_bot_token,
+ api_names=api_names,
+ to_id=to_id,
+ hf_token=hf_token,
+ private=private,
+ )
diff --git a/client/python/gradio_client/client.py b/client/python/gradio_client/client.py
new file mode 100644
index 0000000000000000000000000000000000000000..62462ffd244d84a94e3ea8b8f3daba8282108f44
--- /dev/null
+++ b/client/python/gradio_client/client.py
@@ -0,0 +1,1708 @@
+"""The main Client class for the Python client."""
+from __future__ import annotations
+
+import concurrent.futures
+import json
+import os
+import re
+import secrets
+import tempfile
+import threading
+import time
+import urllib.parse
+import uuid
+import warnings
+from concurrent.futures import Future
+from dataclasses import dataclass
+from datetime import datetime
+from pathlib import Path
+from threading import Lock
+from typing import Any, Callable, Literal
+
+import httpx
+import huggingface_hub
+import websockets
+from huggingface_hub import CommitOperationAdd, SpaceHardware, SpaceStage
+from huggingface_hub.utils import (
+ RepositoryNotFoundError,
+ build_hf_headers,
+ send_telemetry,
+)
+from packaging import version
+
+from gradio_client import serializing, utils
+from gradio_client.documentation import document, set_documentation_group
+from gradio_client.exceptions import SerializationSetupError
+from gradio_client.utils import (
+ Communicator,
+ JobStatus,
+ Message,
+ QueueError,
+ ServerMessage,
+ Status,
+ StatusUpdate,
+)
+
+set_documentation_group("py-client")
+
+
+DEFAULT_TEMP_DIR = os.environ.get("GRADIO_TEMP_DIR") or str(
+ Path(tempfile.gettempdir()) / "gradio"
+)
+
+
+@document("predict", "submit", "view_api", "duplicate", "deploy_discord")
+class Client:
+ """
+ The main Client class for the Python client. This class is used to connect to a remote Gradio app and call its API endpoints.
+
+ Example:
+ from gradio_client import Client
+
+ client = Client("abidlabs/whisper-large-v2") # connecting to a Hugging Face Space
+ client.predict("test.mp4", api_name="/predict")
+ >> What a nice recording! # returns the result of the remote API call
+
+ client = Client("https://bec81a83-5b5c-471e.gradio.live") # connecting to a temporary Gradio share URL
+ job = client.submit("hello", api_name="/predict") # runs the prediction in a background thread
+ job.result()
+ >> 49 # returns the result of the remote API call (blocking call)
+ """
+
+ def __init__(
+ self,
+ src: str,
+ hf_token: str | None = None,
+ max_workers: int = 40,
+ serialize: bool = True,
+ output_dir: str | Path = DEFAULT_TEMP_DIR,
+ verbose: bool = True,
+ auth: tuple[str, str] | None = None,
+ ):
+ """
+ Parameters:
+ src: Either the name of the Hugging Face Space to load, (e.g. "abidlabs/whisper-large-v2") or the full URL (including "http" or "https") of the hosted Gradio app to load (e.g. "http://mydomain.com/app" or "https://bec81a83-5b5c-471e.gradio.live/").
+ hf_token: The Hugging Face token to use to access private Spaces. Automatically fetched if you are logged in via the Hugging Face Hub CLI. Obtain from: https://huggingface.co/settings/token
+ max_workers: The maximum number of thread workers that can be used to make requests to the remote Gradio app simultaneously.
+ serialize: Whether the client should serialize the inputs and deserialize the outputs of the remote API. If set to False, the client will pass the inputs and outputs as-is, without serializing/deserializing them. E.g. you if you set this to False, you'd submit an image in base64 format instead of a filepath, and you'd get back an image in base64 format from the remote API instead of a filepath.
+ output_dir: The directory to save files that are downloaded from the remote API. If None, reads from the GRADIO_TEMP_DIR environment variable. Defaults to a temporary directory on your machine.
+ verbose: Whether the client should print statements to the console.
+ """
+ self.verbose = verbose
+ self.hf_token = hf_token
+ self.serialize = serialize
+ self.headers = build_hf_headers(
+ token=hf_token,
+ library_name="gradio_client",
+ library_version=utils.__version__,
+ )
+ self.space_id = None
+ self.cookies: dict[str, str] = {}
+ self.output_dir = (
+ str(output_dir) if isinstance(output_dir, Path) else output_dir
+ )
+
+ if src.startswith("http://") or src.startswith("https://"):
+ _src = src if src.endswith("/") else src + "/"
+ else:
+ _src = self._space_name_to_src(src)
+ if _src is None:
+ raise ValueError(
+ f"Could not find Space: {src}. If it is a private Space, please provide an hf_token."
+ )
+ self.space_id = src
+ self.src = _src
+ state = self._get_space_state()
+ if state == SpaceStage.BUILDING:
+ if self.verbose:
+ print("Space is still building. Please wait...")
+ while self._get_space_state() == SpaceStage.BUILDING:
+ time.sleep(2) # so we don't get rate limited by the API
+ pass
+ if state in utils.INVALID_RUNTIME:
+ raise ValueError(
+ f"The current space is in the invalid state: {state}. "
+ "Please contact the owner to fix this."
+ )
+ if self.verbose:
+ print(f"Loaded as API: {self.src} ✔")
+
+ if auth is not None:
+ self._login(auth)
+
+ self.config = self._get_config()
+ self.protocol: str = self.config.get("protocol", "ws")
+ self.api_url = urllib.parse.urljoin(self.src, utils.API_URL)
+ self.sse_url = urllib.parse.urljoin(
+ self.src, utils.SSE_URL_V0 if self.protocol == "sse" else utils.SSE_URL
+ )
+ self.sse_data_url = urllib.parse.urljoin(
+ self.src,
+ utils.SSE_DATA_URL_V0 if self.protocol == "sse" else utils.SSE_DATA_URL,
+ )
+ self.ws_url = urllib.parse.urljoin(
+ self.src.replace("http", "ws", 1), utils.WS_URL
+ )
+ self.upload_url = urllib.parse.urljoin(self.src, utils.UPLOAD_URL)
+ self.reset_url = urllib.parse.urljoin(self.src, utils.RESET_URL)
+ self.app_version = version.parse(self.config.get("version", "2.0"))
+ self._info = self._get_api_info()
+ self.session_hash = str(uuid.uuid4())
+
+ endpoint_class = (
+ Endpoint if self.protocol.startswith("sse") else EndpointV3Compatibility
+ )
+ self.endpoints = [
+ endpoint_class(self, fn_index, dependency, self.protocol)
+ for fn_index, dependency in enumerate(self.config["dependencies"])
+ ]
+
+ # Create a pool of threads to handle the requests
+ self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=max_workers)
+
+ # Disable telemetry by setting the env variable HF_HUB_DISABLE_TELEMETRY=1
+ threading.Thread(target=self._telemetry_thread).start()
+
+ self.stream_open = False
+ self.streaming_future: Future | None = None
+ self.pending_messages_per_event: dict[str, list[Message | None]] = {}
+ self.pending_event_ids: set[str] = set()
+
+ async def stream_messages(self) -> None:
+ try:
+ async with httpx.AsyncClient(timeout=httpx.Timeout(timeout=None)) as client:
+ async with client.stream(
+ "GET",
+ self.sse_url,
+ params={"session_hash": self.session_hash},
+ headers=self.headers,
+ cookies=self.cookies,
+ ) as response:
+ async for line in response.aiter_lines():
+ line = line.rstrip("\n")
+ if not len(line):
+ continue
+ if line.startswith("data:"):
+ resp = json.loads(line[5:])
+ if resp["msg"] == ServerMessage.heartbeat:
+ continue
+ elif resp["msg"] == ServerMessage.server_stopped:
+ for (
+ pending_messages
+ ) in self.pending_messages_per_event.values():
+ pending_messages.append(resp)
+ return
+ event_id = resp["event_id"]
+ if event_id not in self.pending_messages_per_event:
+ self.pending_messages_per_event[event_id] = []
+ self.pending_messages_per_event[event_id].append(resp)
+ if resp["msg"] == ServerMessage.process_completed:
+ self.pending_event_ids.remove(event_id)
+ if len(self.pending_event_ids) == 0:
+ self.stream_open = False
+ return
+ else:
+ raise ValueError(f"Unexpected SSE line: '{line}'")
+ except BaseException as e:
+ import traceback
+
+ traceback.print_exc()
+ raise e
+
+ async def send_data(self, data, hash_data):
+ async with httpx.AsyncClient() as client:
+ req = await client.post(
+ self.sse_data_url,
+ json={**data, **hash_data},
+ headers=self.headers,
+ cookies=self.cookies,
+ )
+ if req.status_code == 503:
+ raise QueueError("Queue is full! Please try again.")
+ req.raise_for_status()
+ resp = req.json()
+ event_id = resp["event_id"]
+
+ if not self.stream_open:
+ self.stream_open = True
+
+ def open_stream():
+ return utils.synchronize_async(self.stream_messages)
+
+ def close_stream(_):
+ self.stream_open = False
+ for _, pending_messages in self.pending_messages_per_event.items():
+ pending_messages.append(None)
+
+ if self.streaming_future is None or self.streaming_future.done():
+ self.streaming_future = self.executor.submit(open_stream)
+ self.streaming_future.add_done_callback(close_stream)
+
+ return event_id
+
+ @classmethod
+ def duplicate(
+ cls,
+ from_id: str,
+ to_id: str | None = None,
+ hf_token: str | None = None,
+ private: bool = True,
+ hardware: Literal[
+ "cpu-basic",
+ "cpu-upgrade",
+ "t4-small",
+ "t4-medium",
+ "a10g-small",
+ "a10g-large",
+ "a100-large",
+ ]
+ | SpaceHardware
+ | None = None,
+ secrets: dict[str, str] | None = None,
+ sleep_timeout: int = 5,
+ max_workers: int = 40,
+ verbose: bool = True,
+ ):
+ """
+ Duplicates a Hugging Face Space under your account and returns a Client object
+ for the new Space. No duplication is created if the Space already exists in your
+ account (to override this, provide a new name for the new Space using `to_id`).
+ To use this method, you must provide an `hf_token` or be logged in via the Hugging
+ Face Hub CLI.
+
+ The new Space will be private by default and use the same hardware as the original
+ Space. This can be changed by using the `private` and `hardware` parameters. For
+ hardware upgrades (beyond the basic CPU tier), you may be required to provide
+ billing information on Hugging Face: https://huggingface.co/settings/billing
+
+ Parameters:
+ from_id: The name of the Hugging Face Space to duplicate in the format "{username}/{space_id}", e.g. "gradio/whisper".
+ to_id: The name of the new Hugging Face Space to create, e.g. "abidlabs/whisper-duplicate". If not provided, the new Space will be named "{your_HF_username}/{space_id}".
+ hf_token: The Hugging Face token to use to access private Spaces. Automatically fetched if you are logged in via the Hugging Face Hub CLI. Obtain from: https://huggingface.co/settings/token
+ private: Whether the new Space should be private (True) or public (False). Defaults to True.
+ hardware: The hardware tier to use for the new Space. Defaults to the same hardware tier as the original Space. Options include "cpu-basic", "cpu-upgrade", "t4-small", "t4-medium", "a10g-small", "a10g-large", "a100-large", subject to availability.
+ secrets: A dictionary of (secret key, secret value) to pass to the new Space. Defaults to None. Secrets are only used when the Space is duplicated for the first time, and are not updated if the duplicated Space already exists.
+ sleep_timeout: The number of minutes after which the duplicate Space will be puased if no requests are made to it (to minimize billing charges). Defaults to 5 minutes.
+ max_workers: The maximum number of thread workers that can be used to make requests to the remote Gradio app simultaneously.
+ verbose: Whether the client should print statements to the console.
+ Example:
+ import os
+ from gradio_client import Client
+ HF_TOKEN = os.environ.get("HF_TOKEN")
+ client = Client.duplicate("abidlabs/whisper", hf_token=HF_TOKEN)
+ client.predict("audio_sample.wav")
+ >> "This is a test of the whisper speech recognition model."
+ """
+ try:
+ original_info = huggingface_hub.get_space_runtime(from_id, token=hf_token)
+ except RepositoryNotFoundError as rnfe:
+ raise ValueError(
+ f"Could not find Space: {from_id}. If it is a private Space, please provide an `hf_token`."
+ ) from rnfe
+ if to_id:
+ if "/" in to_id:
+ to_id = to_id.split("/")[1]
+ space_id = huggingface_hub.get_full_repo_name(to_id, token=hf_token)
+ else:
+ space_id = huggingface_hub.get_full_repo_name(
+ from_id.split("/")[1], token=hf_token
+ )
+ try:
+ huggingface_hub.get_space_runtime(space_id, token=hf_token)
+ if verbose:
+ print(
+ f"Using your existing Space: {utils.SPACE_URL.format(space_id)} 🤗"
+ )
+ if secrets is not None:
+ warnings.warn(
+ "Secrets are only used when the Space is duplicated for the first time, and are not updated if the duplicated Space already exists."
+ )
+ except RepositoryNotFoundError:
+ if verbose:
+ print(f"Creating a duplicate of {from_id} for your own use... 🤗")
+ huggingface_hub.duplicate_space(
+ from_id=from_id,
+ to_id=space_id,
+ token=hf_token,
+ exist_ok=True,
+ private=private,
+ )
+ if secrets is not None:
+ for key, value in secrets.items():
+ huggingface_hub.add_space_secret(
+ space_id, key, value, token=hf_token
+ )
+ if verbose:
+ print(f"Created new Space: {utils.SPACE_URL.format(space_id)}")
+ current_info = huggingface_hub.get_space_runtime(space_id, token=hf_token)
+ current_hardware = (
+ current_info.hardware or huggingface_hub.SpaceHardware.CPU_BASIC
+ )
+ hardware = hardware or original_info.hardware
+ if current_hardware != hardware:
+ huggingface_hub.request_space_hardware(space_id, hardware, token=hf_token) # type: ignore
+ print(
+ f"-------\nNOTE: this Space uses upgraded hardware: {hardware}... see billing info at https://huggingface.co/settings/billing\n-------"
+ )
+ # Setting a timeout only works if the hardware is not basic
+ # so set it here after the hardware has been requested
+ if hardware != huggingface_hub.SpaceHardware.CPU_BASIC:
+ utils.set_space_timeout(
+ space_id, hf_token=hf_token, timeout_in_seconds=sleep_timeout * 60
+ )
+ if verbose:
+ print("")
+ client = cls(
+ space_id, hf_token=hf_token, max_workers=max_workers, verbose=verbose
+ )
+ return client
+
+ def _get_space_state(self):
+ if not self.space_id:
+ return None
+ info = huggingface_hub.get_space_runtime(self.space_id, token=self.hf_token)
+ return info.stage
+
+ def predict(
+ self,
+ *args,
+ api_name: str | None = None,
+ fn_index: int | None = None,
+ ) -> Any:
+ """
+ Calls the Gradio API and returns the result (this is a blocking call).
+
+ Parameters:
+ args: The arguments to pass to the remote API. The order of the arguments must match the order of the inputs in the Gradio app.
+ api_name: The name of the API endpoint to call starting with a leading slash, e.g. "/predict". Does not need to be provided if the Gradio app has only one named API endpoint.
+ fn_index: As an alternative to api_name, this parameter takes the index of the API endpoint to call, e.g. 0. Both api_name and fn_index can be provided, but if they conflict, api_name will take precedence.
+ Returns:
+ The result of the API call. Will be a Tuple if the API has multiple outputs.
+ Example:
+ from gradio_client import Client
+ client = Client(src="gradio/calculator")
+ client.predict(5, "add", 4, api_name="/predict")
+ >> 9.0
+ """
+ inferred_fn_index = self._infer_fn_index(api_name, fn_index)
+ if self.endpoints[inferred_fn_index].is_continuous:
+ raise ValueError(
+ "Cannot call predict on this function as it may run forever. Use submit instead."
+ )
+ return self.submit(*args, api_name=api_name, fn_index=fn_index).result()
+
+ def new_helper(self, fn_index: int) -> Communicator:
+ return Communicator(
+ Lock(),
+ JobStatus(),
+ self.endpoints[fn_index].process_predictions,
+ self.reset_url,
+ )
+
+ def submit(
+ self,
+ *args,
+ api_name: str | None = None,
+ fn_index: int | None = None,
+ result_callbacks: Callable | list[Callable] | None = None,
+ ) -> Job:
+ """
+ Creates and returns a Job object which calls the Gradio API in a background thread. The job can be used to retrieve the status and result of the remote API call.
+
+ Parameters:
+ args: The arguments to pass to the remote API. The order of the arguments must match the order of the inputs in the Gradio app.
+ api_name: The name of the API endpoint to call starting with a leading slash, e.g. "/predict". Does not need to be provided if the Gradio app has only one named API endpoint.
+ fn_index: As an alternative to api_name, this parameter takes the index of the API endpoint to call, e.g. 0. Both api_name and fn_index can be provided, but if they conflict, api_name will take precedence.
+ result_callbacks: A callback function, or list of callback functions, to be called when the result is ready. If a list of functions is provided, they will be called in order. The return values from the remote API are provided as separate parameters into the callback. If None, no callback will be called.
+ Returns:
+ A Job object that can be used to retrieve the status and result of the remote API call.
+ Example:
+ from gradio_client import Client
+ client = Client(src="gradio/calculator")
+ job = client.submit(5, "add", 4, api_name="/predict")
+ job.status()
+ >>
+ job.result() # blocking call
+ >> 9.0
+ """
+ inferred_fn_index = self._infer_fn_index(api_name, fn_index)
+
+ helper = None
+ if self.endpoints[inferred_fn_index].protocol in ("ws", "sse", "sse_v1"):
+ helper = self.new_helper(inferred_fn_index)
+ end_to_end_fn = self.endpoints[inferred_fn_index].make_end_to_end_fn(helper)
+ future = self.executor.submit(end_to_end_fn, *args)
+
+ job = Job(
+ future, communicator=helper, verbose=self.verbose, space_id=self.space_id
+ )
+
+ if result_callbacks:
+ if isinstance(result_callbacks, Callable):
+ result_callbacks = [result_callbacks]
+
+ def create_fn(callback) -> Callable:
+ def fn(future):
+ if isinstance(future.result(), tuple):
+ callback(*future.result())
+ else:
+ callback(future.result())
+
+ return fn
+
+ for callback in result_callbacks:
+ job.add_done_callback(create_fn(callback))
+
+ return job
+
+ def _get_api_info(self):
+ if self.serialize:
+ api_info_url = urllib.parse.urljoin(self.src, utils.API_INFO_URL)
+ else:
+ api_info_url = urllib.parse.urljoin(self.src, utils.RAW_API_INFO_URL)
+
+ if self.app_version > version.Version("3.36.1"):
+ r = httpx.get(api_info_url, headers=self.headers, cookies=self.cookies)
+ if r.is_success:
+ info = r.json()
+ else:
+ raise ValueError(f"Could not fetch api info for {self.src}: {r.text}")
+ else:
+ fetch = httpx.post(
+ utils.SPACE_FETCHER_URL,
+ json={"config": json.dumps(self.config), "serialize": self.serialize},
+ )
+ if fetch.is_success:
+ info = fetch.json()["api"]
+ else:
+ raise ValueError(
+ f"Could not fetch api info for {self.src}: {fetch.text}"
+ )
+
+ return info
+
+ def view_api(
+ self,
+ all_endpoints: bool | None = None,
+ print_info: bool = True,
+ return_format: Literal["dict", "str"] | None = None,
+ ) -> dict | str | None:
+ """
+ Prints the usage info for the API. If the Gradio app has multiple API endpoints, the usage info for each endpoint will be printed separately. If return_format="dict" the info is returned in dictionary format, as shown in the example below.
+
+ Parameters:
+ all_endpoints: If True, prints information for both named and unnamed endpoints in the Gradio app. If False, will only print info about named endpoints. If None (default), will print info about named endpoints, unless there aren't any -- in which it will print info about unnamed endpoints.
+ print_info: If True, prints the usage info to the console. If False, does not print the usage info.
+ return_format: If None, nothing is returned. If "str", returns the same string that would be printed to the console. If "dict", returns the usage info as a dictionary that can be programmatically parsed, and *all endpoints are returned in the dictionary* regardless of the value of `all_endpoints`. The format of the dictionary is in the docstring of this method.
+ Example:
+ from gradio_client import Client
+ client = Client(src="gradio/calculator")
+ client.view_api(return_format="dict")
+ >> {
+ 'named_endpoints': {
+ '/predict': {
+ 'parameters': [
+ {
+ 'label': 'num1',
+ 'type_python': 'int | float',
+ 'type_description': 'numeric value',
+ 'component': 'Number',
+ 'example_input': '5'
+ },
+ {
+ 'label': 'operation',
+ 'type_python': 'str',
+ 'type_description': 'string value',
+ 'component': 'Radio',
+ 'example_input': 'add'
+ },
+ {
+ 'label': 'num2',
+ 'type_python': 'int | float',
+ 'type_description': 'numeric value',
+ 'component': 'Number',
+ 'example_input': '5'
+ },
+ ],
+ 'returns': [
+ {
+ 'label': 'output',
+ 'type_python': 'int | float',
+ 'type_description': 'numeric value',
+ 'component': 'Number',
+ },
+ ]
+ },
+ '/flag': {
+ 'parameters': [
+ ...
+ ],
+ 'returns': [
+ ...
+ ]
+ }
+ }
+ 'unnamed_endpoints': {
+ 2: {
+ 'parameters': [
+ ...
+ ],
+ 'returns': [
+ ...
+ ]
+ }
+ }
+ }
+ }
+
+ """
+ num_named_endpoints = len(self._info["named_endpoints"])
+ num_unnamed_endpoints = len(self._info["unnamed_endpoints"])
+ if num_named_endpoints == 0 and all_endpoints is None:
+ all_endpoints = True
+
+ human_info = "Client.predict() Usage Info\n---------------------------\n"
+ human_info += f"Named API endpoints: {num_named_endpoints}\n"
+
+ for api_name, endpoint_info in self._info["named_endpoints"].items():
+ human_info += self._render_endpoints_info(api_name, endpoint_info)
+
+ if all_endpoints:
+ human_info += f"\nUnnamed API endpoints: {num_unnamed_endpoints}\n"
+ for fn_index, endpoint_info in self._info["unnamed_endpoints"].items():
+ # When loading from json, the fn_indices are read as strings
+ # because json keys can only be strings
+ human_info += self._render_endpoints_info(int(fn_index), endpoint_info)
+ else:
+ if num_unnamed_endpoints > 0:
+ human_info += f"\nUnnamed API endpoints: {num_unnamed_endpoints}, to view, run Client.view_api(all_endpoints=True)\n"
+
+ if print_info:
+ print(human_info)
+ if return_format == "str":
+ return human_info
+ elif return_format == "dict":
+ return self._info
+
+ def reset_session(self) -> None:
+ self.session_hash = str(uuid.uuid4())
+
+ def _render_endpoints_info(
+ self,
+ name_or_index: str | int,
+ endpoints_info: dict[str, list[dict[str, Any]]],
+ ) -> str:
+ parameter_names = [p["label"] for p in endpoints_info["parameters"]]
+ parameter_names = [utils.sanitize_parameter_names(p) for p in parameter_names]
+ rendered_parameters = ", ".join(parameter_names)
+ if rendered_parameters:
+ rendered_parameters = rendered_parameters + ", "
+ return_values = [p["label"] for p in endpoints_info["returns"]]
+ return_values = [utils.sanitize_parameter_names(r) for r in return_values]
+ rendered_return_values = ", ".join(return_values)
+ if len(return_values) > 1:
+ rendered_return_values = f"({rendered_return_values})"
+
+ if isinstance(name_or_index, str):
+ final_param = f'api_name="{name_or_index}"'
+ elif isinstance(name_or_index, int):
+ final_param = f"fn_index={name_or_index}"
+ else:
+ raise ValueError("name_or_index must be a string or integer")
+
+ human_info = f"\n - predict({rendered_parameters}{final_param}) -> {rendered_return_values}\n"
+ human_info += " Parameters:\n"
+ if endpoints_info["parameters"]:
+ for info in endpoints_info["parameters"]:
+ desc = (
+ f" ({info['python_type']['description']})"
+ if info["python_type"].get("description")
+ else ""
+ )
+ type_ = info["python_type"]["type"]
+ human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {type_}{desc} \n"
+ else:
+ human_info += " - None\n"
+ human_info += " Returns:\n"
+ if endpoints_info["returns"]:
+ for info in endpoints_info["returns"]:
+ desc = (
+ f" ({info['python_type']['description']})"
+ if info["python_type"].get("description")
+ else ""
+ )
+ type_ = info["python_type"]["type"]
+ human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {type_}{desc} \n"
+ else:
+ human_info += " - None\n"
+
+ return human_info
+
+ def __repr__(self):
+ return self.view_api(print_info=False, return_format="str")
+
+ def __str__(self):
+ return self.view_api(print_info=False, return_format="str")
+
+ def _telemetry_thread(self) -> None:
+ # Disable telemetry by setting the env variable HF_HUB_DISABLE_TELEMETRY=1
+ data = {
+ "src": self.src,
+ }
+ try:
+ send_telemetry(
+ topic="py_client/initiated",
+ library_name="gradio_client",
+ library_version=utils.__version__,
+ user_agent=data,
+ )
+ except Exception:
+ pass
+
+ def _infer_fn_index(self, api_name: str | None, fn_index: int | None) -> int:
+ inferred_fn_index = None
+ if api_name is not None:
+ for i, d in enumerate(self.config["dependencies"]):
+ config_api_name = d.get("api_name")
+ if config_api_name is None or config_api_name is False:
+ continue
+ if "/" + config_api_name == api_name:
+ inferred_fn_index = i
+ break
+ else:
+ error_message = f"Cannot find a function with `api_name`: {api_name}."
+ if not api_name.startswith("/"):
+ error_message += " Did you mean to use a leading slash?"
+ raise ValueError(error_message)
+ elif fn_index is not None:
+ inferred_fn_index = fn_index
+ if (
+ inferred_fn_index >= len(self.endpoints)
+ or not self.endpoints[inferred_fn_index].is_valid
+ ):
+ raise ValueError(f"Invalid function index: {fn_index}.")
+ else:
+ valid_endpoints = [
+ e
+ for e in self.endpoints
+ if e.is_valid
+ and e.api_name is not None
+ and e.backend_fn is not None
+ and e.show_api
+ ]
+ if len(valid_endpoints) == 1:
+ inferred_fn_index = valid_endpoints[0].fn_index
+ else:
+ raise ValueError(
+ "This Gradio app might have multiple endpoints. Please specify an `api_name` or `fn_index`"
+ )
+ return inferred_fn_index
+
+ def __del__(self):
+ if hasattr(self, "executor"):
+ self.executor.shutdown(wait=True)
+
+ def _space_name_to_src(self, space) -> str | None:
+ return huggingface_hub.space_info(space, token=self.hf_token).host # type: ignore
+
+ def _login(self, auth: tuple[str, str]):
+ resp = httpx.post(
+ urllib.parse.urljoin(self.src, utils.LOGIN_URL),
+ data={"username": auth[0], "password": auth[1]},
+ )
+ if not resp.is_success:
+ raise ValueError(f"Could not login to {self.src}")
+ self.cookies = {
+ name: value for name, value in resp.cookies.items() if value is not None
+ }
+
+ def _get_config(self) -> dict:
+ r = httpx.get(
+ urllib.parse.urljoin(self.src, utils.CONFIG_URL),
+ headers=self.headers,
+ cookies=self.cookies,
+ )
+ if r.is_success:
+ return r.json()
+ elif r.status_code == 401:
+ raise ValueError(f"Could not load {self.src}. Please login.")
+ else: # to support older versions of Gradio
+ r = httpx.get(self.src, headers=self.headers, cookies=self.cookies)
+ if not r.is_success:
+ raise ValueError(f"Could not fetch config for {self.src}")
+ # some basic regex to extract the config
+ result = re.search(r"window.gradio_config = (.*?);[\s]*", r.text)
+ try:
+ config = json.loads(result.group(1)) # type: ignore
+ except AttributeError as ae:
+ raise ValueError(
+ f"Could not get Gradio config from: {self.src}"
+ ) from ae
+ if "allow_flagging" in config:
+ raise ValueError(
+ "Gradio 2.x is not supported by this client. Please upgrade your Gradio app to Gradio 3.x or higher."
+ )
+ return config
+
+ def deploy_discord(
+ self,
+ discord_bot_token: str | None = None,
+ api_names: list[str | tuple[str, str]] | None = None,
+ to_id: str | None = None,
+ hf_token: str | None = None,
+ private: bool = False,
+ ):
+ """
+ Deploy the upstream app as a discord bot. Currently only supports gr.ChatInterface.
+ Parameters:
+ discord_bot_token: This is the "password" needed to be able to launch the bot. Users can get a token by creating a bot app on the discord website. If run the method without specifying a token, the space will explain how to get one. See here: https://huggingface.co/spaces/freddyaboulton/test-discord-bot-v1.
+ api_names: The api_names of the app to turn into bot commands. This parameter currently has no effect as ChatInterface only has one api_name ('/chat').
+ to_id: The name of the space hosting the discord bot. If None, the name will be gradio-discord-bot-{random-substring}
+ hf_token: HF api token with write priviledges in order to upload the files to HF space. Can be ommitted if logged in via the HuggingFace CLI, unless the upstream space is private. Obtain from: https://huggingface.co/settings/token
+ private: Whether the space hosting the discord bot is private. The visibility of the discord bot itself is set via the discord website. See https://huggingface.co/spaces/freddyaboulton/test-discord-bot-v1
+ """
+
+ if self.config["mode"] == "chat_interface" and not api_names:
+ api_names = [("chat", "chat")]
+
+ valid_list = isinstance(api_names, list) and (
+ isinstance(n, str)
+ or (
+ isinstance(n, tuple) and isinstance(n[0], str) and isinstance(n[1], str)
+ )
+ for n in api_names
+ )
+ if api_names is None or not valid_list:
+ raise ValueError(
+ f"Each entry in api_names must be either a string or a tuple of strings. Received {api_names}"
+ )
+ if len(api_names) != 1:
+ raise ValueError("Currently only one api_name can be deployed to discord.")
+
+ for i, name in enumerate(api_names):
+ if isinstance(name, str):
+ api_names[i] = (name, name)
+
+ fn = next(
+ (ep for ep in self.endpoints if ep.api_name == f"/{api_names[0][0]}"), None
+ )
+ if not fn:
+ raise ValueError(
+ f"api_name {api_names[0][0]} not present in {self.space_id or self.src}"
+ )
+ inputs = [inp for inp in fn.input_component_types if not inp.skip]
+ outputs = [inp for inp in fn.input_component_types if not inp.skip]
+ if not inputs == ["textbox"] and outputs == ["textbox"]:
+ raise ValueError(
+ "Currently only api_names with a single textbox as input and output are supported. "
+ f"Received {inputs} and {outputs}"
+ )
+
+ is_private = False
+ if self.space_id:
+ is_private = huggingface_hub.space_info(self.space_id).private
+ if is_private and not hf_token:
+ raise ValueError(
+ f"Since {self.space_id} is private, you must explicitly pass in hf_token "
+ "so that it can be added as a secret in the discord bot space."
+ )
+
+ if to_id:
+ if "/" in to_id:
+ to_id = to_id.split("/")[1]
+ space_id = huggingface_hub.get_full_repo_name(to_id, token=hf_token)
+ else:
+ if self.space_id:
+ space_id = f'{self.space_id.split("/")[1]}-gradio-discord-bot'
+ else:
+ space_id = f"gradio-discord-bot-{secrets.token_hex(4)}"
+ space_id = huggingface_hub.get_full_repo_name(space_id, token=hf_token)
+
+ api = huggingface_hub.HfApi()
+
+ try:
+ huggingface_hub.space_info(space_id)
+ first_upload = False
+ except huggingface_hub.utils.RepositoryNotFoundError:
+ first_upload = True
+
+ huggingface_hub.create_repo(
+ space_id,
+ repo_type="space",
+ space_sdk="gradio",
+ token=hf_token,
+ exist_ok=True,
+ private=private,
+ )
+ if first_upload:
+ huggingface_hub.metadata_update(
+ repo_id=space_id,
+ repo_type="space",
+ metadata={"tags": ["gradio-discord-bot"]},
+ )
+
+ with open(
+ str(Path(__file__).parent / "templates" / "discord_chat.py"),
+ encoding="utf-8",
+ ) as f:
+ app = f.read()
+ app = app.replace("<>", self.src)
+ app = app.replace("<>", api_names[0][0])
+ app = app.replace("<>", api_names[0][1])
+
+ with tempfile.NamedTemporaryFile(
+ mode="w", delete=False, encoding="utf-8"
+ ) as app_file:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as requirements:
+ app_file.write(app)
+ requirements.write("\n".join(["discord.py==2.3.1"]))
+
+ operations = [
+ CommitOperationAdd(path_in_repo="app.py", path_or_fileobj=app_file.name),
+ CommitOperationAdd(
+ path_in_repo="requirements.txt", path_or_fileobj=requirements.name
+ ),
+ ]
+
+ api.create_commit(
+ repo_id=space_id,
+ commit_message="Deploy Discord Bot",
+ repo_type="space",
+ operations=operations,
+ token=hf_token,
+ )
+
+ if discord_bot_token:
+ huggingface_hub.add_space_secret(
+ space_id, "DISCORD_TOKEN", discord_bot_token, token=hf_token
+ )
+ if is_private:
+ huggingface_hub.add_space_secret(
+ space_id,
+ "HF_TOKEN",
+ hf_token, # type: ignore
+ token=hf_token,
+ )
+
+ url = f"https://huggingface.co/spaces/{space_id}"
+ print(f"See your discord bot here! {url}")
+ return url
+
+
+@dataclass
+class ComponentApiType:
+ skip: bool
+ value_is_file: bool
+ is_state: bool
+
+
+@dataclass
+class ReplaceMe:
+ index: int
+
+
+class Endpoint:
+ """Helper class for storing all the information about a single API endpoint."""
+
+ def __init__(
+ self, client: Client, fn_index: int, dependency: dict, protocol: str = "sse_v1"
+ ):
+ self.client: Client = client
+ self.fn_index = fn_index
+ self.dependency = dependency
+ api_name = dependency.get("api_name")
+ self.api_name: str | Literal[False] | None = (
+ "/" + api_name if isinstance(api_name, str) else api_name
+ )
+ self.protocol = protocol
+ self.input_component_types = [
+ self._get_component_type(id_) for id_ in dependency["inputs"]
+ ]
+ self.output_component_types = [
+ self._get_component_type(id_) for id_ in dependency["outputs"]
+ ]
+ self.root_url = client.src + "/" if not client.src.endswith("/") else client.src
+ self.is_continuous = dependency.get("types", {}).get("continuous", False)
+ self.download_file = lambda d: self._download_file(
+ d,
+ save_dir=self.client.output_dir,
+ hf_token=self.client.hf_token,
+ root_url=self.root_url,
+ )
+ # Disallow hitting endpoints that the Gradio app has disabled
+ self.is_valid = self.api_name is not False
+ self.backend_fn = dependency.get("backend_fn")
+ self.show_api = dependency.get("show_api")
+
+ def _get_component_type(self, component_id: int):
+ component = next(
+ i for i in self.client.config["components"] if i["id"] == component_id
+ )
+ skip_api = component.get("skip_api", component["type"] in utils.SKIP_COMPONENTS)
+ return ComponentApiType(
+ skip_api,
+ self.value_is_file(component),
+ component["type"] == "state",
+ )
+
+ @staticmethod
+ def value_is_file(component: dict) -> bool:
+ # Hacky for now
+ if "api_info" not in component:
+ return False
+ return utils.value_is_file(component["api_info"])
+
+ def __repr__(self):
+ return f"Endpoint src: {self.client.src}, api_name: {self.api_name}, fn_index: {self.fn_index}"
+
+ def __str__(self):
+ return self.__repr__()
+
+ def make_end_to_end_fn(self, helper: Communicator | None = None):
+ _predict = self.make_predict(helper)
+
+ def _inner(*data):
+ if not self.is_valid:
+ raise utils.InvalidAPIEndpointError()
+ data = self.insert_state(*data)
+ if self.client.serialize:
+ data = self.serialize(*data)
+ predictions = _predict(*data)
+ predictions = self.process_predictions(*predictions)
+ # Append final output only if not already present
+ # for consistency between generators and not generators
+ if helper:
+ with helper.lock:
+ if not helper.job.outputs:
+ helper.job.outputs.append(predictions)
+ return predictions
+
+ return _inner
+
+ def make_predict(self, helper: Communicator | None = None):
+ def _predict(*data) -> tuple:
+ data = {
+ "data": data,
+ "fn_index": self.fn_index,
+ "session_hash": self.client.session_hash,
+ }
+
+ hash_data = {
+ "fn_index": self.fn_index,
+ "session_hash": self.client.session_hash,
+ }
+
+ if self.protocol == "sse":
+ result = utils.synchronize_async(
+ self._sse_fn_v0, data, hash_data, helper
+ )
+ elif self.protocol == "sse_v1":
+ event_id = utils.synchronize_async(
+ self.client.send_data, data, hash_data
+ )
+ self.client.pending_event_ids.add(event_id)
+ self.client.pending_messages_per_event[event_id] = []
+ result = utils.synchronize_async(self._sse_fn_v1, helper, event_id)
+ else:
+ raise ValueError(f"Unsupported protocol: {self.protocol}")
+
+ if "error" in result:
+ raise ValueError(result["error"])
+
+ try:
+ output = result["data"]
+ except KeyError as ke:
+ is_public_space = (
+ self.client.space_id
+ and not huggingface_hub.space_info(self.client.space_id).private
+ )
+ if "error" in result and "429" in result["error"] and is_public_space:
+ raise utils.TooManyRequestsError(
+ f"Too many requests to the API, please try again later. To avoid being rate-limited, "
+ f"please duplicate the Space using Client.duplicate({self.client.space_id}) "
+ f"and pass in your Hugging Face token."
+ ) from None
+ elif "error" in result:
+ raise ValueError(result["error"]) from None
+ raise KeyError(
+ f"Could not find 'data' key in response. Response received: {result}"
+ ) from ke
+ return tuple(output)
+
+ return _predict
+
+ def _predict_resolve(self, *data) -> Any:
+ """Needed for gradio.load(), which has a slightly different signature for serializing/deserializing"""
+ outputs = self.make_predict()(*data)
+ if len(self.dependency["outputs"]) == 1:
+ return outputs[0]
+ return outputs
+
+ def _upload(
+ self, file_paths: list[str | list[str]]
+ ) -> list[str | list[str]] | list[dict[str, Any] | list[dict[str, Any]]]:
+ if not file_paths:
+ return []
+ # Put all the filepaths in one file
+ # but then keep track of which index in the
+ # original list they came from so we can recreate
+ # the original structure
+ files = []
+ indices = []
+ for i, fs in enumerate(file_paths):
+ if not isinstance(fs, list):
+ fs = [fs]
+ for f in fs:
+ files.append(("files", (Path(f).name, open(f, "rb")))) # noqa: SIM115
+ indices.append(i)
+ r = httpx.post(self.client.upload_url, headers=self.client.headers, files=files)
+ if r.status_code != 200:
+ uploaded = file_paths
+ else:
+ uploaded = []
+ result = r.json()
+ for i, fs in enumerate(file_paths):
+ if isinstance(fs, list):
+ output = [o for ix, o in enumerate(result) if indices[ix] == i]
+ res = [
+ {
+ "path": o,
+ "orig_name": Path(f).name,
+ }
+ for f, o in zip(fs, output)
+ ]
+ else:
+ o = next(o for ix, o in enumerate(result) if indices[ix] == i)
+ res = {
+ "path": o,
+ "orig_name": Path(fs).name,
+ }
+ uploaded.append(res)
+ return uploaded
+
+ def insert_state(self, *data) -> tuple:
+ data = list(data)
+ for i, input_component_type in enumerate(self.input_component_types):
+ if input_component_type.is_state:
+ data.insert(i, None)
+ return tuple(data)
+
+ def remove_skipped_components(self, *data) -> tuple:
+ data = [d for d, oct in zip(data, self.output_component_types) if not oct.skip]
+ return tuple(data)
+
+ def reduce_singleton_output(self, *data) -> Any:
+ if len([oct for oct in self.output_component_types if not oct.skip]) == 1:
+ return data[0]
+ else:
+ return data
+
+ def _gather_files(self, *data):
+ file_list = []
+
+ def get_file(d):
+ if utils.is_file_obj(d):
+ file_list.append(d["path"])
+ else:
+ file_list.append(d)
+ return ReplaceMe(len(file_list) - 1)
+
+ new_data = []
+ for i, d in enumerate(data):
+ if self.input_component_types[i].value_is_file:
+ # Check file dicts and filepaths to upload
+ # file dict is a corner case but still needed for completeness
+ # most users should be using filepaths
+ d = utils.traverse(
+ d, get_file, lambda s: utils.is_file_obj(s) or utils.is_filepath(s)
+ )
+ new_data.append(d)
+ return file_list, new_data
+
+ def _add_uploaded_files_to_data(self, data: list[Any], files: list[Any]):
+ def replace(d: ReplaceMe) -> dict:
+ return files[d.index]
+
+ new_data = []
+ for d in data:
+ d = utils.traverse(
+ d, replace, is_root=lambda node: isinstance(node, ReplaceMe)
+ )
+ new_data.append(d)
+ return new_data
+
+ def serialize(self, *data) -> tuple:
+ files, new_data = self._gather_files(*data)
+ uploaded_files = self._upload(files)
+ data = list(new_data)
+ data = self._add_uploaded_files_to_data(data, uploaded_files)
+ data = utils.traverse(
+ data,
+ lambda s: {"path": s},
+ utils.is_url,
+ )
+ o = tuple(data)
+ return o
+
+ @staticmethod
+ def _download_file(
+ x: dict,
+ save_dir: str,
+ root_url: str,
+ hf_token: str | None = None,
+ ) -> str | None:
+ if x is None:
+ return None
+ if isinstance(x, str):
+ file_name = utils.decode_base64_to_file(x, dir=save_dir).name
+ elif isinstance(x, dict):
+ filepath = x.get("path")
+ assert filepath is not None, f"The 'path' field is missing in {x}"
+ file_name = utils.download_file(
+ root_url + "file=" + filepath,
+ hf_token=hf_token,
+ dir=save_dir,
+ )
+
+ else:
+ raise ValueError(
+ f"A FileSerializable component can only deserialize a string or a dict, not a {type(x)}: {x}"
+ )
+ return file_name
+
+ def deserialize(self, *data) -> tuple:
+ data_ = list(data)
+
+ data_: list[Any] = utils.traverse(data_, self.download_file, utils.is_file_obj)
+ return tuple(data_)
+
+ def process_predictions(self, *predictions):
+ predictions = self.deserialize(*predictions)
+ predictions = self.remove_skipped_components(*predictions)
+ predictions = self.reduce_singleton_output(*predictions)
+ return predictions
+
+ async def _sse_fn_v0(self, data: dict, hash_data: dict, helper: Communicator):
+ async with httpx.AsyncClient(timeout=httpx.Timeout(timeout=None)) as client:
+ return await utils.get_pred_from_sse_v0(
+ client,
+ data,
+ hash_data,
+ helper,
+ self.client.sse_url,
+ self.client.sse_data_url,
+ self.client.headers,
+ self.client.cookies,
+ )
+
+ async def _sse_fn_v1(self, helper: Communicator, event_id: str):
+ return await utils.get_pred_from_sse_v1(
+ helper,
+ self.client.headers,
+ self.client.cookies,
+ self.client.pending_messages_per_event,
+ event_id,
+ )
+
+
+class EndpointV3Compatibility:
+ """Endpoint class for connecting to v3 endpoints. Backwards compatibility."""
+
+ def __init__(self, client: Client, fn_index: int, dependency: dict, *args):
+ self.client: Client = client
+ self.fn_index = fn_index
+ self.dependency = dependency
+ api_name = dependency.get("api_name")
+ self.api_name: str | Literal[False] | None = (
+ "/" + api_name if isinstance(api_name, str) else api_name
+ )
+ self.use_ws = self._use_websocket(self.dependency)
+ self.protocol = "ws" if self.use_ws else "http"
+ self.input_component_types = []
+ self.output_component_types = []
+ self.root_url = client.src + "/" if not client.src.endswith("/") else client.src
+ self.is_continuous = dependency.get("types", {}).get("continuous", False)
+ try:
+ # Only a real API endpoint if backend_fn is True (so not just a frontend function), serializers are valid,
+ # and api_name is not False (meaning that the developer has explicitly disabled the API endpoint)
+ self.serializers, self.deserializers = self._setup_serializers()
+ self.is_valid = self.dependency["backend_fn"] and self.api_name is not False
+ except SerializationSetupError:
+ self.is_valid = False
+ self.backend_fn = dependency.get("backend_fn")
+ self.show_api = True
+
+ def __repr__(self):
+ return f"Endpoint src: {self.client.src}, api_name: {self.api_name}, fn_index: {self.fn_index}"
+
+ def __str__(self):
+ return self.__repr__()
+
+ def make_end_to_end_fn(self, helper: Communicator | None = None):
+ _predict = self.make_predict(helper)
+
+ def _inner(*data):
+ if not self.is_valid:
+ raise utils.InvalidAPIEndpointError()
+ data = self.insert_state(*data)
+ if self.client.serialize:
+ data = self.serialize(*data)
+ predictions = _predict(*data)
+ predictions = self.process_predictions(*predictions)
+ # Append final output only if not already present
+ # for consistency between generators and not generators
+ if helper:
+ with helper.lock:
+ if not helper.job.outputs:
+ helper.job.outputs.append(predictions)
+ return predictions
+
+ return _inner
+
+ def make_predict(self, helper: Communicator | None = None):
+ def _predict(*data) -> tuple:
+ data = json.dumps(
+ {
+ "data": data,
+ "fn_index": self.fn_index,
+ "session_hash": self.client.session_hash,
+ }
+ )
+ hash_data = json.dumps(
+ {
+ "fn_index": self.fn_index,
+ "session_hash": self.client.session_hash,
+ }
+ )
+ if self.use_ws:
+ result = utils.synchronize_async(self._ws_fn, data, hash_data, helper)
+ if "error" in result:
+ raise ValueError(result["error"])
+ else:
+ response = httpx.post(
+ self.client.api_url, headers=self.client.headers, json=data
+ )
+ result = json.loads(response.content.decode("utf-8"))
+ try:
+ output = result["data"]
+ except KeyError as ke:
+ is_public_space = (
+ self.client.space_id
+ and not huggingface_hub.space_info(self.client.space_id).private
+ )
+ if "error" in result and "429" in result["error"] and is_public_space:
+ raise utils.TooManyRequestsError(
+ f"Too many requests to the API, please try again later. To avoid being rate-limited, "
+ f"please duplicate the Space using Client.duplicate({self.client.space_id}) "
+ f"and pass in your Hugging Face token."
+ ) from None
+ elif "error" in result:
+ raise ValueError(result["error"]) from None
+ raise KeyError(
+ f"Could not find 'data' key in response. Response received: {result}"
+ ) from ke
+ return tuple(output)
+
+ return _predict
+
+ def _predict_resolve(self, *data) -> Any:
+ """Needed for gradio.load(), which has a slightly different signature for serializing/deserializing"""
+ outputs = self.make_predict()(*data)
+ if len(self.dependency["outputs"]) == 1:
+ return outputs[0]
+ return outputs
+
+ def _upload(
+ self, file_paths: list[str | list[str]]
+ ) -> list[str | list[str]] | list[dict[str, Any] | list[dict[str, Any]]]:
+ if not file_paths:
+ return []
+ # Put all the filepaths in one file
+ # but then keep track of which index in the
+ # original list they came from so we can recreate
+ # the original structure
+ files = []
+ indices = []
+ for i, fs in enumerate(file_paths):
+ if not isinstance(fs, list):
+ fs = [fs]
+ for f in fs:
+ files.append(("files", (Path(f).name, open(f, "rb")))) # noqa: SIM115
+ indices.append(i)
+ r = httpx.post(self.client.upload_url, headers=self.client.headers, files=files)
+ if r.status_code != 200:
+ uploaded = file_paths
+ else:
+ uploaded = []
+ result = r.json()
+ for i, fs in enumerate(file_paths):
+ if isinstance(fs, list):
+ output = [o for ix, o in enumerate(result) if indices[ix] == i]
+ res = [
+ {
+ "is_file": True,
+ "name": o,
+ "orig_name": Path(f).name,
+ "data": None,
+ }
+ for f, o in zip(fs, output)
+ ]
+ else:
+ o = next(o for ix, o in enumerate(result) if indices[ix] == i)
+ res = {
+ "is_file": True,
+ "name": o,
+ "orig_name": Path(fs).name,
+ "data": None,
+ }
+ uploaded.append(res)
+ return uploaded
+
+ def _add_uploaded_files_to_data(
+ self,
+ files: list[str | list[str]] | list[dict[str, Any] | list[dict[str, Any]]],
+ data: list[Any],
+ ) -> None:
+ """Helper function to modify the input data with the uploaded files."""
+ file_counter = 0
+ for i, t in enumerate(self.input_component_types):
+ if t in ["file", "uploadbutton"]:
+ data[i] = files[file_counter]
+ file_counter += 1
+
+ def insert_state(self, *data) -> tuple:
+ data = list(data)
+ for i, input_component_type in enumerate(self.input_component_types):
+ if input_component_type == utils.STATE_COMPONENT:
+ data.insert(i, None)
+ return tuple(data)
+
+ def remove_skipped_components(self, *data) -> tuple:
+ data = [
+ d
+ for d, oct in zip(data, self.output_component_types)
+ if oct not in utils.SKIP_COMPONENTS
+ ]
+ return tuple(data)
+
+ def reduce_singleton_output(self, *data) -> Any:
+ if (
+ len(
+ [
+ oct
+ for oct in self.output_component_types
+ if oct not in utils.SKIP_COMPONENTS
+ ]
+ )
+ == 1
+ ):
+ return data[0]
+ else:
+ return data
+
+ def serialize(self, *data) -> tuple:
+ if len(data) != len(self.serializers):
+ raise ValueError(
+ f"Expected {len(self.serializers)} arguments, got {len(data)}"
+ )
+
+ files = [
+ f
+ for f, t in zip(data, self.input_component_types)
+ if t in ["file", "uploadbutton"]
+ ]
+ uploaded_files = self._upload(files)
+ data = list(data)
+ self._add_uploaded_files_to_data(uploaded_files, data)
+ o = tuple([s.serialize(d) for s, d in zip(self.serializers, data)])
+ return o
+
+ def deserialize(self, *data) -> tuple:
+ if len(data) != len(self.deserializers):
+ raise ValueError(
+ f"Expected {len(self.deserializers)} outputs, got {len(data)}"
+ )
+ outputs = tuple(
+ [
+ s.deserialize(
+ d,
+ save_dir=self.client.output_dir,
+ hf_token=self.client.hf_token,
+ root_url=self.root_url,
+ )
+ for s, d in zip(self.deserializers, data)
+ ]
+ )
+ return outputs
+
+ def process_predictions(self, *predictions):
+ if self.client.serialize:
+ predictions = self.deserialize(*predictions)
+ predictions = self.remove_skipped_components(*predictions)
+ predictions = self.reduce_singleton_output(*predictions)
+ return predictions
+
+ def _setup_serializers(
+ self,
+ ) -> tuple[list[serializing.Serializable], list[serializing.Serializable]]:
+ inputs = self.dependency["inputs"]
+ serializers = []
+
+ for i in inputs:
+ for component in self.client.config["components"]:
+ if component["id"] == i:
+ component_name = component["type"]
+ self.input_component_types.append(component_name)
+ if component.get("serializer"):
+ serializer_name = component["serializer"]
+ if serializer_name not in serializing.SERIALIZER_MAPPING:
+ raise SerializationSetupError(
+ f"Unknown serializer: {serializer_name}, you may need to update your gradio_client version."
+ )
+ serializer = serializing.SERIALIZER_MAPPING[serializer_name]
+ elif component_name in serializing.COMPONENT_MAPPING:
+ serializer = serializing.COMPONENT_MAPPING[component_name]
+ else:
+ raise SerializationSetupError(
+ f"Unknown component: {component_name}, you may need to update your gradio_client version."
+ )
+ serializers.append(serializer()) # type: ignore
+
+ outputs = self.dependency["outputs"]
+ deserializers = []
+ for i in outputs:
+ for component in self.client.config["components"]:
+ if component["id"] == i:
+ component_name = component["type"]
+ self.output_component_types.append(component_name)
+ if component.get("serializer"):
+ serializer_name = component["serializer"]
+ if serializer_name not in serializing.SERIALIZER_MAPPING:
+ raise SerializationSetupError(
+ f"Unknown serializer: {serializer_name}, you may need to update your gradio_client version."
+ )
+ deserializer = serializing.SERIALIZER_MAPPING[serializer_name]
+ elif component_name in utils.SKIP_COMPONENTS:
+ deserializer = serializing.SimpleSerializable
+ elif component_name in serializing.COMPONENT_MAPPING:
+ deserializer = serializing.COMPONENT_MAPPING[component_name]
+ else:
+ raise SerializationSetupError(
+ f"Unknown component: {component_name}, you may need to update your gradio_client version."
+ )
+ deserializers.append(deserializer()) # type: ignore
+
+ return serializers, deserializers
+
+ def _use_websocket(self, dependency: dict) -> bool:
+ queue_enabled = self.client.config.get("enable_queue", False)
+ queue_uses_websocket = version.parse(
+ self.client.config.get("version", "2.0")
+ ) >= version.Version("3.2")
+ dependency_uses_queue = dependency.get("queue", False) is not False
+ return queue_enabled and queue_uses_websocket and dependency_uses_queue
+
+ async def _ws_fn(self, data, hash_data, helper: Communicator):
+ async with websockets.connect( # type: ignore
+ self.client.ws_url,
+ open_timeout=10,
+ extra_headers=self.client.headers,
+ max_size=1024 * 1024 * 1024,
+ ) as websocket:
+ return await utils.get_pred_from_ws(websocket, data, hash_data, helper)
+
+
+@document("result", "outputs", "status")
+class Job(Future):
+ """
+ A Job is a wrapper over the Future class that represents a prediction call that has been
+ submitted by the Gradio client. This class is not meant to be instantiated directly, but rather
+ is created by the Client.submit() method.
+
+ A Job object includes methods to get the status of the prediction call, as well to get the outputs of
+ the prediction call. Job objects are also iterable, and can be used in a loop to get the outputs
+ of prediction calls as they become available for generator endpoints.
+ """
+
+ def __init__(
+ self,
+ future: Future,
+ communicator: Communicator | None = None,
+ verbose: bool = True,
+ space_id: str | None = None,
+ ):
+ """
+ Parameters:
+ future: The future object that represents the prediction call, created by the Client.submit() method
+ communicator: The communicator object that is used to communicate between the client and the background thread running the job
+ verbose: Whether to print any status-related messages to the console
+ space_id: The space ID corresponding to the Client object that created this Job object
+ """
+ self.future = future
+ self.communicator = communicator
+ self._counter = 0
+ self.verbose = verbose
+ self.space_id = space_id
+
+ def __iter__(self) -> Job:
+ return self
+
+ def __next__(self) -> tuple | Any:
+ if not self.communicator:
+ raise StopIteration()
+
+ while True:
+ with self.communicator.lock:
+ if len(self.communicator.job.outputs) >= self._counter + 1:
+ o = self.communicator.job.outputs[self._counter]
+ self._counter += 1
+ return o
+ if (
+ self.communicator.job.latest_status.code == Status.FINISHED
+ and self._counter >= len(self.communicator.job.outputs)
+ ):
+ raise StopIteration()
+ time.sleep(0.001)
+
+ def result(self, timeout: float | None = None) -> Any:
+ """
+ Return the result of the call that the future represents. Raises CancelledError: If the future was cancelled, TimeoutError: If the future didn't finish executing before the given timeout, and Exception: If the call raised then that exception will be raised.
+
+ Parameters:
+ timeout: The number of seconds to wait for the result if the future isn't done. If None, then there is no limit on the wait time.
+ Returns:
+ The result of the call that the future represents. For generator functions, it will return the final iteration.
+ Example:
+ from gradio_client import Client
+ calculator = Client(src="gradio/calculator")
+ job = calculator.submit("foo", "add", 4, fn_index=0)
+ job.result(timeout=5)
+ >> 9
+ """
+ return super().result(timeout=timeout)
+
+ def outputs(self) -> list[tuple | Any]:
+ """
+ Returns a list containing the latest outputs from the Job.
+
+ If the endpoint has multiple output components, the list will contain
+ a tuple of results. Otherwise, it will contain the results without storing them
+ in tuples.
+
+ For endpoints that are queued, this list will contain the final job output even
+ if that endpoint does not use a generator function.
+
+ Example:
+ from gradio_client import Client
+ client = Client(src="gradio/count_generator")
+ job = client.submit(3, api_name="/count")
+ while not job.done():
+ time.sleep(0.1)
+ job.outputs()
+ >> ['0', '1', '2']
+ """
+ if not self.communicator:
+ return []
+ else:
+ with self.communicator.lock:
+ return self.communicator.job.outputs
+
+ def status(self) -> StatusUpdate:
+ """
+ Returns the latest status update from the Job in the form of a StatusUpdate
+ object, which contains the following fields: code, rank, queue_size, success, time, eta, and progress_data.
+
+ progress_data is a list of updates emitted by the gr.Progress() tracker of the event handler. Each element
+ of the list has the following fields: index, length, unit, progress, desc. If the event handler does not have
+ a gr.Progress() tracker, the progress_data field will be None.
+
+ Example:
+ from gradio_client import Client
+ client = Client(src="gradio/calculator")
+ job = client.submit(5, "add", 4, api_name="/predict")
+ job.status()
+ >>
+ job.status().eta
+ >> 43.241 # seconds
+ """
+ time = datetime.now()
+ cancelled = False
+ if self.communicator:
+ with self.communicator.lock:
+ cancelled = self.communicator.should_cancel
+ if cancelled:
+ return StatusUpdate(
+ code=Status.CANCELLED,
+ rank=0,
+ queue_size=None,
+ success=False,
+ time=time,
+ eta=None,
+ progress_data=None,
+ )
+ if self.done():
+ if not self.future._exception: # type: ignore
+ return StatusUpdate(
+ code=Status.FINISHED,
+ rank=0,
+ queue_size=None,
+ success=True,
+ time=time,
+ eta=None,
+ progress_data=None,
+ )
+ else:
+ return StatusUpdate(
+ code=Status.FINISHED,
+ rank=0,
+ queue_size=None,
+ success=False,
+ time=time,
+ eta=None,
+ progress_data=None,
+ )
+ else:
+ if not self.communicator:
+ return StatusUpdate(
+ code=Status.PROCESSING,
+ rank=0,
+ queue_size=None,
+ success=None,
+ time=time,
+ eta=None,
+ progress_data=None,
+ )
+ else:
+ with self.communicator.lock:
+ eta = self.communicator.job.latest_status.eta
+ if self.verbose and self.space_id and eta and eta > 30:
+ print(
+ f"Due to heavy traffic on this app, the prediction will take approximately {int(eta)} seconds."
+ f"For faster predictions without waiting in queue, you may duplicate the space using: Client.duplicate({self.space_id})"
+ )
+ return self.communicator.job.latest_status
+
+ def __getattr__(self, name):
+ """Forwards any properties to the Future class."""
+ return getattr(self.future, name)
+
+ def cancel(self) -> bool:
+ """Cancels the job as best as possible.
+
+ If the app you are connecting to has the gradio queue enabled, the job
+ will be cancelled locally as soon as possible. For apps that do not use the
+ queue, the job cannot be cancelled if it's been sent to the local executor
+ (for the time being).
+
+ Note: In general, this DOES not stop the process from running in the upstream server
+ except for the following situations:
+
+ 1. If the job is queued upstream, it will be removed from the queue and the server will not run the job
+ 2. If the job has iterative outputs, the job will finish as soon as the current iteration finishes running
+ 3. If the job has not been picked up by the queue yet, the queue will not pick up the job
+ """
+ if self.communicator:
+ with self.communicator.lock:
+ self.communicator.should_cancel = True
+ return True
+ return self.future.cancel()
diff --git a/client/python/gradio_client/data_classes.py b/client/python/gradio_client/data_classes.py
new file mode 100644
index 0000000000000000000000000000000000000000..bfd86651167d15d20d386c839e9f32b1662461b0
--- /dev/null
+++ b/client/python/gradio_client/data_classes.py
@@ -0,0 +1,17 @@
+from __future__ import annotations
+
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+
+class FileData(TypedDict):
+ name: str | None # filename
+ data: str | None # base64 encoded data
+ size: NotRequired[int | None] # size in bytes
+ is_file: NotRequired[
+ bool
+ ] # whether the data corresponds to a file or base64 encoded data
+ orig_name: NotRequired[str] # original filename
+ mime_type: NotRequired[str]
+ is_stream: NotRequired[bool]
diff --git a/client/python/gradio_client/documentation.py b/client/python/gradio_client/documentation.py
new file mode 100644
index 0000000000000000000000000000000000000000..af1337646761dbdcbdb68eb9d34fcf185846748f
--- /dev/null
+++ b/client/python/gradio_client/documentation.py
@@ -0,0 +1,276 @@
+"""Contains methods that generate documentation for Gradio functions and classes."""
+
+from __future__ import annotations
+
+import inspect
+from typing import Callable
+
+classes_to_document = {}
+classes_inherit_documentation = {}
+documentation_group = None
+
+
+def set_documentation_group(m):
+ global documentation_group
+ documentation_group = m
+ if m not in classes_to_document:
+ classes_to_document[m] = []
+
+
+def extract_instance_attr_doc(cls, attr):
+ code = inspect.getsource(cls.__init__)
+ lines = [line.strip() for line in code.split("\n")]
+ i = None
+ for i, line in enumerate(lines): # noqa: B007
+ if line.startswith("self." + attr + ":") or line.startswith(
+ "self." + attr + " ="
+ ):
+ break
+ if i is None:
+ raise NameError(f"Could not find {attr} in {cls.__name__}")
+ start_line = lines.index('"""', i)
+ end_line = lines.index('"""', start_line + 1)
+ for j in range(i + 1, start_line):
+ if lines[j].startswith("self."):
+ raise ValueError(
+ f"Found another attribute before docstring for {attr} in {cls.__name__}: "
+ + lines[j]
+ + "\n start:"
+ + lines[i]
+ )
+ doc_string = " ".join(lines[start_line + 1 : end_line])
+ return doc_string
+
+
+def document(*fns, inherit=False):
+ """
+ Defines the @document decorator which adds classes or functions to the Gradio
+ documentation at www.gradio.app/docs.
+
+ Usage examples:
+ - Put @document() above a class to document the class and its constructor.
+ - Put @document("fn1", "fn2") above a class to also document methods fn1 and fn2.
+ - Put @document("*fn3") with an asterisk above a class to document the instance attribute methods f3.
+ """
+
+ def inner_doc(cls):
+ functions = list(fns)
+ if hasattr(cls, "EVENTS"):
+ functions += cls.EVENTS
+ global documentation_group
+ if inherit:
+ classes_inherit_documentation[cls] = None
+ classes_to_document[documentation_group].append((cls, functions))
+ return cls
+
+ return inner_doc
+
+
+def document_fn(fn: Callable, cls) -> tuple[str, list[dict], dict, str | None]:
+ """
+ Generates documentation for any function.
+ Parameters:
+ fn: Function to document
+ Returns:
+ description: General description of fn
+ parameters: A list of dicts for each parameter, storing data for the parameter name, annotation and doc
+ return: A dict storing data for the returned annotation and doc
+ example: Code for an example use of the fn
+ """
+ doc_str = inspect.getdoc(fn) or ""
+ doc_lines = doc_str.split("\n")
+ signature = inspect.signature(fn)
+ description, parameters, returns, examples = [], {}, [], []
+ mode = "description"
+ for line in doc_lines:
+ line = line.rstrip()
+ if line == "Parameters:":
+ mode = "parameter"
+ elif line.startswith("Example:"):
+ mode = "example"
+ if "(" in line and ")" in line:
+ c = line.split("(")[1].split(")")[0]
+ if c != cls.__name__:
+ mode = "ignore"
+ elif line == "Returns:":
+ mode = "return"
+ else:
+ if mode == "description":
+ description.append(line if line.strip() else " ")
+ continue
+ if not (line.startswith(" ") or line.strip() == ""):
+ print(line)
+ if not (line.startswith(" ") or line.strip() == ""):
+ raise SyntaxError(
+ f"Documentation format for {fn.__name__} has format error in line: {line}"
+ )
+ line = line[4:]
+ if mode == "parameter":
+ colon_index = line.index(": ")
+ if colon_index < -1:
+ raise SyntaxError(
+ f"Documentation format for {fn.__name__} has format error in line: {line}"
+ )
+ parameter = line[:colon_index]
+ parameter_doc = line[colon_index + 2 :]
+ parameters[parameter] = parameter_doc
+ elif mode == "return":
+ returns.append(line)
+ elif mode == "example":
+ examples.append(line)
+ description_doc = " ".join(description)
+ parameter_docs = []
+ for param_name, param in signature.parameters.items():
+ if param_name.startswith("_"):
+ continue
+ if param_name in ["kwargs", "args"] and param_name not in parameters:
+ continue
+ parameter_doc = {
+ "name": param_name,
+ "annotation": param.annotation,
+ "doc": parameters.get(param_name),
+ }
+ if param_name in parameters:
+ del parameters[param_name]
+ if param.default != inspect.Parameter.empty:
+ default = param.default
+ if isinstance(default, str):
+ default = '"' + default + '"'
+ if default.__class__.__module__ != "builtins":
+ default = f"{default.__class__.__name__}()"
+ parameter_doc["default"] = default
+ elif parameter_doc["doc"] is not None:
+ if "kwargs" in parameter_doc["doc"]:
+ parameter_doc["kwargs"] = True
+ if "args" in parameter_doc["doc"]:
+ parameter_doc["args"] = True
+ parameter_docs.append(parameter_doc)
+ assert (
+ len(parameters) == 0
+ ), f"Documentation format for {fn.__name__} documents nonexistent parameters: {''.join(parameters.keys())}"
+ if len(returns) == 0:
+ return_docs = {}
+ elif len(returns) == 1:
+ return_docs = {"annotation": signature.return_annotation, "doc": returns[0]}
+ else:
+ return_docs = {}
+ # raise ValueError("Does not support multiple returns yet.")
+ examples_doc = "\n".join(examples) if len(examples) > 0 else None
+ return description_doc, parameter_docs, return_docs, examples_doc
+
+
+def document_cls(cls):
+ doc_str = inspect.getdoc(cls)
+ if doc_str is None:
+ return "", {}, ""
+ tags = {}
+ description_lines = []
+ mode = "description"
+ for line in doc_str.split("\n"):
+ line = line.rstrip()
+ if line.endswith(":") and " " not in line:
+ mode = line[:-1].lower()
+ tags[mode] = []
+ elif line.split(" ")[0].endswith(":") and not line.startswith(" "):
+ tag = line[: line.index(":")].lower()
+ value = line[line.index(":") + 2 :]
+ tags[tag] = value
+ else:
+ if mode == "description":
+ description_lines.append(line if line.strip() else " ")
+ else:
+ if not (line.startswith(" ") or not line.strip()):
+ raise SyntaxError(
+ f"Documentation format for {cls.__name__} has format error in line: {line}"
+ )
+ tags[mode].append(line[4:])
+ if "example" in tags:
+ example = "\n".join(tags["example"])
+ del tags["example"]
+ else:
+ example = None
+ for key, val in tags.items():
+ if isinstance(val, list):
+ tags[key] = " ".join(val)
+ description = " ".join(description_lines).replace("\n", " ")
+ return description, tags, example
+
+
+def generate_documentation():
+ documentation = {}
+ for mode, class_list in classes_to_document.items():
+ documentation[mode] = []
+ for cls, fns in class_list:
+ fn_to_document = cls if inspect.isfunction(cls) else cls.__init__
+ _, parameter_doc, return_doc, _ = document_fn(fn_to_document, cls)
+ cls_description, cls_tags, cls_example = document_cls(cls)
+ cls_documentation = {
+ "class": cls,
+ "name": cls.__name__,
+ "description": cls_description,
+ "tags": cls_tags,
+ "parameters": parameter_doc,
+ "returns": return_doc,
+ "example": cls_example,
+ "fns": [],
+ }
+ for fn_name in fns:
+ instance_attribute_fn = fn_name.startswith("*")
+ if instance_attribute_fn:
+ fn_name = fn_name[1:]
+ # Instance attribute fns are classes
+ # whose __call__ method determines their behavior
+ fn = getattr(cls(), fn_name).__call__
+ else:
+ fn = getattr(cls, fn_name)
+ if not callable(fn):
+ description_doc = str(fn)
+ parameter_docs = {}
+ return_docs = {}
+ examples_doc = ""
+ override_signature = f"gr.{cls.__name__}.{fn_name}"
+ else:
+ (
+ description_doc,
+ parameter_docs,
+ return_docs,
+ examples_doc,
+ ) = document_fn(fn, cls)
+ if fn_name in getattr(cls, "EVENTS", []):
+ parameter_docs = parameter_docs[1:]
+ override_signature = None
+ if instance_attribute_fn:
+ description_doc = extract_instance_attr_doc(cls, fn_name)
+ cls_documentation["fns"].append(
+ {
+ "fn": fn,
+ "name": fn_name,
+ "description": description_doc,
+ "tags": {},
+ "parameters": parameter_docs,
+ "returns": return_docs,
+ "example": examples_doc,
+ "override_signature": override_signature,
+ }
+ )
+ documentation[mode].append(cls_documentation)
+ if cls in classes_inherit_documentation:
+ classes_inherit_documentation[cls] = cls_documentation["fns"]
+ for mode, class_list in classes_to_document.items():
+ for i, (cls, _) in enumerate(class_list):
+ for super_class in classes_inherit_documentation:
+ if (
+ inspect.isclass(cls)
+ and issubclass(cls, super_class)
+ and cls != super_class
+ ):
+ for inherited_fn in classes_inherit_documentation[super_class]:
+ inherited_fn = dict(inherited_fn)
+ try:
+ inherited_fn["description"] = extract_instance_attr_doc(
+ cls, inherited_fn["name"]
+ )
+ except (ValueError, AssertionError):
+ pass
+ documentation[mode][i]["fns"].append(inherited_fn)
+ return documentation
diff --git a/client/python/gradio_client/exceptions.py b/client/python/gradio_client/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..5329124e7aa955a95867951d2afc2a93924b121b
--- /dev/null
+++ b/client/python/gradio_client/exceptions.py
@@ -0,0 +1,4 @@
+class SerializationSetupError(ValueError):
+ """Raised when a serializers cannot be set up correctly."""
+
+ pass
diff --git a/client/python/gradio_client/media_data.py b/client/python/gradio_client/media_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..c815d1981935dedf38aab68a2ab35f0a83aaba39
--- /dev/null
+++ b/client/python/gradio_client/media_data.py
@@ -0,0 +1,8655 @@
+BASE64_IMAGE = ( # test/test_files/bus.png
+ "data:image/png;base64,"
+ "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"
+)
+BASE64_AUDIO = {
+ "path": "test/test_files/audio_sample.wav",
+ "data": "data:audio/wav;base64,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gwobAWwAoQTr+LgFs/1Q7/sCcPj0AJ72QQC9/Qr4NgOE+NYFt/hRABEDm/xzAH/9DQLyAyT/PwQVAiP/wwUdAtb/DAFnATn/owdP/1UJe/pSDFEGUPt/Ezz4GAVj/BX7nP+P9W0CB/ti8ogAp/OF/yr3e/hJ/5z4egiV/uQEswHyAaEEmPpMCMEDwQKBAlL/Ygc78fwCQwVN9sr+KAXbAMgEyPwOAuQB5fnZDOv3mQrbCSP7yAlg94MHpvVc+LIIr/izAcb+pgKMAY75vfz3/Lf30foJ/bj5k/vBBcvytARRBOcE4AMVAFoJzfnMAVYADwC7ABsDtgRCCB4CgwtoAmn/cAX+/0AAMgWiAdP9JQIF+oEDHPYZAaD6x/VCAWvwUQG88hcAIgFp+8oC5v63BKD9pgKI/a8ErvxHBx4DgwGnBF4EN/w3BQH8ff86ASj8qQdr9JgLz/mwCI74EgOvAtn+cwaw/o4GK/1eAZEJ8/diAAYDjfX4CInqdBIE87YBjwFu9A0H2/Y1/3b3M/nF+SgAH/nQCt787Qa3/68E7wQG/sQA8gSv/dYBsgsQ+ogLtABkBxwDSAcLBXADVP4LBDcA6vPZBQr1NwLV+zn8IwKt9Kz88PzO7QsHa/wz/r0HqPi/Cn35yASb/7MBuv0cDPsCYQMiAD75GwVk830GfflZ/3MI3wFH+MkH0/xpBT37ZQadBgv8DAlO+7gDCPyTBrr3awvc+AMDDP+n+gcF0/fj/Mn7cwFM//787fTeA0/z3wLn9HX/uQSb/dwDcf1QAMsEDAKL/oAJO/vBB9cFuf5D/1EDZAEBBs7+qQof/hgNAwO4/dcDm/zUBw/4Gv+m9nX9wvbl9RT22//D/HwCPfnF/7/7oQJXA6D5ywdRAUIHMgA+Ayf9FwQBBi39M/6YAxX97ACJ/Zb73QAsAaMF2v/8AnADgwMpAj//SvyNB2UBl/tMBGT8ggVD+4MHQPzC/2gDCv1p+ov9Zv9x85cF/PJt+p4BCP1n/eb8x/ypCiXzgAqT/xX7jAhq+tYFN/tACMAA3QL8BDAK+P6LBuIE6ATBBL8DegTMBOT6WQbx/ED1UQS07z3/cvdE/Ib76fppAfj4jfdMSVNUYgAAAElORk9JTkFNEAAAAEltcGFjdCBNb2RlcmF0bwBJUFJEFgAAAFlvdVR1YmUgQXVkaW8gTGlicmFyeQBJQVJUDgAAAEtldmluIE1hY0xlb2QASUdOUgoAAABDaW5lbWF0aWMAaWQzIHAAAABJRDMDAAAAAABmVElUMgAAABAAAABJbXBhY3QgTW9kZXJhdG9UQUxCAAAAFgAAAFlvdVR1YmUgQXVkaW8gTGlicmFyeVRQRTEAAAAOAAAAS2V2aW4gTWFjTGVvZFRDT04AAAAKAAAAQ2luZW1hdGlj",
+}
+
+BASE64_AUDIO_DUPLICATE = {
+ "path": "test/test_files/audio_sample.wav",
+ "data": "data:audio/wav;base64,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gwobAWwAoQTr+LgFs/1Q7/sCcPj0AJ72QQC9/Qr4NgOE+NYFt/hRABEDm/xzAH/9DQLyAyT/PwQVAiP/wwUdAtb/DAFnATn/owdP/1UJe/pSDFEGUPt/Ezz4GAVj/BX7nP+P9W0CB/ti8ogAp/OF/yr3e/hJ/5z4egiV/uQEswHyAaEEmPpMCMEDwQKBAlL/Ygc78fwCQwVN9sr+KAXbAMgEyPwOAuQB5fnZDOv3mQrbCSP7yAlg94MHpvVc+LIIr/izAcb+pgKMAY75vfz3/Lf30foJ/bj5k/vBBcvytARRBOcE4AMVAFoJzfnMAVYADwC7ABsDtgRCCB4CgwtoAmn/cAX+/0AAMgWiAdP9JQIF+oEDHPYZAaD6x/VCAWvwUQG88hcAIgFp+8oC5v63BKD9pgKI/a8ErvxHBx4DgwGnBF4EN/w3BQH8ff86ASj8qQdr9JgLz/mwCI74EgOvAtn+cwaw/o4GK/1eAZEJ8/diAAYDjfX4CInqdBIE87YBjwFu9A0H2/Y1/3b3M/nF+SgAH/nQCt787Qa3/68E7wQG/sQA8gSv/dYBsgsQ+ogLtABkBxwDSAcLBXADVP4LBDcA6vPZBQr1NwLV+zn8IwKt9Kz88PzO7QsHa/wz/r0HqPi/Cn35yASb/7MBuv0cDPsCYQMiAD75GwVk830GfflZ/3MI3wFH+MkH0/xpBT37ZQadBgv8DAlO+7gDCPyTBrr3awvc+AMDDP+n+gcF0/fj/Mn7cwFM//787fTeA0/z3wLn9HX/uQSb/dwDcf1QAMsEDAKL/oAJO/vBB9cFuf5D/1EDZAEBBs7+qQof/hgNAwO4/dcDm/zUBw/4Gv+m9nX9wvbl9RT22//D/HwCPfnF/7/7oQJXA6D5ywdRAUIHMgA+Ayf9FwQBBi39M/6YAxX97ACJ/Zb73QAsAaMF2v/8AnADgwMpAj//SvyNB2UBl/tMBGT8ggVD+4MHQPzC/2gDCv1p+ov9Zv9x85cF/PJt+p4BCP1n/eb8x/ypCiXzgAqT/xX7jAhq+tYFN/tACMAA3QL8BDAK+P6LBuIE6ATBBL8DegTMBOT6WQbx/ED1UQS07z3/cvdE/Ib76fppAfj4jfdMSVNUYgAAAElORk9JTkFNEAAAAEltcGFjdCBNb2RlcmF0bwBJUFJEFgAAAFlvdVR1YmUgQXVkaW8gTGlicmFyeQBJQVJUDgAAAEtldmluIE1hY0xlb2QASUdOUgoAAABDaW5lbWF0aWMAaWQzIHAAAABJRDMDAAAAAABmVElUMgAAABAAAABJbXBhY3QgTW9kZXJhdG9UQUxCAAAAFgAAAFlvdVR1YmUgQXVkaW8gTGlicmFyeVRQRTEAAAAOAAAAS2V2aW4gTWFjTGVvZFRDT04AAAAKAAAAQ2luZW1hdGlj",
+}
+BASE64_VIDEO = {
+ "is_file": True,
+ "path": "test/test_files/video_sample.mp4",
+ "data": "data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAWlzb21tcDQxbXA0MgAAAAFtZGF0AAAAAAAD8BohEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8AAAC4gYF///e3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0NiByMTFNIDEyMTM5NmMgLSBILjI2NC9NUEVHLTQgQVZDIGNvZGVjIC0gQ29weWxlZnQgMjAwMy0yMDE1IC0gaHR0cDovL3d3dy52aWRlb2xhbi5vcmcveDI2NC5odG1sIC0gb3B0aW9uczogY2FiYWM9MCByZWY9MyBkZWJsb2NrPTE6MDowIGFuYWx5c2U9MHgxOjB4MTExIG1lPWhleCBzdWJtZT03IHBzeT0xIHBzeV9yZD0xLjAwOjAuMDAgbWl4ZWRfcmVmPTEgbWVfcmFuZ2U9MTYgY2hyb21hX21lPTEgdHJlbGxpcz0xIDh4OGRjdD0wIGNxbT0wIGRlYWR6b25lPTIxLDExIGZhc3RfcHNraXA9MSBjaHJvbWFfcXBfb2Zmc2V0PS0yIHRocmVhZHM9NDggbG9va2FoZWFkX3RocmVhZHM9MiBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIHN0aXRjaGFibGU9MSBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PWluZmluaXRlIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz0ycGFzcyBtYnRyZWU9MSBiaXRyYXRlPTMwMCByYXRldG9sPTEuMCBxY29tcD0wLjYwIHFwbWluPTUgcXBtYXg9NjkgcXBzdGVwPTQgY3BseGJsdXI9MjAuMCBxYmx1cj0wLjUgdmJ2X21heHJhdGU9MzMwIHZi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PcnL10/Cvr6+kSq/FeyoRHS4/u8MZclfrWoI+7zQyT+v/Vf30X/SJ9WLDgsz4EeAIRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0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WTvfBNyaQO5hYw6x0WPO5hLvd7+T3wrkgo7vbLO61+CLe8XW7363d/666KmR39iUCK7u/ZPTT+pgQ3dp5fIzjGfcLrr6ybr19fS+b6cN+SrX+HvjYCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8AAACikGbz0pAK+CvzDs1pfN40Wnza3vfNx9xq+Xbthj0RKpf/sXLJmSb3FH6nRNn/wqWcCpsRFPp7v8v3vbLCBnw3EZ3Dt0eatetoFrbUvD8tD7cJHqfpy5yz3P6k2vxdN9ByxeX/6fhpfF8s/mMliFPFDOE3xWhePCdl/u3GRlewuE2LpvQJElJqtwf2n3eT3Utz6D2+4KvRuC/7vhzV3jHf4jaH97B3Dy6buEi3Ve8od+EtBFQQzLnE+qxMEk4KvPayfy96tAolg/d3On5CnFQy9/vy5CfmCXDtya2i9deX/dr6mX8KPfG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WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vAAABVBBm6AV8FflHZg+nL/vhAvNg2QvDjRKR3+YmEX9v8u7hmUxfqaGFlcI99YX8EhNIJPAqly/+4Q87zGan2ajZB8pUzejQG9xpQRrZR3fTe7vkHz59o8JF5pgMluTcv73hEmdfIPXQXQvB7FJPptzzutX9LLa1/+U5iJZlO0gp4odzNhjZTzWDXX2NywLR0NG8CRnPqfwp2WyjtlLofjjzDhEzn/lgv2Q60cwvOJYfvjX0Y/z93nYIZl5o1zLrvatU5f4krvdJ31p/tkK7v+Xl5kQTL/7gsGMnvaLkWMi13cb9TPuJvUv1xNIgrVTil8v3dbKc3fsSwRQEzKz/b//xVvVn9Hao7k/SuvBTD3ty/P4Bduuv3vcL57bnI4S2350D3tboHvhLxWtOTb37gqM3Rl63ljfxWaLxAYtZO2hrjN0mdidOuFI8+9Ducf1jSzAuHb/LuRtG6fEfteaQm5Sn+5JO4D5zOH+1fGl4R685UGMvXu+7fSNN/5Przt7CFvuUavIHMJcA19UrYk90Tlhv+Qm77L6woZtsZGfDDihPZZYetJc01eJteuc3Czx+zv250RjabH+R3Z9y5w2OCQB2Xb6PGZbM+C9gEtHwGyhfEQu2RobbOf9gp6jA0QIr63HICcZKH4PSpT+1k1zvJy/5ehKeEfQpmX/ywS92jqeVRWT6Vr8PWdwyzK4bSch/GPA+i4WTeevfWaF/rInCkjyTzNrFafVbGtFTwq9G+G5/6u+3pjB0rPT1VO36v+CCuDHaDrnDNhuzWh591j6JrPZKU/lKEvC2bz5SXwxu5Vyr91xlf6azwRTzvSq1KjMFuE5x7IRL3cpV0pbaluFDelv993u8q8pWB1zp6p3lIvbWThHwTbZ/m8rOLdVhe+7u9n1desEk2/x2LYLZdvKXfi7ro7BEU+RbdYJdO+PFz8usEnc6eXWCK7v7rIIhyj+mzqwQid2d+1V/ynveshMEZnd22hHwRkP76/GCR6v5+raG5oP3fysJdJ3st7vrSplu+T0uqXMZ39ZCny/Xk9qxP9EKDS5pcNQa36ylJUpTVFQRu93d7nTfk+umugV93z9/OmXgOoR7FECnP6Zm/cZe6T6dmq/LBO73rorCgnPnH2VTuXLPYcJ0w0rkQe3vD7Ubejpl+bSVpex1lBd6DMSf3JLThG+yz+zv17yc0dEi4lh1wrfLvlGbXcXJKz4J/rHLumsZfdOZDu9/0NU4q9x24eW8I9CZl47SMz5zxudvZ1MITLzMXdROETu72n72OT1utRbDO31n2vrw8WE/hM8T38+XpHQDv3dZffVN5do5PSr/dFJ/UOX3Mc/pjCy/v4sQc6YlZJtfRAk89F0p4493eQ+PR++lhPdrWOve86Fqm73W+T3cv6BNnSXeaM9CPh4lr49WrJGtGidjw2uBfVHf4JzN6Vzb3N7VBA73lxJ3e78tC0U0/bHYrfeVJPy5+gkSbbvtdwRFyZRWtH5ff8JaBvB5N/J/VSNngl6WS3W1AaXiPaTUsImd98I0h+1h8hw137LuQlrJI2W5JYSL6NXjxCnXOEuEf41Tr1+O3vY7xX9MIFOwG5P30UFo+fp5/7iBuq6ZLvdfcwjPevJ9S92+qpO8eIlwrG42cmPg/jFvwykG1N2eg70JKEO/v7GgouYPJeVYdcVTpKu3KSgnLD3fvY8Pus+FMkgWbJ68kWNTbdIRNfezr9ogouxcQXNsq/0L95CF794jeuyQU2z+YHPuqTyYWyQiRoZ7yfjPf4S3fFc0ul3sTmvJ7T0I47tczBFfc7Zf+pIYr6+sJE3ZKn6/ESF5cBZAAAE8UGbz0pAK+CzwiKw9m/Ihu7Jm+/ykW5iVe5eTXl/3y733wv5iTzMg/jeYeDj2Jt/T9h7E2/s8Mr5dy+a60xYPNSr+HIlrl/bdRhW8I7x59MzTr4muN3eWMIKPQ+vw2koVTyjppdgpSkdL+/hi8w49sITxGYu5P9x9z/7mK+neqW8r3au/xnhI/NbK3u9uHRysK+YZeOm2X93xnMcKTd63JlX9AJcRvtPy/v2FdXThxbdgacw92Sf/uItv0udxEey1139/vl/vfVl1Cnm8ZvS/vthQllO91frZOTu+W2qHvvsZ7uwyiX3vd0WQ8VFaYllhAp57bnJc/9v5J78n6XjdhK6Xy00JZsj/SlK+X14mKkeu+UF3u0Mru5IP3LduO4CLzqaox962VnIC3OM3P5P7dpy/y3NrWE3+NEKWVlb7e4I82VIptWG7PXh23/3TTQKpZNHHpPEUTk0UlVNF12FG8yBbNfyLHl9+CI8OL0U//6/9+vpr8KbHBXFpI5HI9b6q/M3Bls+/g7t6gtMYIq/ln34VLKgOGXKg0U3qYzVR/v9fIYS94S9CHb+wT1q71F7lH+3eWHso5CN5mYZEjtSJPkBH9m7rwX1U0L/7BXEB7MVbp3zs1xdga/2dXzof7QXsAl2l0ML6/9iYJOWd8v37gnlWJxtECNur+kulaAvx/w+Wl3TO9vu9+p1f9r15fV9QjMJPLjYZL3IHb5FpPdM+hqxhoaUzfIoua2jz13B+4n0JjxOG5Pd3vdOl6mJd3CHmys0vRiH/v5PcFcDykzilTJ2uv3fLoX9uvWLXuixW6osF0DV9Xfe9M9qvbvpldk+T7/8ERN3eEPBFl/WX7XiAVzpyaZS7OM2WMvv3uFDisVu8ao1G90i52fpQ22HdWuGaD8fSv81U6zJeMIiH4KRY8besJ223AjuQXi+NVs8EJrT0veJNDqL1aPd0lFvCp89+XqX3/8NGdy7rCS7G/3+Pu/d3vfp6vPLffuS9/sFhXKw9ux93SIL8s/3H+TGcbr6BSIb4HrSLCs6W3oxC/wTd3cbG/v3lOePS1T9SVOe+r5zr90VOrycxBoSXfZ+X9p819+myyB0/9lITu9qJJUI+EiZGU4+md/GEddOT3N+a79PftCxKNjfLr+zsIz/58ufC05P3t+nvOtXeE7re7f4SveQvfvye3+bizbgjV7+LRj/szZP0ksalElczvAJ3p5v7WxK+kyb33Y8rKPf8r3d5YfH2j+dYN5z+P0wj4ITS+6cPQITO/48rEnLh+5bCrcstvzJi20uT21Wqly/SklYyf99y0977PKTmy1F9nyVyfSYbl9BG5E5yl0mruz6giJ5aIx3+J97Bve1J/brbjCW77ub8At/Y7+/y+T221a0h0sPDiTF8vdLD6euSoS8IEn3G8m7w7TNVTvspwnve9e2OK9KynpP3Lb0opuxfF9+6FSl6+8puf21japAqnSFGkm5liuMCM1mn02L71XlLbh2UX2D1fA/PqDnu+RJcXX0b18a3+loRBLzb3udIVWi+T7+URJKUs3Q+7CF9+HHqPemqLFUqXNfiJbzz62V89OzIxt3k+qGVbreZ5LzhTWmS5ZU4WL9N/rZMJkKjt3u77xB577fvEdTpqt/JBFyynBtImtr1C/qkXyWmn/ET55LvL/+Tz/iIJYwy+fvnTdPvefA/8ZAAAAE3UGb70pAK+CvzDuHEfxZZLOcs5/v3MQN5b78vksL+CQlouMemy/+4R3dmQcaIL8T42vYQJe8iHZf9ywRF1zpp3J/TrnYQI6+t43AeRNi3KXqnw/nLkQdyBMyu4dv12RuOYv6/Elxs/vVHq8W3mu1V5kF62e93P2i/r3dnHFj+CPpjuhRQp5hk7VRRK79wpnSTxTjTG9uyNlvEOqOa85cuG8iPx0QzSpQZfu3oEu9cXcq33g7UnJS17jJA/3d5Qy0HOV0SGjv6acydNgvWpr77Lyff/0X4zaC+FC//YJyR3ZDizXn7M/j3dsGX3d8Tq6ZR5oaYd9aWCoqKhO+51s5KcChsrEZ63D9/v681yJ5LPBNYeaZZPsJvYu2ZPTacy1ef4UW2WMEH7u93Hdu75g3r/wpMP3vnfnPvc8dFZGPE+fvDpZh8+uN7Ydn+upIlkiH8ty6tfc2e3EFaPym2FYmHSVumqPHx9+fJF/DMGT1l14KicfEgcNaad359N7hTphBs/DezL1qtzdiDtfhH582l/90Fbt5B4ArdfrM9P18/XXRRN2zRCNYKDCH36m7N5uC0gPa/resn23bpuPyiE6/c0+Y2Eij9WZYK6j2xW5NgTVgTJoHfYUanYC8XWKO5X3yj7fdGzeos46GlNIbkF+9p2XSHn2Ji5c7MqDq3wS3f3MOTmn8FmNBZsKDSbe93KqY0kVOMNoJz+8Z7zkndMduNSGQ0zn+WJEtPTy/J6151giJe7i+TJOvuEPN5f8STI9SslNT7/BHtv1+C7huS/1JmHf22CIs0qcG7zwQ3Iy7F37wR+HV0KMd6xd7vvbVWCc0OPyFkQ39tawQlWFNv7h2VEK5fcIeTeXy/7eCMjxW9b6xwm7u7vKxW+/dT37FhH3gv77wVEcOOG7y5xlki4v3MIui7cYUxpfMl988d73d+a7v27RmCWleHmeNHBurM2rzwV5ZXhvZtVMWfkF9BDu77N7vSQvYK+Q+25U7u+UCu3E0xNOuR7/oOXvb7t1CPYKjOWRIorSn+2m3dtdthKX8+F3fuYr712mEqKcfl39nvRvt6y3IcXrX7sxX30eakBdUU/9tZ/aQ/n5w6+z984sleIVhOkvu+T7dz8n6GXKoe7uRS7vuw3CPQdjJjb9OZNFmTf5YSzRLyz+/eqUdHlorv1Glt33cvyCofSWJ/4rk2191jWEJD/MNK0UG6u77dTfwXzlCPua2FxT62n/qCAQ7vmc0Qv2Kn4g3F0oOG8DP/YRve9ITlKhKfvTtYot3d75f3096WL7vh12MI+KJjc7qQRHn8v7+jXPwgd7u93RO7cnt2/kKDAWRz9p2jxSs/Z/3IRw/dv15JO590PYSzPvd/VlfZd/cX03kRT3d7gl1JklvzxT0WrqLNw3FGkUuI/////wj47CEjcvxkSF5fyYR8mCVtNf4UItrapfB8TeT6cgEmOyRnJzC1xOSrfX2YuX+T1fqJLl/P1T++hPyRRqwg40w4e1KOQs1vr4Wh6LT8VvO05f6J9+Ld9DDi/9/gj3cvIkKeTLuifWv+tzutevpImf+sIlq+733vXkgp2/dx4T+XpxvS3up9hb2abtddYmt5TOc0rfvCIt0ezfKOL7pEODWWS8Zxwxf+IyQ+XZfNJ/J67bioqJ7qfP4qpEgsgAABUNBmgAV8FnihWYEIdyxG6T9xJNfv1Nd/F85o0pcgl9I58sL+MJy5JOYtDSBNsx4MUzUbH/GljL6tFl/mPYXTyOcmz3qcVPbnr/3ClEURvb8Em0nbhCsak13qti9tsWI33joW34k136vzRzuU4z1/4qnvqz+Er5Z8E7adcvyX4nx4Z02z/qMUhTw4aEH+mYBrekvrfJQhyl3kuEA9Or3G4azaCb+qsb4EX8Xf4fXuWcPUQeSU0s23VFwEM0t6rQ8xfe4spi9faaC9kt4tdyzJl933CkfU2d03+CT6OfKVJVw+lw07CdtEK2CdkLRv9ypvtsKejMmZfaqr61zDlp69C9QKq79IwUP+wykEq7hQoRcbhSOxjLG2lebTPzR3uct8bI5abHsMKHbSRbjeEH9W8O+cmN0QSf6FcVuDJZi69a0zlQrTeffk9JdfG0GQTjcjnCRarYRUkXEjvvjRafnSagxr/y++9BS4QMOXW/vwtwywOjvDq6Lfrghgt8sEs7c8xfb0j2kyywVz+/3l2xwwvaNwV344oim+N9xkk817mjtr3LG8Gb7Rwb7CfgsCWn/XXT50BjvCbbquOlYt72J98ZQv3uHxsve4kuifPy/9ZPpOXs827aPWa8yBh6LqizeNepp6CHKoAgPToy834YrBv0Lb3+bhVTPe1wm/seIt3e+AJNy4dn+/xnswEe+bJwxsrgjgeNO25fr3ChQWdYw/ekUeKV0menniA7K+rfcXuQX4gvHB6wqimaOfcIbIi3znyvrJhfTWzn/STxtGOmmz6BSTZjx/Wmx6ho+YksLPtk+nI9cKUVh0F8dsb+5QKWrNuDaWo+51JgvKJJ1ze+T9aCBhzHlhL1dl/3bBPDSThGjUI9t24OjwvhL3y0Y2Uk0uv6y0PDlmvJ9qo0r4U03FndwoBfyz/fDV/15p/d5w5LfK7J31amuhyqMbPoZWD+Z+EyuMa3yhONiPsWwRGoOp23y+pZOCg6Nzg14Ve8OYOnBHHBJeke7yaTbye293ikKwDH6Lp2kknhmXLUnC5jlIZRLOki5OOKXV28PLcfSVtBMS09N6e+nRNb3qEl3ghI5+/Wkt1w7E9e4Ijp98NP7JOu9/XOda5d4s7yxz8sWL7oIincK8/zhve6dMEJQ8kk+x2eFCu7923303bpvargr3d3e72+ZCHo3fgrJzMPve/t+WhPda8q5PrvfBLmf88v/q9erh6/S99G8vCL+wpTzoCa327fdsvffWLyqT/3eT1//3IXd6rP/N3fQmE5Q0+8/6WrF9X/R1pJU99uTe4R8TL/H6bv1BES532/soQE4Vcb+4rd7vsWw9z++yyelE3v/WK7vGP+/erG/dU6k9PJ1wiR3e+E+HvfEDf6lfL0cRfTRahE8xR7e979NKVN6UgqeKdIqDbhHxBoyY/P/wRGp0/HqJOK3FbitxWK5PT1y613Lr5N1ne01Vix3f5Pt8XXNLvpSokEvb9sqK/x2pyw3vc/e7XMxZnR+CSlEdVlQR3JtjrLb3d4h/kZSfuEfPFV+Nd/hc0nXhzsKgpnNV2SJvliy9vdMV9IcXdGYL6ol+5d6QbGvvUOtX/68sgh6t7EyybdvVKmGml/UvZrJ9vi1dAnM5RWEWHZRbksh/a3dOqo1xMJeYwLhhv9+78uoOe9akbu7wtWJLpviHH5oIsrny21JEXa/T6JVP5fki+X7u9uSmOxvHjoz/favrBPxuZ350ghgn1WSTeklrJ6dv+pBdajsq+bw4PWkUivCypcvmcL+qRLERE8PuP+v9778l135LjnR8FcAAAWuQZogFfBZ4sUkGs4a7h79ykJf1+Xz8M+Ykh8Ee3MQWvi8PsOhJfxfGxpLE6NFu4qcI9woUfZW/8J32b+fCCi8fhk90Rx+N56bZWiDwmGgj/dd0vdLfJ9lSYXW/3bn6TfLJX1u+T95MTLHXfNmvLlfn9ezP/CvizckNR6Z+FMfnHIXmOgkv43u1CbXq35KHEdlAE2+dNKz2Q/wxkMt+I9/7du1+7Jhwjb23G79y/flEKYY2vMj77iNK7BDt/ktTr7/m4bijF4SaY7/GbbUZi6tsMw6G4O48MjIMr/2BW/uIKNifQ8OTnrXr8dIDjM3uayLuaeZpSh+X9fCUoi7TjAZ/KbrXBhixSjh+9vCtU/+FpDuj8j64338vyeoRy8d9zInp3feliSny06vZBPzCuNyX7hQk7jGUyUhmnzuyPy0yMIux6VsnNEjv7i+8umxt2IiOpvAW1dd/csj7EvezgI/47yvvNlPktsZQ1xbUrf3VFYeKGmetLejR3p4y7m2np952UfdYS7n/WMvHZlUCF6OtP+6c8I325H+EPHonkeWNJEy+KvDbJb0O46j2LifLgyJ93Rf18FF4R+Hz6GbB29wpmgWCl23eHccE8U4s0LXB/AJwm9zptJpsKdDHxULt97eYk4SOHoZb8Fla3go1hcvzghPLGigyOImYgt2W7lx3dzxEZbQuf6TXhX3/G/mkG3akD950G1fw1LBkifqxHrjXf7BbukjSIvoqE3VUWXx91Qg8WHINM4y6U6TvY9StkjMO9IbZe95E3OdTOlGqLRUut1ITdH8EpLHw61JQZAcgnuui+6yxtoZUHtdfNdpVPr6EEP1LbdYd7x1dHk+lTp8Evcg6ndrprs+19b0uEn+CexPXZbvMmlWisb2jSmfluMQnUp3AjflnP+ObaP/6D9Eym4EHp+ogvj1kz465t1dVc0drB9dy8wzlJyZ2/+mCQzNdeexkx8n0ll3mLKIw63fL9v4JTP3gqlFW/BcV9u75GdXWX7kwyt95f31FZRKX5gc+mwiQddH3hqhkCEycgWqukJODJ64T/onfZb7hHw/3Ddbs8FMmPx7oP45i+UgJ7sY6Zf8g2luHamAOKEsvO972tQ4Kef+T1fc/E93MPsH7/IUj+gr7VkZl1/R4LZB/fNHnNLmgh0RX/aVf8FPdy61ZoRRRXV9320dYfokPL+u97u/oTv2+GPv120r9F+0C7e93f/5xfXnh8I5ILBG6u3Xd671O4qjuq+vrWONfXVVtayXfCK7wU2g337u9G+5pYZk/29sFRN2nd7710XtL9LRpRMvva3iL3u969p937WT6T/E95NCt73L+l8Vml3n+xPqyZf9o13wj4JvLw26PK8lrlwWEuHMJdk93em2T6zW85ARieSQtH4R7ujvvPuxsTdy/vvr1qpY6vWTdjfX6izPhL4sPmlyLJIpVvKXAj17ffvQ0W8V3p2be99b3uEfC8iEkw8k70jceCftNC749100ZnQM+zaxITbBQIf3vdzL5O+ET3Hct3c/5c37QKBeDrg5cL+L00uQhCTR9ZLvOtqiUIz+T2m/lJyf15JPWT2aPVZIQLaZ1y32976d1lmEPA1eK+/sXPvvL+kz5Iwk/UICCxDFaG7n5/vd7yiZx9+43VVxW9ekUrxW/J7GiTHWu6Ebd9/qjFLzdze/TGm4c4djYqEemf7iDXzv55jPWv39DYQ8fWwg5unMNd3utXtwfCPuTt3uO0PLxZhzK/qvBZe4r4cZ1P7zpCmSE+SFaTL4gydZtHqe/ExImHWSX6mu9hWnlm4rdWJ7p2gvvDctLu/Z7X/Sm0nLleSCr3fPy8dbPpxuiQSWUYldD4V8QIVfSX4qbXJlqaXJ6qVmiOLtj3vuNTVO26veT5Pr/JRzMy5ove85iVg/deSQl7hj1Tr74YxX5KnqyRBSbmZIco8FYLIAAAReQZpAFfBZ4sVy4/cN+HBHHI5L/iaWX/2wjtkOZqlkwumzu9vX4IdZiyXW7Q/e9oOCSjC2TtPhuL+Se7Ynvh7d5cfxq5v/LVe+9SxRUi/3b+CPuNtqd/fPbhXzGwwvdmfKYl/d7G4SeQNTp23LJ2IJEiXNrstqBfx4cvXosOwlPocDnZ6aB8x+sF9IOjRFNH/4U24NsFbsAYR+vP7dlTBv1VB+H2eOoqV9x1tGjYX3d91tJ7jANLAu4M+9bChQl9tby4Xsq/d3e+V5Z0zFqlLCHI3ODzSvgm1PX9Hu9/LGZ37B+N9uUOtL9CY+NxnDlO0zj8OLqPJ/XTliru8yKCP4GWPtBEpeNrLbsyqN3/l5nkaE3+KCFqzgK3Jvu/xnu7HYiYXfvOFzjr/XthMrFfcJ3gNakhUfcJ0V+dl77aF3z7hN0v4Qvve9jvf4SKY3ecR76o0/u/cFG1HRL0eAgEvv5//El9wgQcE962BK/itl+/E2vCsj+/aCfdPGxAbv97u4TXtggEZjju7vgpOnCPk+PX+O9L730Cu0BDumDZwwxlfZ/udmDRkPXRYU4yL73DMW/1o/qSkqN0JU/ZP38byHKKLBPXv8EFBi/ynIQvbBc6AZ8NqNH36OwyJ3d/6ab9xd33rqiXMIve0j1CksFjOpL/768wjLj7M7GSBZWJV/e9INVuMN6BHi4eh2IpcGeG5J0lTXpXwS5oxDmLTRTNknDO4675Mot6UI+CMRPvZ+C2GK/+d3d7iT6r9wWZVwyvlyE5d4I9L3/mMLolwVkeXbAO1xRCsVffCueVp65S+HuYTzL1TngiERurudYKy8JeUXq2j3W7xzpzFPQ72P2eCIke3/94IsI/NO02/VAgpTFbcEvDqgQ8zvMj5RJYdsc9JLZvum9mHM85m/pUVKqp0xG97v7Qy5aPz+97u9wkufBWR3d73Xbr8E0yCHYs9yy0T/s/Lc5vvvCZyRe93f4skOIs/xvf6xb9S035PbS9UumySNDNSw7zMEJK1p/P8PwSHe9qf4Iu7tCK9wViuVcV73vrfuFBLivef7p7v7sW1z1Qn1S12Pq/f2quN139krl2kvtesI+CEj7b79Ne0/Iiw23eTs/v6EPqu/v7T035C3vuveEfRH/Rn/KLe/RPilVfX15PSXrNMbI3xVe6SrkhHzHL30/y3e9asokWmZY53d+T0ndzyLL6/EKnfXrZFt+SipBtIskK9TrTd9fvKxJ+rk5P4oQ+qwKKwIr2pUi71iIR8hZf/CZNARGEieTy/r4jeXn5ffdldgmLuYNn+5JD7T4QRBeb06Xus5mPzd+T+mnkcUasYEO5vy1T+kJhLw8w8/F9Af/U8F8EH1Z+T17rJU4oW8pabf2Xd9fIGJYbu70q9U7y/kKiydiZe71o5UCW73czOLbosIXhC00/z/d+oLrps9sm6QenC662Z71ejnTVYj0oK8/e73d3pVVavQx2TDHqkSzRE5E/5ryCYRgqgAAAQiQZpgFfBX5h2Ohbi+CAubOX0a3X+LC+LJlxLDjqL2Wex/Uvq/Fy9swrxL9eUfh8srC3hwJY5k5EvDuT/hTzSNF39rZhECT+Xb395mEysYsG/LET94Z7fR+7y/veCefLwH3Fr/JK/i6KGRBYK8AEFCcjjy2UhachZ80T93xNzyp4yv3vhDY7p73DNwu8v/yllybQqyBTzGlo0Y4vx19jekErFAYu+u6geGSzf4C1VSNRae6VEve09rboz+zxvxQOea3kVmz7YU4gnu7f34b85EGdyVlpxjvn/KUMLW20PptJWJLuhc6ZkwTvm3LCEiL7QZKaN5eUx8Sw91uPpJH/75a3Cf3u+nEXPry7Zw36wS42nlX1b3H0rqvFTxlGXhxZn+a+YQ1+JLy/u4U8EAxzBetxVzkTQKeYpOgAjq9rLz01jml631uVjLtXtyxADI1/VIhtrvlLs2KQILsOIrAQKv+0M6WX5S7fg+6HRfdyvx0Cv4IDgjv14RP+vfn6bVckmdL+MJ+JTRre+IJ8g6fy7/FZacv/lKYPFPkOduJiIJbvngEnrXOmuyxneY5ZNmvA303ScS2uDfSk/Xz6BMQbE/w+3zQylp5C/SqT9dT2zR8v63rR3tZJ5cJrbLGCnsVu7/u4lzcBe3U/Txef0N8OGL00XDCTsjv/vpfd4aa190zKqfwQeETgjPD0meA75fnc0hxjepUka//L7fuOPKGkkUGldpDBX+6cvrt4KomEyBvW1w4g4OlpCUPjhOeNp8kng6v17gpGMXYBSKva86lWcYefd+qCmJsLv09h+CMbXLpkXR8MO4uBLubq9/lqnwSz3wh4q7DSjASlf/XzAt+WtNxIvJX/d69FCe73mjCPgiGZP+3+CLTuUffX4bh+Lpat1au7/0dhAkO1P/z9XBPvjAl/kHiLadCX7F/cEJnvy70V+/vJl2Nx/IwUGzPhJw9T52WOrQl6evCWUlV+ZL34gnMu5f/fRK1k/UR/9TTh93elfEQm5D/3vr7OSEfBPl/y+v2I5unRXoSy916kvosVUdBK78q/oq7LXL9X6yS+7hHwSiJn67t7db5P6+z6X0xN77G/dXrX6XqspASXf6EfBN4/TXd2/sEJnvrf2JG3d7T9P5JCO/1RTgy+i91Vif4JBBbhjFV6L3R4I+dVJd2LRDu+m/kk/CRfv3IKe7fwVne70nduf2/EC7ve/v9Zf3dOqE/J6r8EgjEQjlCj+/wXb3fS1+OLl17o73dO2hOmv+I9jf5sFneof+JtmEgHV5HPhSseSTMfneE/Jh61mlyIt97+UERsueqnKJu79Sd3usr8T9apom9wu6zMtV6pc3LnqW3m26yLdCNBETNupfucp3RLQom58fvdLhK5JvYrd4Y8EV29Ok/Ncblf+6Ov5Llb2usFcAAAP4QZqAFfBYX/3MKcKvtrymy916lSF/BJ47ImMv/uCDKHy0eLR9QM192ludUjeK8+9xZwlFxt7NOc+X99QtjpGHm54YeBWT2nb8cix+X033GzalTwn8EVvSmnBfoyWCL6Z2SM9fl/23Fkf1T+JENPXuGTsJxifi9MuHr/y96tD+je8+SkT07yd54YV8Ehrm4n12kxr3GY/OVcSEG93+vIFy5uplP7SetBNdyPczaG4us/audFW7gty5btmKaKn8ZCvjfoOjyA0KxStp7gvGJnR7lQXlTlaqsJlOJTXcBH7kb6/tS8F2fZKJHeTc6eoKcjn3l79mNH6dVvl5aZf3dy3DjbAyJr6/hPzEk29/Y0k0Ebpk4CrtcB4++HfYlUWK3XyKS9n/G7IlYNlTwclitbw9mnszG70a60W5h8/2755RNfeavthCWXMCyHGHd2Ocf+CUpSZS+ErTHbs86bvOwSbmQO06PqyXDG5BZbQ7g6nm0/r3X9YKKsr7T3L5W1uWCHjeRPxfhtJH0YMYHr42iwwluVsXaodgOZDRxcQCAztub29F8cmpCTc3nzTRU4fu9vj03hP5761omWV6uf/VdBC78vu7u4S8E4p28nb6y/9Nh4mTe74BTy6/f14btx/bBTnFIbuND8p3/Tvv1Sd8n1WXTgt4aQxnMDi6Am17f/Z+IEucP5rRFT+4LiFDpd0t+9asTZXMg9HglIZdoOlzjL/+q0gwTjJN37XWWnHu+CLLWLxeSYe+4S8EYq763+Cre5VwfLXBPda3WWCDjLpyOmnnh+EPj9f+PVV3eNYUJwQ4EWB/ieQdDcOa3+4gkuIibl2BY/VEw47sN4TFnpMe3cwSk99/cEQqau50e5/fVS6E6V0/IUj31Zu4520t02Mly7iv7qIF8N0xyCGkHqDovULRhdHuFC6ZVd7uX73d2hPxIjKxk9b1yXv2Lbu+YqqPR+6tkKP76tddfXtPwQ+Xt3QIZLiOqcqf/RSK8IeCLy/X4szj1Ho/P7/CAm772z69vX/Y0vVdifiPX1qw1yckI9gmNbt5ffXzi6b5t+j+/t+/r6L7E0JerF+0l6nrrUI9AmmZdCbn8MpEZTvk7+9ddfVq/fXhe9+SwQb+1eNr9dZfERZU5Cvff5ru8I+CUlbT8KtO9PzwUb3e99Vvt6FdriPd7dJ/J6P7ErvNxpO7T6BMXd7u6KdrjMJeMl2/JInTe+RIlOo0E5D5e+utfElOIcT91k+T230K9fk9ubIUfpvJHEKF7kH7e6stdrt5tQsT6q8Y6qi9NCf+jluvJ6pNEfITuWFURmTt6/ThfJKZ7urE6L/kiOXyeie1hf0JSJZLkjJCi+aT5C54wWQAAAO7QZqgFfBX4YHaQ24zU68c7/iyh3NHScVkJN33FkJhrYRs2f825Ub2/F70uHM58FEt3meWamSGPCBOO9UB4Qyzu9qS8f6yP3YN/spf7d9buFL34bk/c9bzRYN37inTOX7/CPd7joGzlwEjfzd3oBO/wmV4bQwWu/Lpalgj054koV8xqTQJPD+6l/d7G5Nci/J9hYVvsJ/NYEvjkqi5KeDx53l58iHp/3irvZBAbRVbMOITiUY8WZkn7GUruP7d8swn7R2H4Z66SkKzZ7j2VRTR2WMhPpj73BnTGA1tfZ2e4dgryfbaYnbqdPcQVhqeK55Xrgp0ZkDishMD+EvBM+ZzpcjfjNEvPuVi9VPX4rn9z51W0W7js719iSmQbZ/lISf5bDljCfgsCEidiepSn/ytTxef/fhTv86Bv96xqu3q4cT3Op1dGniT30fvoExaFuY0QWttMtk+kres3HZnk9JLL3CfmvK2Vq9BbCenSBN+x+uHuV/J+lqyWbjomXOCfgnp1O53tLCz2/sFRkM1ciB33PABAG7L9duOXrL721jeHqBz+6WyD6RIz7b3qL/6Mg/tHOf09pKe/VhSH2GPYqZBjYYTDj854PwFd5NaOmELZVP7vysaoTyIeJIPhFpnuNNcvwl+sXiXc2lha70m41hUiInv/uQfuiv5b31QJhbnve9FfY2KpNNOt/yGcwkCB922LSfbeLVtDDHXd6zZ0BDJ44ed9910+1vCnQPzBhCLi/pigfk3etQNpugHcBD6a/fhDfC67f6TG0noO5tHTr2JP56RDeC8xNIixHT4oYdEP/L68S1r+Ei/+XXYKxR8qkTnlPLpaEjt7ZfODTjuG96QuH394JBHD8nDvcx93VtOeT9NrizZcG8WPD8lnlEI779rXKpt7hJ/iScsdN/qzy+8EZ3v7on8KXd0D2dm3vd3s179H5PTS/wREx2T7vZOMzW/BEWndupCi8Zywh5QkTZf5YJRL3vfhJXrV7rui/zeXhHyEbdN5fJ+NN3TJ1djdbXXCfnEu+imet/ijU6dN95MvYn2/eYXe8v/qbd+/omrFoJGd9424a9NbXZIS8E8z+MmGxwq3PVlgpK7l9t3ufuc9t/fa1r3++vJ00uxO795hF2I/7m7veqlPefhGsmEu529fv0wXG9Ny973fOCUj3d78N9VaXJqxPtcn3+vt+gTFuNiwLB9g/z9t1cxb5f0oVf5T1ky8Rl17T3vv7+8WV39tVkkIfy+GHt/TXZPjv6phvqob8l1/s45KngsgAAAA2RBmsAV8Fj9xYqTC4rXsV/KTHemvdUw/L3TDHgkJDfg6uvf2lNe4R0RYZghgiROqW+ZvyvrhmV3vjoLrqXco+PtDvqlXiTeXl/sraFXcPO5cGkfcXj4UOjxe7QvgJffPtd6Abk/S71/KVJ5b0WJ0y+FkqlJ9eT5OM54V8xtQT7xf47ILk1IzcY3OUk5bfw78b9ITPctKDA/uV76FuVk2/GcePYIcNNQ9w7cSVO0iHi6l5UO/oLV3mrj8eR77nBHa48e77rt7nDa57pptpzCz9pueCgoTct3fxyuxTdFjKbYrkXQz5u/VpUuRC977lFq+zUZ2Lrw2XIH3XHKfhPxgyGdxQXv8DsV6yvDO/fJQSYO72Q7YqI7WGXVNcfjQXttjJ5EuDsvbbAx5XJuhWl+a9k/MITm+s+Yvi9xnHGuUFp9p8i5CPjIeHRWCkpgzTpjcw4eilv3AblbJ+u7qP3t3viUb0u74f3ddJbvkn17SdSTl1dPqhvCXkpXlGit26SKmw4y1/n33X8MuS5PSSTWsEd70/uO54Ht8blhvCb9oeOs3d/d/cwW6t2hn4I4VWzXwm3yfr5Xgpp4YS/OPTfYZvi4aScu/ZPvc/lIJx099Wronet+r/gqJtIw1OOGof1+kT4fiLmLlByhxQb7CfguLI1bn37f2C26IS8x/HRTfS7rcb8/NGhzReGcGdo6Rnj9LpIdDq7ol+18cSsa7OTI/xf092/DbfMHnkcWjsFIl5QvMN3n2GVDg6rVN4YMGscQ+UNvVi89P1+Upc77Hy0N7ye6pZFhO7/DM+d74QMUFvfdzq3OLsKoEkKqioEYlbF8lS8TEvNN98vCJf3iSSCr3vIrRXMn0l6uJ5gvbh9J/9nZe4/7eCO99dfuCPe6f1d5kfV3YlUqc8l3wh5Mv7/KIdv7sTe+8l37TNk6u65L+0tqvCHkx2n9DiWdKx1h/3xukfl/Lyx297vit+mTquxJbr60JaqOuqBFm3rohVfaSogIbvfoR7ZJn3dWtV4IS7v3T6yVV/J6tG7svukftvk7S5IR9CL0/PV7pNCXuxfxFe/X/k6Uul6FMp99Jr6etXhfslU+uvrqxfr3r9bPhHwfId5Mnkwst/J/TJiOUkz+T0/7JFnuk7v7+vVKSbd9eSJ3e+4YvgwgAAADikGa4BXwWeLFLKSktSP+5iZyxxpF/2stprDJf/cJEWiZyiw6SkeKS/vso0sxIpczbA5XqLTCG9fWcsp6J7KvDIb/KLfqNf/jZyNEM430LY33bgCdq7fDr3BWuJl7i7+HR3FynZ5jDbK3Z1b7PhvB5zkv+JTl7vXpFvf8ISwzyl1thmZwS9xVyyvlhtqPqK8KeCQ1I+pq2ZMv924zeEy4+QIV/8bUtqwZf3CrnAtZUEdiBGbWfksZrZDd/5Pi3Y65PbUpSroZfFoe+WGy8eLineELgy+vn19jYI//WoUsec3cInnoRu/8Ymv3D96hmdd/9N24MChu937FxovOXi//L4yy+SFMzSnLa/c9Td/btHM5S6U6w5bIgIW19uqy+SlebneQev3E3e5f0L2jcVmTv/8pZXnSsBQTf4LAk7WHakdcqlv75faq8E2/vUHc7ftXX5j5+XSbapVXeCu+KijYkg6kq6J7Hlbs6FXveXwoX7rbGmPhGXU4Dy9o6fC66x8ATLcV/rO+OkGU/NssKSPUbsPV2h3JFL7vK6H+e6kvLXldv/uMvXKItMCR/6/f+T1X3wQTLQTPHbwh/lmY3KHQRPWpRc2uf24I7gy5qiVX/8Ep0pu8F3SaYiN7hMgaSTWlf3kKvW39H9e0tQp5rKnaOmXu5i7U+7OqGkyCw6rR2Z6fHSjLvc36rssZOjtjRS+T00v7BLbed6BJYTIkn+0lpBMbLe98n73iSZfLwk/arwgEjL5k64WKESO0f+TqHqRFd7lxb/o79i3Xi+de76sSgQyy9jJ7TX9mM8iEdTGvq4S8t1qvZY+gQ31T3kRepa+97FEvd79H9vk9q/Gfs8xXd32kvQl2LFbm6eN76sFolK9N9q3mo9e7fvJvfRF5SQls/yzVfbm3d9v2/yq0JeCbe3P4aVlffWUSf0z/6EdXghLu9dj6t1+T35Pbb9VKZ5XWvJIW942F4viyEPCoYonvXPCz8vlnr9FBHu4aegu5evsTR6ql7vtI2ZNyAbMziqoyWL2aEfOVY73+/sPkbhl1nhG+0+WNu/4cX7J3qvFEPjby+/qUSF3EHek/6XsnomqI9tyObN37TNSHEFc50Oyzm/cP3Ay+09Ls1jRinwnksUtbpes296TywRHyoTSKm8kR6fWb7pPHZf3hm3lp+1kJhXyGXVeXbvy+hPSRZPrWRsWt/4ayUQ6SfD3xUAAABEJBmwAV8FngoFGln8d0fFYrzGxrTDPmyCGE59m+M8M7umNGXJagvb/AIPmZqypoGVddXvd/jL9Q5BF8fMU/BoPln6XcdBO/xWFh/fj5vxpl/uEeMnhrbtwI1X4ftL/L6vOxZM6IwHKboFLaf2JhM673svvNJLr3CHjMraO98v/0C7liad7iu/L4eXAFV7gtHFNeZSGnWit7xa3cQXeH/d/cRAT+sL3dravOrdeqY6L96y4V8KEtFxzoDVX/y1LLGThl2qnGrodNJtiSgrljPl7WE344sC+f8Y2EuI62k7hMo/l3KGr9UKxpn8ssn6t8TRiu6YTczVhK8j320ekm6CezvdIo1sTBHu86dHQLNz/3CPz1zNZJWlVJEaYKDWg97e8qatpre+Xd4TflgnEP3cNv7tAr/hL5VwYz8GrcN9q5EMp4pQ7nXGRfdgs5+xRfcG8n0/Y3ho+VM6V5y5f/yJEyuy8nt64q4ItApQ+VGwl8nf+wS2x26gJ/edEdoV15MJepLf2KuuFRdvfvrNhx70niYwhe7Xc9hejQYBzd+p3RuF/0Yeiwhirysnpb5NFO9XXuPr6oEJjpwzus9tX0fu9dd+7UWgVkKPsjBHxs73KFyFvvyyD8PUzTzpIEh5n+oQ83hx70JNk2Xsex3VWS99NJyBDyry7fhl06a21f6BcXd7yu1tJ36+rFb3e77LyfdCvlQSzlDEXte/eyZaFEnj8vtbpCD7vd/61vkkNe5eEe2Ix+jWfgrPL+XLuypv02r+pTkf9Ua93povIQ7BwnfX02rjaq/bQJLlb920ELu73fu9v9F/eVOEPIXhp6/bGkOwHn+2ty9MtkZZy9uNiketvlWL/ukcwkFGt7gl+lt/Pcr1VSiT5/RZ81hCMq6alldV3feT0kpdPDG6T3LCyqHzdPpK6HXDaSN/d3e77xPd7v0bp80Zuc7u+G5aV277PeEN3d3e7u3tIJXZvxzW9FhLe+79II73Ivd7u9bpwh4JiPXeRfLbqVxRnwQ+/D/3N7yMqKNzR20XkM7+kwlvfd6TcWlrt1hutWta4LN73hBpiXcFNb9P9dbLd/wlvd75f+iEH73e3CjY+EfBOYuxoTG7QR/+UwuQ3CywhT3FZce8V7Sl+/TooU6b8gl399WNRb37TBHO68V26qhRHvEvj9B6H7Xst9v8tXTcI+GizU6XTr47v36gqNc4rzNuolhl7J6614oj3u33dkKJEp0rvL3dl3vtaL/4heSS8xtK/x0cE9Ei9QKf10RLv9Xqdh7rZD+e4aI8JnLh5G7n5fhahMvFfRS9093fqUps/foTNu/RoISF947V7KpNwr54CxbL0d/pZ8eR5ZFubXlWq010L275cIa0IghOfJS9OtiemsRIW7+IiyXhVueHHuaOufb7uK9wx6pF91Dn4O+/4ifQu5Jet/iMZ7Nt+hF1JL+IjubN4/j+CuAAAGREGbIBXwWeKFc2LmNe5SF2Pki73zczQ3H814btX6l80wwX/3CRLjOmrlulL+94KyzI385Y/cNt78otOfh6ZBOgtNndgkbEoBpqqdnrnP2gQeq15q3bls2Qu9B9cv5e4TEmvY8yJF3Nur17lIcx716ZS6bhTwuI4b0ObXshnZmz1Hm8qeEXsXDuAV7Y3CTqbdTF5fb7AWviTzf878V3f7uqbzGSTc7iHNsv5JxGdNkaGj5WUhLaF8b7aLbsdh3oN5OG3MNvBF50zDSPYvtja92XlfO+Ntn37DcVkYNIZxtQsbut4xE/TZ7jeGmlXhL3/tfTIbK/zuV9Rky4f9NhAsJ/ZKMT/y2Bnm75x8yvyfaq7uOhO5bC+8ILRwg5NDAP6SLcTysFw8aXSXgk4fXMaV2m5Uby3vH3s+5x/dK2yIhQkV585eN2fl4Tdy2GE/BYENpHW179JaJnfxwF1Icf2y/Vbh2W6WFtTLlLGgV3AXvZk6u/YeP9+T27EvtwgV6nlnvmB5C95tEwmw+b+xMVu/KF0Uv+/l/3yyrhI5Jt0rv5On8IXM+CFv842JJEzGC+J/2Vuvlwn5KbTTdbtjYhgd1kZn2CoqrpcW034XHLf2nVmATXpdtrDvd3v+VZZdp/SR2o0mBFufO9Ub978wlRXM7n5O/qAySv2L6+CLcULjbvGcXBAQt919Q53NdruNvP5wxLMJsK+1EHcUCFt1b0Efz5KHoN7ZlW36NfIf+ylDkfFqY+ycl92uNEjkTiE6ue9xP3UxQv+3HfnTDBW2/9i3/SZLQeNKLZx6wkNML2URMnXeYl0tf9i4k8W/CFwf0P1qjxhp/G+IyMiK41b28xW9mfB+3SS42LvDN3eOTpb7CgRipoRXh8aBkuyAvgIXa14swyOvry6m8dQfaWkNoaxqmyFbUYH5ZKqfJf6/S7D73HvmJ6CYzCw7xqfrbZt7XCPgoh6tthHq68z6G3t7oxWh6DQy7Yd+/dmL/3TuC0hbdEBXxJyHg2SvyZCeLDaaPxuoBDkXdejm/P9ZoW7up8W8Am6+N9WMBf5ucfZGC+5z9KzFd+/ibHIbpmQ2/6m7J5I9uJKmnc69tvUSwa877/dfokFhMOfvc4/b2VLB7je7hijve12kFigeQWl8I9ukrdVkPKN8M0b+hMOFS1X8ax8sFO73fhuJg+XZ5pZ+qNNChMIOKZ2FtCwX+1RvMtJx0ujF4xtJ50CiHoP5zqhzzvfqyWdx1eEfBWYnpsdak39z1CHl+F9WXNj2LYJtBcyOyaGOaV9m7Swl6T88dvioTLqw77u/seR2JvuH7SQt31jTzC90qBefZ5PhMsepuXZwatM1XbbbLusFJILuZt22R/JvsdYQLck93vm3a5oojucs4LO0GvdL0DC5H+kht5dCS+blXd9Q1nxn4zKr/xxbvnzSu+ixdp2t72sRIC695Nd6fL9dZRJZTJx/gnHRy7czHad/woRfTfvGKOy25dUU43l7gqE7u4hzvO3bT54IbW7jbRShzWfXglJd33eL6BNIW+y3d28uxPrBLd+8uRfYISPeF9eu68Sd37ny9UEbvd3fd3tt0QZd3fd33Y969yw2rXwi/IzCHvr6RXvqr+ul+OLJ0+933+9ronu7/hG+73d7wj4Wy7I2OnCQs/snipX/fysz7d5hmhZ03rmI7/p5/7GsFt33JbOzJ24q7vfemsQ+/o9E78Fe7vjCPww4U+3+OEu7y/uyeE/DxrV868JbarexsmBYLDt9ZoMqy/O7yI2t+4KD3oqTpt2LL3iBM7X3vrGJwRXe6dfH733d96WlBH3c6dfv9Ah2+nXoEhrw4CB+lvsYV3vw3T2MP3cvd73pIU4e2n4nCPqkG/xxqjqousqibnO+HfZOtqhxRurvtB6ew98n3rjTxJT5vl+j+el7L2JXkf3rTSCAiY4VMLbH8IG4N7odz27+X+SuE/IUdwgy39IIea8sebK8okIGFd/F1d/jhAKxYl3vcummY5n1Kuy68hjkZ9Na0kWpStb6XsXCZT2r6Ut31TNxkv5PSp/mBF3IXSqX03XhfsE/c9mrsiSO36pFJ7f34kqZy21fdGqelX5tJtLkhm76YXST/WnRCcZ8GK/JJJrzW8kQU8xj/dEbhHXUPfGQAAAF5UGbQBXwWeERWW9KXG4Sl/xZDAo4zSmJBx7+Xmv81KXIY8xOG8XL/9i8PQ/ET75dyB0/UVhO1jWCEdlL+740rw98x8f49HqViLd1h72kbuPns6Pl+8tw9xmrczwDkXbDSX2kaT/ct56O6wk3v6rPBWalu6WwNuOlj4+JYtHRYQPMwykjfl+vcJZ98scnpKX6hnlnivbb/4QpValw/8vhXzG41ES/u+NyASCH4HpQS2r6Qe1aACPx5JuzldgYe4TBQ23200XdX1D/Y/xveu/96ZfveYKAlfORx4byP/f4yZccktuvkh9LMKPafPL8OZpw1Kt8gXbrLyelpOuEy8/aPsk63xU/Pgh/y/YmJ3u+/xheeAe9/kfaIzhPzGjtJpZGX+NJLGBG0l/uEikM/bi2KUl2z+x1WZPu9uTd/zSecfeY9zwsrkbYf7G3KYsTVelzsPWfZKjQ03fXCRpUrYkS7xBa9t/h/z/dCVhL3dTrOkj/vpsaWsypzdw/WXF5DDNN6r2PrwwHQVQrMb7yWkJMr/lSRLNFwrUiRz1xaRO3yfS5XtjbVlfluIu4D3L/5dLdu9KA7hnSDD7n7WsFfSOxXsnSDcnywNSdfBXvPF7x6OLje55dKXgouUeetBDOvOnX1hfe+odi/2E/yV+mmqG46EQX2R/l3T8sLmXFZcBVUZ8tL8+wEQpVuvl1dgwvlJeGm6CduftQWXl59dEEl6SGe3+Uu7SIzL2tOm3ksdvcnz34oS8gjdu/wpownfoXZnu25VLF+w+Y+dEkwdvaBBc2H1wncBGq0aalW4M3Pv1U5+Yhabvnn+8M3W6bMPZs/jbSI78CBf++H5di/dvHWg1ISVh4/V931XrBctFgDh9JW23bVE3UbEfpZseZYPVQcl3ZT/JYfub/iC99w6i4HAW/3V1/5H7XuNINFLzizXX73fNV/l6f3ElPnvIXZ9hexcl39/kjZVwCffQ3h2mgOtpJL5FvSZF+gN8dX9pTPIauy0zFXsKYcuGW4/402Or7fVQ8WQfn+D6znmYPP3+CGprWw/jE3Mt/Gwk1a13eJP5u0aJ/I3hCPUiv3m/6B6Pc755v/3j9Jr/J9JJedMTz3rliCz4+EfQr+9bBFdoZeN/sMbw/b+et78c7/+FDTov78sbuv7kEZnRC/65/f5Rlbgcvfc2XuC0SUffGZWrvXSd/wTbu+p1eFP1BJePov29y1/k93G9yzbvrckKEod6Snr/CT75gG6sfpKqY64/0CbunmdlyaC9kt9b5S9bZIJz3um9OUJ+CQyWGnn9y3eDt/iDvftORbqCIQnHu/b+RCdn72z/CPojflIycvf7/BId7313q+/dld230V5P6fysVPRllJX/e5mrWi6zwjszi+jve/WCK+5i62QvsDnWJpXmEr71cUV3e+6fbwiu8FJnRqw6W9Ne5du3+Mn8/vduX9v6E+mum+vqiHP5w1tczyelX/1u+jk9Ut+i3kd7hG77yhq761NvevGYQ8GHjdFrX8RUZf/xRnP3uif5WLTd+sxHf1id33vzIKF3fd93u7pV7BRve7uQTdj4Tvd33tJ/J68giWoJBD3DKSxvpfBXve08Lo4cliDfXakm3pNBEXu933vSRSShPdK997i1CPgnMfrHLhJthdKvhEzt96q1yeu8hLYUPLhYlt94tyw1/aWmu4SEuMV97v3DV71Pi/19hLMv3d9KJl7v572X3i93d77p6F5+f3u/sxuC+Jz6GZj79uX3P9Pu8n11MnQIy3n6eEfPX4Zqv8aYMvbAlbtrz3Whp63NT9ZRLYJyPwbq95/30MEzJtLOgc2c4+f/opqq+8t0Ttbzb1VP0kDAQM8RHzcBiT0XXd79Wa/yeu66fTUKZJNR1bvOyewmJFjXufbSk2T7xDbLXolkpp5PdLkyfUSVt9IltfUSZ3Ku0HPfXZITj5/7yb8jhdLWEiPpUb90kSU/G/0v+pC3Sf4JyOWny4lXxW9xW+GPVIlmiN+Ll31+93LnJ3dCxDuuCuAAABSlBm2AV8Fz3zBDHSThnz0VeHGm/4IMaDQhHy9rG7IId4FaLnzZWb/mm6C6NacW6OZ6fy/27YrOUvK/7gsvlx57hLwcszl/2n1bngoJzChcygQi4CC05bs9Tv6TcvJ+/rT3vL/l8LP7GiFDj1shK/lL85CRQ5Q6GArrQG345K0ySH9MiXruLbEraz7CShl3WB7/+2NKkZ72HbEP43B2MF60a8OxFnPI0RHGthDrpMP/H9ZfafsZBHL7M2cVCuOIf5ptAhO3HvOVHyDrXdqbewlosEOzJx4rGqXd0Euh9F6aXUWjJ+tvWpC19Zf8tv8p+eQTL/7Y0VaNLhHyeIX2UeFHjhsNpISHQePZbFb/TWtbtDdZZIquFYq8Il6Q1t3+vbv3CtpB2Pk4XD8Fr2lbfXEay+13hArEb4RKPEEHnDoS7bvT7I+x+ifBfURPY3t/JJOi899aZfdXrtwoWyiyL3MRIW4S5a93uEXjobPOJXa6jd5zbjMRe9reSkScSZ8avWBLgL/DbtYV+o2jUPuc4nswQ/Wbs+91HTitwi2y/veg9OdLhYQo/ce5c4nTkrttm3rI7G1VffPnPBLtwQ/Vom3j/Pc+pFk1C9x4iF4cvMMpPGpF3kV8XLrXBJ4ei7pU3+JKZFb7xwl4oQ99Im13+M4ZEWfyxn7k7iVtDtCrTsD9aeCCEXerG9AHivkAGI92RkYp2C42t+gP9C1JV9tP1HvONGNXnr/e+NklMgjrS0G1s5vx8RwaO984+7XUBG1M2cLsrAz54D1gTv/z+qx2LnHfrfEFtWe29fv/m93gkH7+tfjyTkU7vDDuu/vwTv/fThsr4G8flnp1jPf+vqKvaMDWr72sFRJWJTdXkbvJDd3MCENYJ48vxtoqHZYK9BoAoP/n/xwHTIhb4JW+1siW7zJ8rFwT3a+3LRst+w/PI+kmnDsAMrp2/vduFlc28Fo3ET0O8sbmsC4336j5TnWP/qEvRKy/2vk9VK68uOvjSMVk9UjtvwmaS3DYHx0rtA2V9dpAjOH4j2gvj21ViavtLcExM6+Oh4JZI0snH3WUrzBqrFxOHLzt4YcPTje+bqmfzdKo/w4JIoel5mT3RsHn5VH8n1RPuWZGBpODQXsPR/b3rUJdgkmR3VjJ6Sb3Z4Jeubvce300fQRvvuU9jsC+qfJ+lk9mLLD1ojnX1gnyjqXKF791YgmzDbwMgbJ3tKlhN+4J93e98R6QJS3u97dav71uQsq9AyamJKtf0Xe/0VnRU97+gll797/fP4QL+/hkxn7991f7fP/TKXd7/Md3SfY115IexnN2NW6z0RyqpXbVN3vcI+Cbe8rFOX4K8/ve7zb1rpoEZ3kQ0o70Q6d+6UtlGfby2X6Vd8vfqJz/e/RfWC413uY45r56K1aZUCiGXu9MytmelSF1pJzpsWJufuL3d+RkvfyRxHja7e9yoIR8Lky/Ha7AzDyQuWrzDiXtic/Ll3ftQgd993vcq9/fXkXSZiSoIS/0T12e9wl4dMULxnvKybMfGTGQf4cUNwmbfgnIXu+963b5RLu+T3/NUEJZsy1O8X191S6bFq8n6qrREHTTB8An9/a7QTHs/Tpb1xfGyux109Mgcc9/fqJ7l77v7YskZ/CqxJdGTJUVhKVhWnd/kXYvp/KVK3tuQi0uMKUh9/JZbDHp3C3iBGq8u+3d/SpKjp1fk+Mjizz6u3cl9qKjkiHRRq8SgntXENH94ZOFbTzXx/vhf0ITrkTo12T11J8QWrVGfvgsgIRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwAAAVpQZuAFfBYvcLCufQwhiMlSQ56/hd/vykzaYz8X3fSaDBf/cIkY5YY3KCPz0UVZpWWTzmjXFZf3txpYeZoKLBA9dbj3P/7HWVx33Kk2wy4v5PbTbfKgjlq00GvgeL2tLik3vQLZcsE5nu8NEPsKAyWK06b0yxJ2bzXd2Svx/H2zPRr0iSry1GsVnwj5Z3caIZr7SCvmMTUgTfq+3qkv7vY3xvATCzce90+Ep/QphRiVWxUEz2jV8cn7VSO7bd9PuEnzn8v/uMnu+PffY6HEUvbHLYR+vxsKvHHuInbCbWGEGfqo5Y2B9gOYvcpeqaUx/7vbGFgivV/vYH8N3+cMJVFsHrzOe5Pu8/sJVztOeaOSHRL5Ppv3UKXq9IEubceAe/g+2ijfsS4+UDhVlUg/e4IzZfD/u8jqXsfdp+5de31eWM+PaO+YOd3dTctBd7WCYrv74yCoL0hR/hEcWz3Hf+d72W3l+/cKaFpvfnDR1tZObwzTs6cYek435bSK3GFMG7yCz3YBDbwSaM9X71hLDqefu4Q+fuqT9JrpsJlXpju9w+lvi0WETXDK8i9VR4V1MZ6U3lv5b3bCXl06y/+VjJmRG+sdm9ujFk0+Q7e26porBASUPhy5eAHPbeU/dkb5nZNv+Ro7TP+4SculRfpwjlhKyXnEYIvC3kH2zk+ixc+5k+kiJt6GiftHJFX4+HWrQyfZd3r83b6VsiBUSAdlVsJcKvuWtIjxW7l7BdKq/LwkcTK7UssJnbfu+8lxVzlvd9OMM5Q1hqk1Oi3z2H3IL168tWdwfJChLIHx8uQP+59lZsQ5PVoNl725GwSAUpxSY/wT5QxggdvAf75+ipnK6T/J+vrlK93CRPrr7BEKdt+wpcsEJFH2iNgb2NNnuFJHNgX111/QcYWDBcPAnPi+17BL5BVnS1wdeQUiDxS7dX/VvwW93cij1us8pTD0oYL7PXsnvXuWCrH5/m+dd9/xZHzLzBkEfu/+jwW3d4cSvuHuTOW0n/4QO7733P8I9AjNFWiN5Zfx2QtFiZ+gXEmlGVPHzt9tAoK8oLezu/eTe+3BESxuVRB+JOnvkMnYl/30RjJ9/9FOZHdlb7gtJshud5X67FoEJrLGSy7bWoTE273vujPBPd979diUCXe+9x2hHxIg/rP47uf32coKD3P4y5u9XeT2095/8El3d+1rr2X9fXvUER3fTLuPES8irfdyhb6gi3vLJ7VfuY977Ognu+yfbZqhHL3tJ7yyuEfBMIuf5or3FeWLuXiu3u9Ovk+nHSxtowvdr2jd0eW76oTXul6cEed//pJe0mpX0kCTLv2msmEfEl4cdFIplv5DgkI4f6X51dlMLIJEj0Tun7vtwWU39zIbtuL7rD0iEv7ZW92d/pkvr3G933PDbavdKi+aP+4q+aIbXa8/1ll/7E8npO64qCI2VikfNG3uf3vjthcHnboyhFTmNB7PXye103qJEvefvveQsgIubafL91kIYhfwj4JyH8ZO9bR/xLDKntnQu93ef6dU2d7vSWZGu/q3e77EvrLfesISylP/L4f1mqW324I93ot6cUId+Pc92tJi9Eie78v3MnlOxvhHyYJm+3+IEP+WNSu9FKKIXuX24rvXkgkE3en7FtFNd110vN9fX8YaswFMg7HygdcR+3+/JhPyFYQP9js4l3o2GT038VJ3jr1YnrPJYvd6/d5c/HeMitvb223yetFIRXMIz3mjd/ufZtmOFi/5iOJM79UvNGZNuN47vusuENU1iYIjnvp1oR3lkgnK2++4AC1llgg3eVhvZXd0WL28m6ZBxG2mnsi0sKPX+Szhih3C/sQ7/xHkiQjf+IvkL3tAugAAAR4QZugFfBX5h0N6l/iy6q6Ri4QcXb/iyLG5K8aOuslwUd3cuPisZf/cvMfY9cL+YkxuBA9dNL/7hHmRHgU09uDqCD9fSNmL/X4wvLZCpPjWZaSgx8z7XHN19gn9w06wN6s6p+Pljztr6Fm4dg3CQtnyTBe2KO7O6uUrL/u+Xy3JUNcuXP0lLcv/Tvsw7ufyxnumyCnoxk37jc7oScHbAT9zOlO5w1/gSey9bdwdUqxy25t0LV+uw1SXvQCnTi7hrDOZ4xwQvA/+/sO5PxniJu/f8F/zK2PDy+reIDjqhUq7T8v/eNhF3JdgQXzilx3xKn29zL/b4//05fp3x5bQditGUbu+qV/haJd1U7StLq+HIOC9/idUf3FwmxeSnSUbI55yb8Efdzg9xeXHvSK6tuieX19m3J+vyld3NoTftgqHUUZzFBuWMLKYCrQtlsS4lfxvvgxRhWGGGIvJ9/Xicbr+hIv28f/r3lj/7gj3e78pcZfu6Lqj+qBYQI+SpcZ08IeWgeLl+0HXdnUKP7BVgo9s2rlu+5dvsa22gXkwolLAVtdwQWZy5S+B+p8X8eq9FYLOmV+4aXGQ0lzmCo4YWIXEPh0TwAsd0qc1d/yIwDqu+/B54SyTT/8JknXyg7hyJ/aR5YmPNP9OkVH859dsu/Xl/jyRYpVRAuD4MUsXpSpX43sI1iLGfWCsm/Zu2buZGrQZrcIfia19reFIJzScR7wze5MW8GamZBvgr2db64R8LdtpUo+vuPaf3+CIrlXfMJh1glN2d4Y7X4ZEtfY3k4zNRUx+B2+03SqotXEoCPaiq7qQYudtIsoy4/SeMA67x/C3Zh3nCAkdf7+k/e8ayoEdBBaejphOzpwWcd6xoib/baXYWqHRa7ktxY3dHlaa6Nn/UEZTTkHn1T+gVXDVp+3IF+8xdsn0t74ICYSXDG3sC+3Aj9i9m8M3d/VkiUFt1RfMKsavxfXV7H/9hM97yR7/CchvckOES/++T+vUXBQbmif7fLVVYIIZotha0+TotPuqeH/cFO396Sn7vbXTVOuut+PtF+/qtb9Skd/6Py/S9vky73rb4Q8IiM7ckud/glPJG93t+Xd9dTPd6L/umJK7vffX1iO7vuvRDtJqvflOT04Q7Eir35/f4+973vfesqLUhPSr10WLrptj0pdp+973k9ttL8vLLJ7v1+X2/y6dwj0Xe9+oJyXrz+qeXaLB967/yleVhv4iqfe60tfYsQEuXy5jtWtd98I+CcoZWjveVJs36/YQ7pu7uXd+kzlj1Y321r11/vIR9677v8Jkvdsdjpq0yPZd7y+unlPne4Sf2IEOvSLnfys17+hIm97b65PJ+kxM1k5Pr17ZWt9i/v0/WCfu93lbqh5H0ZA3+89L+SFF1iCp6vvyTGvfr+xu76L7yke/Xq86CR0793pPxRr3e+9bCMl/Py0z4/evCvj72E65dJBq1PqLIkkYe1WvJLc1uW/ghPtkxItPqlUxU0r8kVmcOZfUm1pk+TDSxvZjXHffEWU3SwWQAAABI9Bm8AV8FnixVxl8bMUR5a/KR+683LkMl/+wiSwo6RmmQmE3upN+b8578y3cfD739ykd7+4K9zgzuc24ZQfLtP7h/xnK8boaPicqZB+lbIgIlO2Huj/hMqTxkTGU6+i3mFr15YJ9zAvu8wvwnKLovn4V8EhpfAQ/5J8VNe4UybHYQAGj6X72Up6K5j90LltrOdgowv3yM/91a6x1r1ldqdbA+gP7jOeVdRErPK/c4a/MPw5tdullfUv/uNsYIv+gWrGz3fuXfaF2g7qODdSOnVr+jxxTCaFvy0/2e/fG1Sbun1T47p0rXsl9pZI+ixclU+efST4LZa/c/FqUvzZ2oO7y/7KVVN3yCXmER3E5hf4wktYetUELn2PG+9/X43S2Xp3ZL4wt3s5RkKu2lCL75I73bBDY289BKfCkj9+Bd+p3/cGo4HmQ/LYg5BvWT20mtaGFD/DRHskssfaoOi3EZiS1EeS0V7jcT1hKW+eoawL7QbSW4iCRsbr/n+k7PLwL94U+pc69Hs8pXlMp230boQ6DQaaUkIiHch7u32Rfq/d4if7XaZSShIoYOT+SsJk/d9XGGcOpMn7EMA+Mmm5N20d9tPjSXd0Vuk+XYO4Arp3F8S1UjfeDPzF1wE2rqtZ9PtPOwWU75ykKs5sXMWw80cfhJc9X2nxqCQR6aLr6TxrEZtQoNY4DlTsDu8RlC1NgbVzXcdcHR96by/02tUVLtczCJsaV9khM76xhM0tYXuksvplZ8hMvTPXkdDpOAm9XuY7T+Z5QNsF/bg/abS0M7Ly/E78I+t8n97pUKK8Lq/dKT18ncFJiL5Kve75l8voYSOy+5+G5dCsgZIH6QnHvv9/xvLeCMpAXeB8evNe/qvdP5oIcjbv+CvOPSnOGnRo6aeB31eLQm0rj4n2wM47L6ydF79ehHxZp2bem6L+/Qq1ToRJcn3fvou9eaXke/o8hXZI9buiMVQn24IiMOX9k9NSXxFHfJ9fv5PX5ETNd8IeCIl7v+CYg/Tf7e7/goPNE/3vf+qPqvf691lPu+qRjtk9pL+1i3lqCMr3peir3BPdje5l7dQj5BCdv3E3ve7utHrpzXf2dgn7ve8ffqv+vS5qsZP1NyvJu+X//r7KgSb3fsQSEPBNlY6cerffpir3vaqr6vpfXp6p9K0aCi00KyW1NKhqYuKh3T9bPu9viMI+F7DNoyYicmvMSDsUyO/nE4akUuUIcb0y273C/w6t6SLt3fV9UYr3elzSc7ar6k3qb04gl72n6whu7lObzw95cjLjJQWEi/v40gfcmY9wK1L2Vmq9q2EXPz1PB2v96jPckIms+Oe8ndzHFcvk9JbSicSJt9ymzL7lbqVQhys7yDuqdEMW95fXkXJ+vl4sj3n/1IL3e1kr89/1dPv1gpEXGT9bYMKERvDrwE9NSHx9F5VSyCt5fd4V8QSXeb305RJ/Eve+Vl0tkqnUnuou7fW4TLPfe9dERjXfWnRL3/ZaQ3bhZ+4g2rW5dtfNy5SSpfEfzCT+fs+Rgm3eHHCq6Z62VZKwzkkED+U9va3K5dfD3xcAAASXQZvgFfBZ4sUNRHullTl/1cxOMzFauX5N+WWDjX/5ePfwwvcEBIcdIEm9LwUQbtHuK/JcrcC4DdfqS3f40uM+vBiRPrb54INy8uzrdG2/astOMfozBaafK/tsrLGSYzcolbtZeH9cwCi2kB93MXcn7WnlRjOPQG0ck+3Vy3BGd31UTHRYZ3V0FJ+Tv8VrXV5f8qotopuO4l/+y8Y7CngkEUiBtpoyb/GeEvBLA6yxuuwxPdZ4+Al80buGBJecPgRxJRvDXy089csutfiPEv+9hDl9+qDnjFpK732d5BL+NtzDbmsrc4Z3B7eXjYg/1NOT/69xBfG7mVbKo1TlgkvCRh6/SrRYSn6BYegxK2//LJj9PVZeT9PLy4V8YaYSd5nBFvkQ9NBpBNDMN8g6qRcNM++4KyF0+7sknlxK2kwZckL0nftZOXzi+Y1+MOdlKaVdmDpCve3h0p7rsrCWaR7xumsDdlddG7vyxRA9Lz8q+UNlTv319CS7u92QS8E5A4899scuthfpiLiT8MV/3DiIwi6O42yM3AQ+rmfS9yjrXsBMJOaVGUyt18CXrhsGO8kYstF/GyUylJFbjbMhDjd3xgl3IoQj8ru3uytGwjwM3cddhG17yUO242UL8vXYmCmjdGUu7A8E9i/BB5Ye9q/8PwVYLctAjWf+SOgpYQfgmnm+/HohrSZ41D833+GH8E+AgedX3pZ/J+16njJkDhyTz0Csh1zPszL7e0pAJvSTm5qrSGwAmvuV/1tQzwSDtwlxNjk9fuGhd767/e/QIt2ucrm3eZSNmBk39tnzK268WJwmWbvNsJdAiEO/r8EJtgviouIawpuHyO1TZLGIWZTg/vDjRg0QezNiv+4Z0BuNZdGAu1n2Hx2k6q/TQ/MeZ+Y84cks/1699tZnrNbCeYNyLyxNieKR9gjgdcI3V+sWC3gp8lAkPK9+oS5QR3t4sv/4JDDKd+XZ2yu79tLLvMSXH+Ziy5/pnr/BPMLTi7vd3O217WkV7cXyEAXf9L3j/4Iyve1eS5fhBdapPwSGHqc7eWCEr3du/oy7b6Mvb3k61Wr3eqOile9LJUT533uEPJvMz8aR3tNjPp2WbsZ0BM7qrsv+UJ93d3P6fwSFNLxd/ikO3e7819L5b7+la6Pyeqr+buf6zXvtVd93v8Ftu/d2hHw/5fL7pzPpvrND0UQS93vtMqyndIrHt+/utNZvbVLS3u+2xqUpihSa/Myicdgen/CPiry+ewTPp6p5aGumyir3v2gXHrXd5ZPaojMRk+22JGfX6fChCXafbuORb7236nFtr9Lk7T3pXiSBElyJtSmnIvfvyWUHH+hQlpDSDc5ON62lPTROT8Kf6kUJnHK/v4sKGTrnzzfem29GKgiJ3cZnPu/shGXBfi+PT5UQTmvd2SzPfeOuby9rkJ8jGCBvBIpFwwk2+HecC1xeCB84tUiQsoYGnseu39T0Ke6zIr+lSl9ifWUTeqfqQllfpwr4ilfJzw0vzELH6VHTreXl+2iaBEV9RY3tFJe9dKa7/Jhf1In5KhS2f7qOduS/iLK6V0qL6r8PfGwAAATqQZoAFfBZ4sVHNlxuMqYlk1l9d8xNsxsMl/9wiTnfKFnWlkNOHW5Mf3HFD49iDWZZsDWDMXjBe+5YTYvJ/b7nh7a+c/jKTEDUZaGl/UslPk92xPvFG5+7S6GQXpJJ757ro4rHqEK35cXl2vaBZuXN9V70r+/LYV8xrl5q0ul/t3G5UM6QC4vaHl3b4UcvMOguQCO7ZWW0STLpq+/R6XRlK35k/ImPFpQQ0UL0/aRW4zbzdFpJu97CPhsxunAz5efTRXjuGr5qCPc4PRTrdyt/hK7jLvlnYFpXycu3S+S+YNSe1Qll77SdIed2OXu/z87EntJFR7agol707l6cilNuJ4q+9V/LehtBMv77Y8Vw7sxWW7cS0WwgV3VWWMILXo7QKeKRJOCpQvC773adtL4mXKC/osYctfzgwNTj2sfZav/J6S5eRE576U3knXuL4R/LU33u8b1dfX1gggj6O/24TC6JmA9BBrKDdNXVSY2N919JJ2U8dyB1n220oy80efWmfmZvgrkBkt7ye6rrie93nkyCXgiNdrj1vjrnx7t3OXROryeq6T4IJrMFkmCoMXmItbXglGuVDeiqqvdbv8x7tiExq/+EZwfDK/LgkNnS24b45BvfjCfp37gp4QccMMfMavnAvpNH36//BH2bv39/kr2l8fwRmYt2vRqWsbQjoYI9ibXkajbMnKow5LmQpSo4PdFbr5Dfz66+8s9uda+a94R8GGd8j4t/h+WCpJ48oK+nWthNzhc/vhybNINti240lzEsggomzvTpoIkm7DazB4fFlT3dNK7q/Zw//EPrJ/3h8txK/vV7CdmvFGbQUcGoWAzjPO8PXtfDbdv8Fu972YdbT+ECOWq8+9yXS3hE7vjz10amJ+lxvV7go52IbvfXvhr3CeO07v6OgpduGm3FZ60qXLXsrG1xo8oIrK2zBtY6TGzMeluFPD17Bqu69VZizqv0Bptq/r39uUHB3dWMWenzd/iuZAh5Xwi+8cbYz+tXfzu5PXjvEzHciA/92KIml9aTXxhpEfv7cIFMM93zj90w7ezp7EIFPGwiOz2icV7uPhHH5EbxF93fX+C7Bz089zCWzbtjIJbB3mPThsoXYH2O1BHulZpLbFXd93yfbZGJXYg3h1ClZltBd3S7Pfv1Rb731IsoQ8NZV9byw/0Ck137buXHLf98s4KC3dXvfaqKILKeFO736lJO+63ZRv37TEvRJd6+GtntHh80EJi/KEX6PE3fKrK76giK93OBHrJ3cJP3KIfbvSIQIlEP3ty4eHnj2gQ33Sgt17rEX3e+mnSX51ii3u929b7vrFXfSf+/M21P3e7y/30Xd/ZBVN7u7l4R8EhFl2/2CTblf3otL9f36v2frLS9QSEe5B7sv/0UTd37QT3u9N5f5VIYt3wm9tQRmffpb9adVr8mX1XI16E/ECQ+i4Hb3y8P7Y8oLDXvjaTx1e+uRkBGJuK5J17ZXuPFy0onl5cqv1Bdd97xbfYUNOljInhuKQUOT2ctajjp4NL/hPx9Jlsvrqo7edzvuSPf7EvP4Tfs4kQ5sgKtFz5kjdvFnyi3u+sxXvtoSyym5JaxN3vlzJ+vJkXTRTu/q0Y4NLQjDCUs7JzV1iOCMu5CJQW0tI3d/knhdwxX5l5Ii1eP49FL/kkkp5KckRPoezr2Sf0Iby7grgAABHxBmiAV8FnixUPM92knGknNYC9OUnHffNpGuoM+Yl1DsKZL/7hHpHGJBV0t/IjXK5juvwxF2pf37BAUw+8sh4Oi/1zl6J3d4JRtST/+FOcXL397bTcAN9x3iPtXtGuvcPk8uVsPZ8jPa3CWT+7TMZLw92PpT9llCt+W76y+f/l9IRc8J3fPB2iA35eSEKr3GiuEnGEAxVilLcz06zkt9Z4KzJbEVYjvkfPsNZ0XrZcGStf7hAu9OA8R9vPPZAcQfDKHA3AxBFzdw/rETbbA6esEn97rf+YsGYr9+gvjlf+myssJcZq3DwYlcPVdPGI71X9njL3eRfe/c6/xxV0lZeSa16gl6pZHhuLHTv1CfmNxXf43w/BWguOC3UTe0EgqELhY/NhbMu8fuxYvP1s+E56R/CBiiO658I19pyPMPgn0r3/8eeXO8gbSu41dk+3/yyuoYupmye3W715JeV/Tid7u91RUqVV7hGZYpWxcEA2rchDh+opkpy8l5BjX/9u1b4Tn/zZW+8JVrztcJeCc0+547wZfu5Cxk/NLC6Xy24rOdlp3bv3CJE7Gfh1pyFZ6J02vwY1pvPorBYXhyK8eMw29w7YOBGYiJ1VqeJo54u4NFIhj2br4b6+xrBLtMGfnH0u/e5vs++ifX2v1gn7nDsIvafL9r4RtDB3BRD8FnXfcV3e/aCkdFylEoTm760vowJahN6Zo6oCFcwXrT7/bc6wQ2Ovtl/y+EfW2YLM0IbT8ol8nd83P43reBnIAF7/+C4hQjWH8n0w4RX3f+PV40oUJhl7AME6aV/eFzJUkjiJcvXFuQXn41VGH9zqNu/dihtdtAm7nl3cEslbYVtjd1gkO6CKp8NPikQ22Sdf62vTQmWCwodkb+8gm7/73C8GY7398EOX5L/rLvUTKvAc2Yo3hzsQURXZf2r0syCzz3C55PJCRcnz5SCPmEE8n37aL/0gVZX5G0SaB0qozQe5fgk3r/9Xqj8n9e56v7r/L4j161wkQxuV+cL3vpvsSq9j3pwh4IwhTvSj8FJ5m0xXvNr7fkzU/gku/lS9yFvRUuoITFPP4uxbRcQS7wRE3dsvru0Xe9b4TPu7u+7/opAnm+9/3efwh4QEXcr5lqR4/yxhXvfd3L73Mvf64dHiSu+Tb6S76xF77v735oJPm4V+vxW95f9P8m9+mJ7u94R8FZLy+O0uZrvX21y4Jcv3/fXtFjdXb6vqil5/sT79arRfJJy8n7aVDagjEBuf70vuuxsJC3cvu7vsiNenveoR8E4g/l+N3Lf+tRN9u29VfVVQn+hZ7tPoiJvfS/lMUOz/S0TCT9MaVy5Scz42cY7OfxLCn+dWjN78oLTO980nb7MJmj6/J6/J70dMO13eX0mFBTvgh+fL5k4t3LzkvvcdvkCBUOfuUL3zS4T8mlNvIQF2e1lukeyJCO0rv4mYfyesld3/jJrv7S3Ri5DPDrZLtaIXX8LaiiZpyX7+/wUCX3eidIpPq29/Xk6d3Ld325ERlpP8jhf1In4i2lUupZ6AvgAAABNhBmkAV8F/mHXGob+bpNBjwiTd5SpenXqnjHT6qQN0V7gpLcwu4ccaZNDWl5C7TRb9MFfjee/TOnd8PwBFhJnyeSb17gnJq8JmHmbFKVbE1Tqq9lXf4vx3ifl2X92lhXzGmt6pf3tsbPOXjIEAhcF0GC7xGGmX0hDeZ/RK8W3b9RgHwKfUhbDtjJv2PU/crgt+sZ+BvnMdJgJtqPDnCd622hm4zdfbOJ/6N6CmqeX9Ydf5YhHhz375r0x9b16UdZ3qXa0MX7CJ/daeuvfcYV1soIhTKGroqaE+8DOQ6LNV4lfJ92vbjbgrnsGenvQTbFUf65o/0N8j9/6xt3a05g/BN4+EP6MQmLE9Ps92vp8kFN5i/LhrGFO/yxnuixHfkmlL0r1VqE97ro7UpEzbscKF/vbCIp3cdpKptluxW972N9srEgDWXHd/uHBKa07KPD1d1Lsfv8i9/YINLRnOHzFbbovKc9uMov37Q8rGva9usoUIPj5o19sCt9iWEr3hPp/+c96ccEjS+nE3OVfe+q8XfctbL6cpd1pJpwT3d3pSkkqk+vfxYjKGg3IxA3ZLkST/grXcffd3d7tb6sTu/LCE1viCCstHu3Kx9wwQkA96rMOhuvDcs9i36LBIVmcaDE3yPpOaXSEyj2ASfnOf0yBu4A9HEV/guLKudejpU4Ne4vlHQm4+ud93uCeUBOUkQNx2m9xJ6VHTrQ4msMtF1HnOFoZe3TRVgpp8+SyGA43n334IaORz7/lEtpvCNYIzG+9OKrBVGwRG4EZ0e5Suf8fTgsIGqk092J7I+yt8APbGYUt+RWjt8PBk/SV/BNtS1Pzn/VunDNjNH2PpxZcExRrf73jHdCiLkgR0KfLpxLBQdw4lUfyzphtKlJ3JK/aC8Els+DV94EP8dnXu2P64fyelvrY3udIOileF3bvuk8y4JlVHcd6Y+Cr7SfEkNMjz6Ge+SoqxqDkpJ51Wt1EHfef3CPixE/t6b/BQXdp2N7assIlBOQ60dpORf7pwUCePRPjhdI700jfq2utXrwUFe+967F2bPMoM015flr0I9grn+7T7t1ub3LGXb3ve7b3/ECWnd331mI7+y+iMpX319YJeWk+bZga1f9Gf8uHmOX+og7vc//5cve+sI8wgQVjfcS/7Qword3ckn3d3NJK3uyz1fxC61fyenCJVfdru+lzaWu+7qxsdR3u7uf/RSE3uEvBhl+P0z3+vFf+Q+6KsTSTeivVUat/UVl/d+l6+t8N9HepevVCO7oJCbu9729PqqwlcvvlyEfC8Ousl7TK/XSou5Q8sE5J3Bi2ky+l/kMIda/CAl2zwfG7cVvFG+xcSeifP1um71QW7et829ZJ6WHpsTUJSL5j73K3ZPv5L3fVZYQlbvveaR/20S0Cndma8+QY8su00XA/ry6vnsn1VEzbu7uEvGEG7lcIfMTmcJbE22/Hbn+9skERpfd8n3n/lEhkaH0LHd4y7K8hVlzetUg2n/fv39MVlx6V76oeZy/Ee99N9Nx8VksZJjcnpekaone3b/9OFCf2bfszv0p8rFjWt9V96kFp8Z/VOuSKvHX9Fd9OJRoI5efHs6Qt5MXR14gmb3P+n2wRHk+nHalvfs3ySX3l/JJ/2ULTH/wt6MdJMllj2nvyb+HvioAAAExEGaYBXwV+LHbkPjXlTRxdwiXhJrysBne4lGCj+YxSWHbl15ev4Y8X40ZTg+0Zwr3COUVAkeliXj+AQaeDM1VT5bF2LvNNJwdlwPaUfcOxr/Uvll5iLzf9z39wTzt3wXYCpKWy2stRlM46/inXXnDsbWEXBswthC/gxHUEfp55cEo9VTquR8vvrX5S5zbhVe4SGAi3Ja3qYEzu07ekPnOxwidiQcar75vgw7h6/u44J7m9JW/+4ibhL/Mb6IOdxSvUSW7op0Idh3f3dVJD/cuHoN1+4is6+dR1vRi7vW6l8/Xl5cD2gJeYlKM5fGE4BH+7IY373CfeuoR/0Mz2elfMf/xsIXvj4GU9er2McEdlrlmpGImfNj+jJhKw7F82YL/X1Tdnf2EuQHkv6oob+CgoT+TSJft4fGaXyp0WJmOHm/5WNfYvjX49yOvfCV7uM7/V4uEymZe7yFCsSe7nudJgk6QD3ZKUo00e4sR2QlAI9y3HfgtfqmlF/u9E7dqVY7t+T8z4S8E8q9joyN/VMWJvtsZDagEQ9uu9+rJ4x9T3ma3+V7mTm7GbL5fV/Gmp9pFC2bpTbuTtAB166np8alBMXEkNSnPF+jCF/U9akitxpV5KaOd3O4Ay6xyv8CLuMzPtKr9M4cbr+v3Bq/vzqtjScS3rpmpoVV4mrabcgMPehNFxfyO3S5YJe0dw60cRXlT8N7mCLwyo7AeP/dnOFiXrJBUbctWKCsfe6dAGH4NJ4tDd2qULYGHOKXBs3Vko+K32h3xH9Pt62ZaY98n2qZ64eI0Nqc7VtEYD5Q0/By0f9Or69owt7wm1K8KCB2n51SfKvbvhhTXbrBAabpqtxTHRfx8UvxDuAmf/q7H1/qFCq+xG9nyf2J3u0vnWYveeg5y5hj6ufmnUBi/3cHOoIykPZ1r4zRi7Fw15c7jK/17+4oieTz98JWOPW04I4CFVZ6/sGZb5T7DbPdOCEuVh5b9EhDyeXov3SRaxbovBEZu6uyfqZd+9PWuxcERZC06V+j3nXHkTk9tsbd/ola3eLQRK3ve7v1a2IEPna30SdLt6q+kRehFb4Tu7u2Rmnf4JS7vl3B2NL3+VdWUr76sIm5td97d+T110CO5Xbm/UEZ03dztVZLqnCL7sWI5/u95CYQ6R/e8/e6UmwUF3e7/qrBJd/uvqlrr61fr6SX+/6d7UJVir3bvPiaXXWjnBtcyy+r/rvHXamChfgXlnr7LNd37ogh990U5aQuxeT1TOvzd2V1JITL79KEPC8OrWceN3Nr8VyKPQSM/fhl7l+VycIHtvjd1dkr+mU73LW8qT9okud+cup61/W6gi6popVKZlQm7vuZvzP7KYSgUfmx2Ad65cQ+fhLxtGk2ZFbSl5VwSd/vavF1vICHe729f+C00vdvsnBmo3449zcl8/907Ky3PhtwLAv8Micv6vL//BObTdO9OOxd7v+qYbrc3kzrtI9IIiAD/+ZpwftQ+o88z/eB779YU9y767CR7vef9N9/fk+ncqJ1SDV4nk/WVdQjPFDu77dXvyf3avCzrtiNV+W93t8VCQk/736+iTFve1cQjctTD1emEiFdy5lh5LOZUsUMYiQQpN5fETfEdEyUdW4deQpMhYLIAAAEm0GagBXwWeLFblxLfuUy6QbL/7i+HoEYi9m5uM4wO6aCa5fy3TGXSsJgi0KRcuG9nR2KYa/ft+8v73gq5yJ4+8OxdcMbgUnNbvPKTeVBvBEUl86OpP6cvLBHfcqa9VR3L/l4u774rCvhwkwUc34a+X+Obl/e2xsqAJO2TKwRgomXCRe1Tq5vej9wF1c7KXhy4Bdzm0SWuHjcH7y7EGv4txpwUFDc3Hyekk3W4f5hZyh+trELv4QatbufYk9tWe4NB+3/gSbadw+o30nu2V9uN9DPwL6UfJhSvrSl95go9r4Za8/3TRYnnDb47YNW6S3eQefpL1Sq1ej3/dU66bEnalhHyD37sj31+bkj+U9zLsXCb9wiMCoD48ZYxLQiHadb5z3/GRP/ktl+h0b/22B+oZRwbpacPx5PHLAnXVnOQsyAC8rbShy+v1TvegR9itpaQW0ugVlhiX5asbDPa273eVNLkiITfbsFveQGckIzHjx8NOt85Zv5qFMgIP1p4LS3m2X6dS/kl4Tuf/LMdFx+CARMnP9qwdkpjYlI81PRP+5lmuv3ChXoHZYRcnZf7dgW7VKpfk2pwW87dwTdzHnoTf4gVMv3blBPcb7/znzQRAay4h8A0e6jHHbEZqSaDj3Fk/PqOGSa/L/QUn/MJ43X4aUxF4AraoTty1+CbwRfVuGFtIwSYt2t8aXHiu84xDbKfelu6m1L/R4bu4duigExG//97gih3bNpJ/bNOn4UuBzgJgpyfMO7WgfScVXdCeteBRsGPwOPwoZsYmPw3501zOiRFcgW7udnSvCfo+HRWCsnu1P7xkuisdZPtuxb3CJCe7p782WQ33+ZtQhd/f9YuYZTs9u+CkqZIz25ff5q9BlFgQ/LnnPm77HOm17p+sWUMy+TAc8bevlDRzqdFZZJpNX1mJuBAuTak9JpLPwTeO1eBDvG9/ZRbIXuyn+tXv+Ezu+OmfahHxYiVhvar+CQsBJv15q//qixbBOThP2+bI7aa8FYt+4fv+9mH35eRO3FCA7e093v5O9J8nr7rr3qveSjnF25BEvR9GaOVPaL5f8E5L3unqEfD5Hv5fU7OpIV/8Fh93P7338ZPS/yyFng76btEwye6kLXDLG3falTyW6HP3+3ra0Uva3wSZ/PFwEfGGdvff74/S19p/4KSm0/unu7Wwrz1rv8hKo9a6/dW1ZIua++8El93rzFRJy+X/yS3fhHwuR4dVm/z+/1zwVOW51ymPvyft+XmLd6rCXkmTb1eid4r24KybvAdVy1s25zl+qikMJ3e9PhPb3RZN1y5OT0u/k9YS8V4Qdv3lb+FNPTvL7ve8gvxh7klb6ZO0y2XHf1SvRP013GpFRqlT+rvf1/DwgxXKDQN04bQqa9+XXWI5ALCXx5awzt/++nCHXoODxXd+tizoLwmX9arfUoIh131vMYyCAnP8/8V7s5f7FdoaMdU+oQvu++71W+k3zFdv+ESYEtWB/1j+f/dZPVS9IkTvc8KXl9Ql93fCvkx+zi+EDOj8u6r1pZuXMvqkuxO76+vdkshO70l0Cndz0cvux3S7nv2cqzsfgR4AAABINBmq9KQCvgsXuLFBB57Hj13OWeL5TTUw15smkIUq7fwQUNIeimLgiCAUvQSwyD86JhHn5uNC2TBHaXmdcbiUm1/Xu/UMh77hDP7vRO4bi//0JgrmHjjZcpKxeeNqfojb60udy2T9X7UJd3xM9o/P5fei8EdvVIvmlkeHXuXu9fZb7QU8OEpSoii8b38v7vjfLwnTzVkGdIvUO9RISPPeJH8pmqbpdra3xr6y2mvgHAwGfeuv/G3TANLUBrYOLXp2pLO2v1Gaf5e0NNYcs/qz+z+vcO7uATi+4a9lwwoODX5EPQ90f+T3ztuqFdyLyL/oYXluHrEqg2A26UuFHgytvyHqV1Bd3u5Sfh90eiQH2tFjKU6K3aacsHuy5KDu4rEw3nf7pToT8/ej5PSoVJLPF33x5P/lLUvwmX/3GDLzU53uaPab5OqErXt+Le4pL/7jO/U2SgQJzO85tiRL0G6SJLOga1/sei43jq03bOvEQAvNduxDdtT9nYKZb941foNyF8gvwoU8EikbjXdwke2n4Zl9gRtva+9m7TmT1xL+wTYcStfoaI5xMNe0ErLfudRSvl7vtQkW7Pe3b7hPPX4eh3ezwwI5OMwR3J/oR6n5UA7eGdu+vsIleCnhy5+jzYRak4sY8vBL7N6lvBGuJSwntjBj3d+zdz+7n97w3Rh7Fa4TufjhkyH7wSSjkzQjcWDl0LYn4mPwxeX6VzIERTlMv7qniV29QS07XHD0qr94LLTKbI7bBH7/vkF+EfHhkN7jTYclV7l+R1EYq1uUa/T6tsg07L9F/y+E23uCEpuvpp/0luCAxl+OMhwTxDC+r2lkWh6utf04KygTf7n2Irb2kL0XBfaREv9Hq/jdtLiki5ZPSSf3IYg/daXFezwSHLMyL7VZYIoLs5/36GxRDOxwYcgY/7QEK5SPllDIN4PXh2Ynp9VCPvdva5aK7pQRELqUtXaoZsSJjIlc4/c60nqvl9WeY3D3fbyX33ghnf/ZPbb0usn7iq6kJvvHQd/9lJ9ovQk/wUZYvvd7mvLZ7v2ld6NB39/mgtu4ZRd9vugLT+u7XtvWva1eEOwT20isVG3t3Zf/K1bXfXgjLe8X2Td+hNa8lWye7tVarM3tYJ+7w1Eaxu1rgi07xtUotKynySCt73fL5PfCHgwy+ZluNoI1fJD/ZDPfywRldid708mhRX33fWSt+tUvebu+j+s3d1ZUUhiUMXG/v5CX3CPgnoEiefysQl6TKfygrub96b3e9OjO8nquEP9fS9iO2snvpuVS69EZ3vCT8pRsBF+dpv2QhE7g7epx3+w6LiLTh56S3l/j+ykpyS5EEBLz+Kz97rfthPxwS33k/rd9i+XpJ53k9KlxGtp7kEO/dCiDUL8/z119AqNW6QI/C3h1EV1Ko0GIc3lnG9cJX3Sd4UyXk1/kmI3vW02UXcv6Wc635JiXfe5PfpPxZ217r+Qzyyy/3ZPskLasmetaiRO2txnX0J9+uyS7rl9NaUJeMrG5f2Szj2G9j8M5JBB8p14go3APqnk+HvioAAAASiQZrAFfBZ4sVu9J3+Y3HphL6F4/Vt+Pf5S6CCfjboML3CBuPcCCwZTV8UH57zhqX9tOhxY7wy0OItNFJOCna8gkiyQItp3C8+XL4Bfd8oqL5bw9Sf9woTLS8T8hVXYwlSvtCgxBr3BDd8G7ZfvbxRXe1ecfrywVe77uc/E7o/8J+EeXcI72wK+CQk0Q9FnPDJhZf3fBAQVhwdQCb3nYRre6Rspp/4BtWBMl3ZaBbwolG+jZG/vsqHcEj68MGtz/zvUxn+4T7NODAWVkvlSaWfVZWMKYegg8dvheYOj6Z2c0pMMdNDsf3FQxc1/M/b7giufZuikv1BPiYn5/O2T7VSo/BgUMY993vLc1X+rdsWTDvR3PvfWWcVf+U93QYS8wqyl8v/2NyPMlRrNrScdlWiKvO2r9ehtUEBTPj2nXfMlmfX5f76CBLKqyFdXm9jtw/a2skpDfExoSvrCPM+9k7zAsw98WUM218td3pflWuCCyBC8rzfV2HYcpAJT4S0XHQLj0tYe8P+6npalThG93+E32py/e+sTcve1qPImxNsJeQ133+CqfokmT92O4RzK6zHftNCWeCgkDq2tns473NplYtjT0ZA60Q2hh2wjvgNKf8MvbgS2VlVkF8zJMPNmtt7h32IA33zcM3wl57CSVeVNt6lm/+8EGYFomDz73d1Nun9X0CvH2veQZPe75imkJyfgq87QdS51+4cve9ttC04UvDydD/jA5Mks1uEGo8Fj2WRLZmNYxY28cQSwXiyz9lBk+lot8aRr76JNjXiQaF/e8geHy5HAT/eabgi36/9YIaRPjfbXyCxbl9z944R8EgyrfqrCcrMFQ3l+T0r3JEwkSaGvciYOwxnp/bvlhf9NZEj5snvTu5aN2T9J/0d6Tvq5rFPFVwt/JHgO8kLaF3BVvy+fzj8xnP0699ii5n7pwj5hC13XaK21pwREHc+znXdFgoFhqK0/uHF//T5PaWu66wS43V9E9MupTO79YIs6u9XbkJZH3o8XZEa8/+SEawVmI2ViX/bJ5b8qBaUm38u+Ndy9awdFTHn8Eb8Hr7E9e6Gddtgm6Tw5F0Ox0rvvt17b01CL9wVEl/e99/PwV3u973u/Y1o9dG+Zm58a3YR3d7T3n/pk0ryeqR/qrCT9f813ek1nrG3RtBDd3u/K3xHatZL3hHxXP72/IkTsn1Te2onN92T+lr3ye+rqSPK97vn/6kK73106pLSSthEQ73hv3fdTh5JJsX+Xa3iS3vd4R8E95Il2HVxn0+vyiOf73wRnll+241kfRdvp+x8SJe97+3u+90Mn7rsIkd3eWd73l9uIT2W8mhLwpfKcafBGqWP8JeWHq1/igO/iTaKP8N28SfWUmnIJEt53vulrNfftBsXjvZ7k7L9Fijbt3v1N5f8t36fd9FQIBAykPo0i4Fu/ec6w1+X2XofuMO/u7uf4T8lo8dZEKIXbmzHF78kSLk7WQ5t7E9vvpT1tJakI7vk9UkvmKW79U4y+fhYvvrglES4/nylVPti5t8z9v/a5JheKy5J67akkghJLVdOvUMZLyXovkjfvScb3xEhQ5o938PfFwAABJtBmuAV8FnixWcXdKyL/mNLY2ve+bidmwM+bZR5fjfD0t+4TdbEP9qbtJFhqdAQ5nwuc8oZO6pze6raYfTD/Z8v7veu3HyE1nyA3uXyrpXyykANpLHv98/eq3LeRPVOrO+Ta2lCd39Vr6F+PUvHl/2yYU8EhtxvIote43O6OkEF5/Rssy2tLZyxaTVUlXf4VHjVcBCf712mFmJ3cl99TQM2v/9/4T+rRUZwR6MLoD3TZkHXYO1vY3nkSyzuuPvOJPhOXWs83d+T/OUjr0g9Xp16J/po7LG/CfTX5NOJ7j9WEnAEuz9/6EesX/9C7+VbD7ak0kfX8aWE37z1+Mg5W9PjM9KPya/auoWr8fcPQbr+ppK/0k7hWUflQPCM4X/9Ljuv+T9Sy/CFovfnjVl3W4vjvPPO795fX3E33LHHz+qvxZdWsuQmX/3FDsSTbiXH5f3exunx07EexMfCPYyN7ptcweTpIODWBF+LXsLqg93sr/oel1/+lrF6cZLbyXk9JJpvzd31Qgrgm9P6/lrpy+a6rXJ6rZNZS7uvBYY5UoalWypnrAW/DX6CU8M5Af6v754wn1TTQnff+O+rlsXKGoddPd8Jv8FRI7lyJz+i2Wxt0DtM3+9OvxpH6v4fRRhEYTWlErcN7w61gm+ha4CT9Ue5+vw8d9bhEdEgcWq7JXzyMG35T08rQQe08OlzLSJ/6E6SssLYPGwJ3+nG6oPviTeNviO5WjQl+UtW+ELafqO86wFX3JaRDo/YmQ5G/fuizwiSNoPe7jbo/xtwezjwim1LiL14Ba0wOe+C3iTyVppb/ha4dz0f1rk268KG2RHz/vT5vYOUKfp9x8PVI53fd3vUf7/hLwQ7Um2KorDmOlFyXZ9//BAIw1+OqeVqx8SurxiB0RQ7/1+8s9jWJ2ep/95wPoT6+sEZ7kDe/X2JS9+KuqKsqfwywrdbgjzBtcPRyfV4ISz//CJf9cohaofwSFcZ7v/p7cpR+n6xX+utkl6/NNsn61rrRe7GoeZ37kUoVveX/9Fy9+ime9wltgmu73u9zsawQll/Xv5v3VP1oj9e7Fbta5N7hHwTS+M0o6jJww6BR2/wpyY9y+58+kft5F5av7kLl7p++T0tb/rNu/X9O7783l4R8Vbt3lY6lJef2XK8/7otxR7vdyS+oemq77nzeTKVemq/jZ6ammwdvPkyJxvblZfNH+4Qve+7363zOILayEvft/mIQcNgJx/5O3Y+ECu9w7lsZx+vvo3K5d+gRFcuvjt5IQl/0zrz/CPhcwacm/D+XzJsPjqXn4sRj9N2/2Cg7J/ELG9KraIeldOu3u/XL4ukBN1L/GcSsbP3t/uXyRBhIv0/j6B0efulb5fvxBARkq52XMn1WWuEBOf3u/LH3WWIPesuLHr8j2u+0nfdZUFxRYBleQ93Dr259S/6RJ/0wpqGdR/Gvp419L2xx88LvefOqi2vI+xaZHX35Pprr6XkiCjuPq8rvX8K+Qk37ytSEfSvSv0iCbsu1fnzQj+Kl/3Jsv5JOpmRBnyUhHDM/JEQx86b7lEH3t/EdkQlZL35LtV/JGF+CuAAAARjQZsAFfBX5h2MSu/cIl55bvMSdhz5TSkp6fN3KMhnzeEPB6aX/3CPDnmAkiZy+hlGuxo7dL3CkPsSvwnQbmPJsQch1vbkL3CF3yqPgl+PWP9fmJdIQqNieq8pwo2P1WTC3gkJkmUJpcv7vhEgrPHAjcbm+KwTfM+CD+UoQzP33s8dLHPkrh5f73CExcry5eUx8FHVf2R4f+HpTfsq/EalXAh286/f9fpT8OlzmiqXG5NhMI+P2f5yQ7U1PX/4Xgu5Wv5lO5aXnM/1TnidJO7/ySaZm6TnSRbu5B+X39/uEvPS/4R7C/TG5eawJDfpzbjdz1edhwngPqv+6oEFl1k07WfXAbEFus+pGxR67im7lgbedNvpT4yVlVHGHk847eu2hppjtPgt+gfZLA95d0f0stzfdnsqWr1WIlfYEWvnxVNMn6ajh6H9hLjzo+mjs8adhU5NNFjQcdIgTccE3vrrdwH/+o0fH9H7y9EWfuNAy7Q1rUweSL6pPBbIzLYEf8V0DGLlMg+SVFLSXlvg7ZPTcsW8Ugtc303//PxeuHuly2Or/TYqCJ8q1u3460OGZfI+nDF93OXLmWrcPcn/DBc7kWWbo1X7Z86bE2ghNph673d8EHy1KciEMaam9w5C4uw67m29Z/j1cShiRSIBHrpHva3LSKjrh7m3ZmP1W0J7yAfdPOSbde0C+7u7uAKL1WreKww4r+E9sFIp7d0zhv+7uX9unwQE8fYw36ji5ecgovgj0j3yfpEX4eO6i3217AjRdAZurfQSC3rH4Y3v6Xwp7cz8B/uYfgheXUxRYpPTd4OqBDfcadu3kWC7bflAqf1+CKO1WKZ2x+Crjx+dBhSrcRLRoQwdS/2n6bBaQA71oxL7zX9qW4Yf3CL/Rbwj4I9O/ykluCLe8vcUaFx1MrTxck8Nj1eLb13OqRRMol76aH6IIuumr6sakdsn7bXr1QskZnQm72vvKTMU18gknrCPlES+mqxWOXcvfuwUHCHxx/NeXXpJ72mpZuXdtF6915PTa7/vFEc0i/Ke3tOzkRX6LhLwmIe+r5PqtefpwRjX3rv8RZ8Iv6+lr6+/stCn7fxVXqtXe4T3d93CPYIiPe/lQJru93d36Xp/oEZ7v7quteye3fYrav3r/3X+/oEZHe75PpP3EkRe617a7S9CPmlYlYrLLe+T6+rb9/aV/JXvVXeq90W+76rWRWrjUi9ra4TfbgukZmRXv92JlO7b/XYsrKSe7r8Z0k2QhNp9Vy6SuQpitG2XCfj778Ee8N7bLvcZzPbG7/ewk4ry+/IileK+ilCBeHUlx2YTLl3J79qT9iff0vYnttaNd+T2l/JFGdxDmNC0Nl2JydidTaqmXX39MaEfz/hTTBIEi/9k9a6tRI3PLe6vITn+nJ3eT6Tm8/J7b/iPVqdN9kYkt3bLDfaUhLl7cNLC+oSM6Wr1tM3Zb0+T5ISKfZL5rSraosZMX7vZAREvdOq1DWGcRJySrJZXD/7gsgAABFRBmyAV8Ffix3LWG9N/lKs8my1oBeJ+UjwVapOgGS/+4LySD0bLiSVMJHBCYcdesf9xpQJ17ka7dntPSPuxUx5TJEfFeOj8O8BcjyskOM6/iJZcWkyzs1IrJo9W+LMYbyy4Zh0dfgj4x44WBvvLBMfPunIho1Un914nvLxNwo2LS97hXwSEzBsbyTZf7dsaTNFxLgdnqEte/ysZlD4PErKg/z7oDDnZrbrOWRwiZ/gzFA1o8NV/3G1bgwb3VVbw7NZu53440XXtWMXZ+NoP01njuoPOrCy4fvOM28udUZYKSvsblJWEkIdATUPGV7rKmqfNyA4vpJ8X5JnQGHvpySaZy8ntp19Pm2lpZL76yn3KSCb9MUOC7S/BNsn9sC8v122ECd35P0JQmcIkOyslocWo/uUrvn8VkFJfDbZWaVJiT68tfe+Xh9bXCXgspn4zj46r/0xYmX98sFU4uaOAm/b9u663fCNlFt/fFAy+l+GDFkdh09uAK9qtjL6l+w/cb38FRTRoMYDh1lZFzU9jBpvt25YOe4d9grgzHZb6OJSEPiq3ETcLDN4f9i2EiycI/I0m7v5hh8gdf20Ntgg6OXGOI8LvXP/x19kKTQcHZJ11PSVPP9k96G+jof3KHiPH0y/pEtS/G3paRdDN0uYqxghWkWENnPNcAhV3uDd6EsR7o7R3j9i086D5rAid16/HeV42guzu6RSuBH54U/9FX5RbK7hOisw6Ws/tJ8xMNRbz1i4SYZcvCWGmwMVk+l6cJibvtRs/k9enWyCNv6+kXuhNFrS5vZ0Ym5l7a3GZlo4J971OEbx5ElacmQSb05SveEi/++X8djiy929niiQjeZ77vdmR69pvet35fL69utda9k9a99HrL+v9/a7enhFcuMEZfN+Xtvz9fRS1vJ739/vfhHu+7yh990VZP7N3Frpe/2oRfs4Kd7v/d25e3tmuyf6rfWuU7v6PCeel3f0/Yn1eT9L6wREvf/ZZC3d91+Cfe971rdYQfpAnu4rd77N9o4q5+nd79sXe73vo5eq6svd9fWruvycnttif4MLvTBPsb3hp3nk13Ln6NLH3p/eijtk93WRVBF5WD0I+KIX4+Yt/zj0Iy2pqMOOZTmRcuvTrsr6ryenKJTfpK1eOoPeI+vkp0T6SJSHd2y+9iGEjyRC4DN57Ng5pITJt9N4R8hY6v9DSN51Jqm/cZ4cVLZYQu74ib/nEjcbPpwRvULJL3THcdsWa/cny7e/LDol5d5cc9+3K0V3/1BDe7pg65PWsViUXpd1spyr+mb/F3Rvapdao1VLREPEPu46XQ20dY6mEfa4go70rNKysa9vcKL93n5Igl7vfX0OFvPS96UV5fr1L3e91FXugs/7EwntvPFOT8nryetU91vXy+R8IcL9+SFu2lhpuWts//35Pev63qa7u736gspXw4LI/b6RdOF/BDNrWRPJd1+SImOn1DzwutakpagsgAAAEYUGbQBXwWeLFGCt0jSStKX/zymHH37K8vF6lJ3ml+buWIY82O+p8le4zzZnJFgEGbAzujx1rL3jcIe528qJ5B8dS+46E7rfbxnrFkip6q2u4nZ/54Xtz8FJG0i7fI8MLlMX5QdlghtrwSj8JHk/y02JhG+au6TXevaCfn27/l0iSwp4KCc8MwhILpd/jCctAqMYeyC+Zi/gbs1gJW7AHAYv1EmjHO/2wRRllNET+W1L93tCbRRClcinsNe5gv9bphWSXNQ56nUqvFH0N4p/5PpN26KwoXMPbbT0P3UFL5pxfzj+MtF+FttN4TxbvLHywSTho6XSq2xfHcfE498Z7tn9pru/30m8hefkH15TzIE8Jv3Cg7n0V2W3nzfhbcNuSWX9t8FROy4gP8ma+7xvZ19+jxJSLnQPq3psn00XavrZYezf9OTd5KLFEUJmGVfAl7v8gSXH4zWFW00X8MUXf5aFLQwfCXgv3nEb37H0t/+4UIK3u93u93f2T+rVywQbuOj/4J/C5O0LYTZHjeCFe/2cDfmuT00s/cIzr8ht+WI2iSde5P0iP8TYk3aw0v/6SLO7Qw7yIgS/VvEfRESG/e8jQ+e2/73v8O8ZOT7b573bDy3l35Kwy2nY2QpLa9/4IiTqVaCkg/GSODiS1DLcyX/zSJHfFr7hrYDENr/1Dk4zZLF2i9jTekUrgNfxJDF+htp0Q7ByBoEG1rjPZLg9x6oxol+zp8/pYTfklpun1gu1Qiaubj7pkb6l3sn0mlueEzbmq9ezwVx2/rRfAYyA2tzZFDzF4Eb8WPd+CkW4aZ4uO29u99V4IxDT9zSvgjO5Q0/FqnLRH/Fbzlc7hmVdZY24tuRvy/nC6stduCHs7rMqfuzXlstyle+TBde8r9j1CPgrMfZvP+9un/BCXNlmqLFwT6XCtLW93rafgmvHXQRcnev/ab7C/PY+96xrv+i+n/BHu/9PrXsnu2Nv4qQtnSjsy7wt/BDfFkYaa/KuQRu9zpHwj5TW73Wos/Lj7fm5PSS/dYPIii3Pj+nrcEQh23v6r1F9L3Cc1eSz57GoEMuX9qs0EN73GpOkoRf48l6b3vfsaWuxB7u73ftmpW6sbBFI6SPXf3mz/bSy1rblkwj4qf3vei+X7iad73y+LBQ+l2Lrl3mver++t+xaBHKLbuNtbdcvl4R8Lw4kw2O8ZMdZp3/5RHP9+oKBJsVtXhQavD1+xJXfvfRUEjnxmns7692O7JP3vQjpLkKWSXuuhBQSeNeKnmY4273kA7hyHWcLpwl4TjJhuZ4Da7Aa/wRiOHu//ryyn3e6X6X3IJ2N7dFFfJ68nqn8r7S6C4hx2Hyks/Td+yUnQff4T56bv6cKF838hnvvlk7E9dSmE8nS/21k9NGufPSiu73ffXC2SMhCpnK/Oa7O0ab5h5HGJXpXy+XPJ3Xspdmrk9pRMi/X5io5ojcRWZiIi7uXHb39Qtk/oh0rJVIksVyFW019z4/Xw98XAIRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpa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4kAna7SgYQIeh8uUdvH6PYUf4yN1fjd32rR/fL8E5N07rb1QtF5eXLr67GwREl+UGvSe69if0JK++rVeZip/uHbJf5MLLbwmIu7yZ3q+tpKnrQIT7uRPMyFS3tVckVu7gSIhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gYhS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeBiFLS0tLS0tLS0tLS0tLS0tLwhEUUAFFABRv/xClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl3gghS0tLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4GIUtLS0tLS0tLS0tLS0tLS0vCERRQAUUAFG//EKWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaXeCCFLS0tLS0tLS0tLS0tLS0tLS8IRFFABRQAUb/8QpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpd4IIUtLS0tLS0tLS0tLS0tLS0tLwAADdCZYiCAV8mKAAOKMnJycnJycnJycnJycnJycnJycnJycnJycnJycnJ11111111111///wXeAAmFEcIGm63wChQOU1oQEeEj84Ba2lPP/u7vw6IgATyCOF2cOKFpqPMANIgQwqMkPMjTYR88zMDUXZnDIT/2wMBVFRFyQ8o8AmLIC7aUBdUP35c9jxADMgEdpYBJkHUp2iKlZXx94+K8ARMxEOpH4OpLDpP8aQdXIO5Ma+G8bVvsdADZ7iv8LXiuvHTinnkOOSBqz8zMW1xGr/eFB8gIenZ4C5x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AAAGAAAAIQAAAAEAAAAHAAAADgAAAAEAAAAIAAAAIQAAAAEAAAAJAAAADgAAAAEAAAAKAAAAAQAAAAEAAAPEc3RzegAAAAAAAAAAAAAA7AAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAABKwAAASsAAAEqAAAAOHN0Y28AAAAAAAAACgAAACwAADXXAABrgQAAwYwAARKNAAFhWwABztsAAiToAAKY1gADEjk=",
+}
+BASE64_FILE = {
+ "path": "test/test_files/sample_file.pdf",
+ "data": "data:@file/pdf;base64,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",
+}
+BINARY_IMAGE = (
+ b'GIF89a=\x00D\x00\xf7\xa8\x00\x9a,3\xff\xc0\xc0\xef\xc0\xc0uXg\xfc\xf9\xf7\x993\x00\xff\xec\xec\xff\xa0\xa0\xe5\xcc\xbf\xcf\x9f\x87\x0f\xef\xef\x7f\x7f\x7f\xef\x0f\x0f\xdf\x1f\x1f\xff&&_\x9f\x9f\xffYY\xbf??5\xa5\xc2\xff\xff\xff\xac\x16\x19\xb2&\x00\xf8\x13\x10\xc2& \xdf`PP\x84\x9b\xf8\x03\x00\xb5\x0b\x0c\xdf\x0f\x00>\x9a\xb5\x87BM\x7f`P\xd2\xa5\x8f\xcc\x19\x00\xa5,\x00\xec\xd9\xcf\xe5\x0c\x00\xeb\t\x00\xff\xd9\xd9\xc7\x0c\x0c\x0f\x0f\x0f\xffyy~MZ\xfb\t\x08\xe5M@\xfb__\xff33\xcf\x90x\xf2\xe5\xdf\xc3\x06\x06\xbf\t\x08\xff\xb3\xb3\xd9\xb2\x9f\xff\x06\x06\xac)\x00\xff\xc6\xc6\x0c\t\x08\xf9\xf2\xef\xc9s`\xb8#\x00\x9f/\x00\xff__\xff\x8c\x8c\xc5\x1c\x00\xdf33\xffpp\xcf\x19\x19\xc0\x13\x10\xbf\x90x\xf7YY\xff\xf6\xf6\xe7??\xd7&&\xefLL2& \xdf\xbf\xaf\xbf\xbf\xbf???\xc5M@cn\x81_\x00\x00___\xcb00\xd8\x13\x00YC8\x80\x80\x80\xf3RRsVH\xc490\x10\x10\x10\x917@\xf2\x06\x00\xcf@@\xca\x86pooo\xa3!&\xc1\x1d\x18\xcf//\x1f\x1f\x1f\xdf\x00\x00\xd2\x16\x00\xcb\x90x\xbf\x1f\x00\x19\x13\x10\xf3\xd0\xd0\xe399&\x1d\x18Yy\x8e\x8f\x8f\x8f\xff\xa9\xa9\xcb\x13\x13\xbf00SF@\xb6& >\x1d\x18\xfb\xdd\xdd@@@\x99\x93\x90\xff\xbc\xbc\x7fPP\xaf\xaf\xaf\xc6VHzsp\x93& \xb7pp\xb3\x86ptPP|pp\xafOO\xd0\xd0\xd0\xef\xef\xefL90\xbc\xa9\xa0o0(\xeb\xb0\xb0\xff\xe0\xe0\xff\xd0\xd0\x870(K0(\xc9|h\x9f__lct\xebFF\xcf\xcf\xcf\xe0\xe0\xe0b& \xff },(@0(\xa9\x93\x88\xa6|h\x1f\xdf\xdf\xd5\xac\x97\xe2\xc5\xb7\xc7`POOO\x9cyhppp\xff\x80\x80\xff\x96\x96\xd7``\xcc\x99\x7f,\xb0\xcf\xbf\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\xffff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\xa8\x00,\x00\x00\x00\x00=\x00D\x00\x00\x08\xff\x00Q\t\x1cH\xb0\xa0\xc1\x83\x08\x13*\\\xc8\xb0\xa1\xc0\x1b\x07\x0c8\x9cHq\xa1\x89\x14\xa72F\xac\xc8\xb1\xa2\t\x1f\x19Cj\x94\xd8\xb1$B\x03\x07D\xaa\x1ci\xb2%*#3V\xcad\xe9\xb2\xa2\x9d 3s\x9e\xdaX\x93!"\x8c:\x83\xf2\xeci\xf0c\xd0\xa3!\x87\x12E\x89\xb4iR\x92.a:\x9d\xfa\xb4\xe5\x0c\x9cT\xb3\xee\x84:\xf1\x06P\xad`\x95*4\n\xb6l\xd5\x84\x06>\x99]\x1b\xb2\xc5\x9c\x83F\xda\xb0\x9d{\xe4\x84\x00\x83W\xe7\xaeM\xe2f\xd4\xa8\xbb\x03\xbd\xea5kE\x88_\xbf\x80\x0fy\x1a\\\xb6\x08\x92\xc3\x87\x01\x070\xe5\x00\x02\xe3\xa9-\x80\xc4\x80\x1cY\xe0dS\x94-_\x0ezd3\xe7\xce\xa8>\x83\x0e=Zf\x92\x13\xa7Gm\x18 \xe1\xaf\xe7\xd5\xb8+\xb7\xceX8\xf6(\xda\xa2D\xd9N\x8d\xbb\xb8n\xc6\x8e}\x8f\xfa\x12<\xf8\xf0\xcf\x11\x1a\x14\x07}|mf\xdf\x00\x9elP\xd1\\\xb8dSaJ\x95\xffz }zu\xadiLs\xa6\xb0&8\x80\x01\xdd\x9f\x9b\x8a ^<\xf9\xe9\xac\xa9:\x82\x1d{\x83\x84\xe6\xef\xc5\xf7\x1d}\xf5\xd9W\x9eq\xa2\x1d\x95\x84a\xb1\xa9\xb0\x01\x00\xdd\x05\xd8\x9c|\x04\x16X\x8a\x02\x0b0\x80\x9f\x0b=\xe8\x94\\l\x1et \n\x00\x10\x02\x08\xdf\x84\x03ZX \x86\x1a\x16W\x03\x87+]\xe7[\x06\x00\x96\xe8\xde\x89\xce\xa5\xa8\xe2\x8a\x19N\xf7b\x87\x19\xa5\x17\x1b\x05\xa3P\x10\xa1\x8d#\xe2X\x9b\x8e;\xf2\xd8"n/\xd6\xd5\xdf\x13\xa2x\x80$\x89\x11\x9e\xd8\x81\x16\x146\xb9#\x8b\xd3\xf9\xe6\xc1\x7f\xa2\x0cp\xe5\x99\x12\xa8\x80\xdad\x15zi!\x98\xab\xf9Ff\x99gvG$g\xdf1\xa0\x80\x9bM\xc2\t\x19\x00\x19p\xd9\x9d\x99G6\xd7Hl\xdf\x99\xc2\xc8\x9e|~\t\x88)~Q@c\x99\xa3\x0cZg\x06\x00\xf8\x96\xa8)\x0c,\xc0h\xa3\x05^\x02\xe9(\x93Rji\x84\xcb)\'\x1fn\x9d~\nj)\xa3\x0e\xffZis\x84\x06\xd7\x81\xaak\xae\xc6\x01\x07\xa0\xb5\xfa*\xac~\xc9z\xaa\x04\x03l\x80+b\xb7\x81V@\x01$\xac\xd6\xe9\xab\xb1\xd2:kpj\x0ep\xe7\xb1\xab\x9aRA\x01!\x14\xd7\xc0\x03\x8dF\x1b\xdc\x00\xd3\x8ar-\xb6\xc8\x12\x07Z\t\x15\xf0:\xdd\xb7n\x8ak\xaa(\x1ddz\xac\x14\x86\x80\x92+~\xf8\xc1\xbb\xa3\xbc\xe4\xae\xe1\x01\xbaR\xfcAG\'\\\xa4\xab\x1a\xbf\xef\x82k\xa1\xbc\x03\xa3\xeb\xd7\x1d\xa4T\xcc\x87\xc2\xc5qP\x02\xc3\xab\xf9+\x9e\xb8OH\xec\xd7\x1bYTL\x8a\x1f~\xa1\x91\xecj"\xd8\xc01n\xfe\x8e\xdaA\x06\xe7\xa2;\t)Q\xb0AJ\x15\\\xa8\xbc2h!\x14\xe0\xee\xcb\xa05\x10\xc6\xa8"s&\x07\n\x13L\xb0sA\x0b\x9b\xa2\x81\x08"h\xf02\x0f\x15\xe0\x964g2\xa8\xd1D\xd3\xa4\xe8\x01\xf5t\x1c\x14`\xc6\xcb\xcbN\x11\xe7\xd6\x87]@\xca\xd7\x8f\x90\xf2\x01\x08#\x10t\x80$\xc5\x99\xc1-\xc7?\x14\xff@\xc6\xdal\x8f\xe2\x04)b0\xb1\t)}\x84\x12J&\x04\x05\x02\xc5\x18\xb8\xd9P\xc0\x0f\x1c\x93`5h\x81_\xb0H(j\x98\xacD( \xc0`P\xc5\x8f\x83\xa6\xc1\xb6;l1\x9d\x06\x1bk\x9d4\x18:(\x1e\n\x15&sR\xb7A9\xc0Q\xf1 \x18X\x00Z\xdf<\x84\xa0:h$H^\x1cgC\\\xa0\xdc\x10\x9a\xc8\xae8\x11gdQ\x07\x01\x07!\x10\n\x11W| {\xef\xa6\x90\xb0m\x01"T B\x01<\xa8\xed\xba_X|pE\x1e\xa7\xc9\xe0D\x19\xce\xcb\xbe\x04\xf5\x08\x11\x80@\x02\xf1+\xce}\t!\xecP\xc1\x0ed\xb8\xdc\xf9\x86\xa0\x88\x8aQA\x06\x90\xc1\x02\xfc\xf2G\x83\x1c4\xc4~\xf8\xcb\x1f\xf7^v\x98D\x98\x0c\x07\xca\x1b\xc5\x05\xba\x90\xbfP`Bt\x14\x81`\x07\'\xc8/\xbf\xc8@\toC\x01)\x9c\x00\xbb\x0e\xd2\xcd$"\x94\xa0\xef\xf0\xe3\x978\xe0l\x02^ \x05\x07\xf3\x97\x00\x04\xd0\xaf%1t\xde\x0b|X\xb0\x820\x8db\x0f\xa4`\xc2\x04\x16@\x8a\x0e\xce\x8f(\x02\t\xa2\xec\x86X\xc4\xb5\x15"\x898\xc4A\xfc\x1a\x08\xc5\x82HQqT\xc4\xdc("A\n<\x08\x02\x05\x94\x90\x1d\r@\xd8E\x83|1\x14T\xbc\x80\x0e>@\n\x14\x88An\xa0\xbb]\x1b\x13\xf2F\xd9Y\xc2dg\xe8\xe1\x1e\x1d\xd2\xc7P\xa0\x10\x07\x84\xf8\xe1 \x1fx\xbf\xfc\x11\xa1\x12\x90XdG\x82\xb8FI\x02q\t/\xb4\xa4&[\x12\x10\x00;',
+ "png",
+)
+ARRAY_TO_BASE64_IMAGE = (
+ "data:image/png;base64,"
+ "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"
+)
+BASE64_MODEL3D = {
+ "path": "Box.gltf",
+ "data": "data:;base64,ewogICAgImFzc2V0IjogewogICAgICAgICJnZW5lcmF0b3IiOiAiQ09MTEFEQTJHTFRGIiwKICAgICAgICAidmVyc2lvbiI6ICIyLjAiCiAgICB9LAogICAgInNjZW5lIjogMCwKICAgICJzY2VuZXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAibm9kZXMiOiBbCiAgICAgICAgICAgICAgICAwCiAgICAgICAgICAgIF0KICAgICAgICB9CiAgICBdLAogICAgIm5vZGVzIjogWwogICAgICAgIHsKICAgICAgICAgICAgImNoaWxkcmVuIjogWwogICAgICAgICAgICAgICAgMQogICAgICAgICAgICBdLAogICAgICAgICAgICAibWF0cml4IjogWwogICAgICAgICAgICAgICAgMS4wLAogICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgLTEuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDEuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgICAgIDEuMAogICAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJtZXNoIjogMAogICAgICAgIH0KICAgIF0sCiAgICAibWVzaGVzIjogWwogICAgICAgIHsKICAgICAgICAgICAgInByaW1pdGl2ZXMiOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgImF0dHJpYnV0ZXMiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJOT1JNQUwiOiAxLAogICAgICAgICAgICAgICAgICAgICAgICAiUE9TSVRJT04iOiAyCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAiaW5kaWNlcyI6IDAsCiAgICAgICAgICAgICAgICAgICAgIm1vZGUiOiA0LAogICAgICAgICAgICAgICAgICAgICJtYXRlcmlhbCI6IDAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgXSwKICAgICAgICAgICAgIm5hbWUiOiAiTWVzaCIKICAgICAgICB9CiAgICBdLAogICAgImFjY2Vzc29ycyI6IFsKICAgICAgICB7CiAgICAgICAgICAgICJidWZmZXJWaWV3IjogMCwKICAgICAgICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAgICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjMsCiAgICAgICAgICAgICJjb3VudCI6IDM2LAogICAgICAgICAgICAibWF4IjogWwogICAgICAgICAgICAgICAgMjMKICAgICAgICAgICAgXSwKICAgICAgICAgICAgIm1pbiI6IFsKICAgICAgICAgICAgICAgIDAKICAgICAgICAgICAgXSwKICAgICAgICAgICAgInR5cGUiOiAiU0NBTEFSIgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgICAiYnVmZmVyVmlldyI6IDEsCiAgICAgICAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAgICAgICAiY291bnQiOiAyNCwKICAgICAgICAgICAgIm1heCI6IFsKICAgICAgICAgICAgICAgIDEuMCwKICAgICAgICAgICAgICAgIDEuMCwKICAgICAgICAgICAgICAgIDEuMAogICAgICAgICAgICBdLAogICAgICAgICAgICAibWluIjogWwogICAgICAgICAgICAgICAgLTEuMCwKICAgICAgICAgICAgICAgIC0xLjAsCiAgICAgICAgICAgICAgICAtMS4wCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJ0eXBlIjogIlZFQzMiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJidWZmZXJWaWV3IjogMSwKICAgICAgICAgICAgImJ5dGVPZmZzZXQiOiAyODgsCiAgICAgICAgICAgICJjb21wb25lbnRUeXBlIjogNTEyNiwKICAgICAgICAgICAgImNvdW50IjogMjQsCiAgICAgICAgICAgICJtYXgiOiBbCiAgICAgICAgICAgICAgICAwLjUsCiAgICAgICAgICAgICAgICAwLjUsCiAgICAgICAgICAgICAgICAwLjUKICAgICAgICAgICAgXSwKICAgICAgICAgICAgIm1pbiI6IFsKICAgICAgICAgICAgICAgIC0wLjUsCiAgICAgICAgICAgICAgICAtMC41LAogICAgICAgICAgICAgICAgLTAuNQogICAgICAgICAgICBdLAogICAgICAgICAgICAidHlwZSI6ICJWRUMzIgogICAgICAgIH0KICAgIF0sCiAgICAibWF0ZXJpYWxzIjogWwogICAgICAgIHsKICAgICAgICAgICAgInBick1ldGFsbGljUm91Z2huZXNzIjogewogICAgICAgICAgICAgICAgImJhc2VDb2xvckZhY3RvciI6IFsKICAgICAgICAgICAgICAgICAgICAwLjgwMDAwMDAxMTkyMDkyOSwKICAgICAgICAgICAgICAgICAgICAwLjAsCiAgICAgICAgICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAgICAgICAgIDEuMAogICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICJtZXRhbGxpY0ZhY3RvciI6IDAuMAogICAgICAgICAgICB9LAogICAgICAgICAgICAibmFtZSI6ICJSZWQiCiAgICAgICAgfQogICAgXSwKICAgICJidWZmZXJWaWV3cyI6IFsKICAgICAgICB7CiAgICAgICAgICAgICJidWZmZXIiOiAwLAogICAgICAgICAgICAiYnl0ZU9mZnNldCI6IDU3NiwKICAgICAgICAgICAgImJ5dGVMZW5ndGgiOiA3MiwKICAgICAgICAgICAgInRhcmdldCI6IDM0OTYzCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJidWZmZXIiOiAwLAogICAgICAgICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICAgICAgICJieXRlTGVuZ3RoIjogNTc2LAogICAgICAgICAgICAiYnl0ZVN0cmlkZSI6IDEyLAogICAgICAgICAgICAidGFyZ2V0IjogMzQ5NjIKICAgICAgICB9CiAgICBdLAogICAgImJ1ZmZlcnMiOiBbCiAgICAgICAgewogICAgICAgICAgICAiYnl0ZUxlbmd0aCI6IDY0OCwKICAgICAgICAgICAgInVyaSI6ICJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQXZ3QUFBTDhBQUFBL0FBQUFQd0FBQUw4QUFBQS9BQUFBdndBQUFEOEFBQUEvQUFBQVB3QUFBRDhBQUFBL0FBQUFQd0FBQUw4QUFBQS9BQUFBdndBQUFMOEFBQUEvQUFBQVB3QUFBTDhBQUFDL0FBQUF2d0FBQUw4QUFBQy9BQUFBUHdBQUFEOEFBQUEvQUFBQVB3QUFBTDhBQUFBL0FBQUFQd0FBQUQ4QUFBQy9BQUFBUHdBQUFMOEFBQUMvQUFBQXZ3QUFBRDhBQUFBL0FBQUFQd0FBQUQ4QUFBQS9BQUFBdndBQUFEOEFBQUMvQUFBQVB3QUFBRDhBQUFDL0FBQUF2d0FBQUw4QUFBQS9BQUFBdndBQUFEOEFBQUEvQUFBQXZ3QUFBTDhBQUFDL0FBQUF2d0FBQUQ4QUFBQy9BQUFBdndBQUFMOEFBQUMvQUFBQXZ3QUFBRDhBQUFDL0FBQUFQd0FBQUw4QUFBQy9BQUFBUHdBQUFEOEFBQUMvQUFBQkFBSUFBd0FDQUFFQUJBQUZBQVlBQndBR0FBVUFDQUFKQUFvQUN3QUtBQWtBREFBTkFBNEFEd0FPQUEwQUVBQVJBQklBRXdBU0FCRUFGQUFWQUJZQUZ3QVdBQlVBIgogICAgICAgIH0KICAgIF0KfQo=",
+}
+SUM_PIXELS_INTERPRETATION = {
+ "scores": [
+ [
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.9217332561281606,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.8478093032233159,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ 0.7775525960239336,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.28228141285466124,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.7110596409959468,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.5717043041883806,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.17004439297432927,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.6232387569967188,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.349160393746381,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ 0.37415556842308434,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ [
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.4147847905809689,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.21617448369040726,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.4393939393939394,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ 0.8667245705462266,
+ ],
+ ]
+ ],
+ "alternative_outputs": [
+ [
+ [1793106],
+ [1795539],
+ [1797837],
+ [1800021],
+ [1815417],
+ [1802088],
+ [1806420],
+ [1824192],
+ [1818906],
+ [1804818],
+ [1813338],
+ [1812561],
+ [1811298],
+ [1817472],
+ [1810533],
+ [1797249],
+ ]
+ ],
+}
+SUM_PIXELS_SHAP_INTERPRETATION = {
+ "scores": [
+ [
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.36599426908032084,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.9044030984144017,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.5780729041010304,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.03706410007949775,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.4724172299368354,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ 0.5148839775509372,
+ ],
+ ]
+ ],
+ "alternative_outputs": [[]],
+}
+
+FILE_TEMPLATE_CONTEXT = {
+ "file_count": "single",
+ "value": {
+ "path": "sample_file.pdf",
+ "size": 10558,
+ "data": "data:application/pdf;base64,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",
+ },
+ "path": "file",
+ "label": None,
+ "show_label": True,
+ "style": {},
+ "elem_id": None,
+ "interactive": None,
+ "visible": True,
+}
+BASE64_MICROPHONE = {
+ "path": "/var/folders/t1/j7cmtcgd0mx43jh9nj_r9mmw0000gn/T/audiovb4gqjpc.wav",
+ "data": "data:audio/wav;base64,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",
+}
diff --git a/client/python/gradio_client/package.json b/client/python/gradio_client/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c66da2e450e6b9130af6c4e008529ad0183d62ea
--- /dev/null
+++ b/client/python/gradio_client/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gradio_client",
+ "version": "0.8.1",
+ "description": "",
+ "python": "true",
+ "main_changeset": true
+}
diff --git a/client/python/gradio_client/serializing.py b/client/python/gradio_client/serializing.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c96e719ce52993f54d20f6368da294a5b1e746f
--- /dev/null
+++ b/client/python/gradio_client/serializing.py
@@ -0,0 +1,598 @@
+"""Included for backwards compatibility with 3.x spaces/apps."""
+from __future__ import annotations
+
+import json
+import os
+import secrets
+import tempfile
+import uuid
+from pathlib import Path
+from typing import Any
+
+from gradio_client import media_data, utils
+from gradio_client.data_classes import FileData
+
+with open(Path(__file__).parent / "types.json") as f:
+ serializer_types = json.load(f)
+
+
+class Serializable:
+ def serialized_info(self):
+ """
+ The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description].
+ Keys of the dictionary are: raw_input, raw_output, serialized_input, serialized_output
+ """
+ return self.api_info()
+
+ def api_info(self) -> dict[str, list[str]]:
+ """
+ The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description].
+ Keys of the dictionary are: raw_input, raw_output, serialized_input, serialized_output
+ """
+ raise NotImplementedError()
+
+ def example_inputs(self) -> dict[str, Any]:
+ """
+ The example inputs for this component as a dictionary whose values are example inputs compatible with this component.
+ Keys of the dictionary are: raw, serialized
+ """
+ raise NotImplementedError()
+
+ # For backwards compatibility
+ def input_api_info(self) -> tuple[str, str]:
+ api_info = self.api_info()
+ types = api_info.get("serialized_input", [api_info["info"]["type"]] * 2) # type: ignore
+ return (types[0], types[1])
+
+ # For backwards compatibility
+ def output_api_info(self) -> tuple[str, str]:
+ api_info = self.api_info()
+ types = api_info.get("serialized_output", [api_info["info"]["type"]] * 2) # type: ignore
+ return (types[0], types[1])
+
+ def serialize(self, x: Any, load_dir: str | Path = "", allow_links: bool = False):
+ """
+ Convert data from human-readable format to serialized format for a browser.
+ """
+ return x
+
+ def deserialize(
+ self,
+ x: Any,
+ save_dir: str | Path | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ):
+ """
+ Convert data from serialized format for a browser to human-readable format.
+ """
+ return x
+
+
+class SimpleSerializable(Serializable):
+ """General class that does not perform any serialization or deserialization."""
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {
+ "info": serializer_types["SimpleSerializable"],
+ "serialized_info": False,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": None,
+ "serialized": None,
+ }
+
+
+class StringSerializable(Serializable):
+ """Expects a string as input/output but performs no serialization."""
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {
+ "info": serializer_types["StringSerializable"],
+ "serialized_info": False,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": "Howdy!",
+ "serialized": "Howdy!",
+ }
+
+
+class ListStringSerializable(Serializable):
+ """Expects a list of strings as input/output but performs no serialization."""
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {
+ "info": serializer_types["ListStringSerializable"],
+ "serialized_info": False,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": ["Howdy!", "Merhaba"],
+ "serialized": ["Howdy!", "Merhaba"],
+ }
+
+
+class BooleanSerializable(Serializable):
+ """Expects a boolean as input/output but performs no serialization."""
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {
+ "info": serializer_types["BooleanSerializable"],
+ "serialized_info": False,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": True,
+ "serialized": True,
+ }
+
+
+class NumberSerializable(Serializable):
+ """Expects a number (int/float) as input/output but performs no serialization."""
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {
+ "info": serializer_types["NumberSerializable"],
+ "serialized_info": False,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": 5,
+ "serialized": 5,
+ }
+
+
+class ImgSerializable(Serializable):
+ """Expects a base64 string as input/output which is serialized to a filepath."""
+
+ def serialized_info(self):
+ return {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of image",
+ }
+
+ def api_info(self) -> dict[str, bool | dict]:
+ return {"info": serializer_types["ImgSerializable"], "serialized_info": True}
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": media_data.BASE64_IMAGE,
+ "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ }
+
+ def serialize(
+ self,
+ x: str | None,
+ load_dir: str | Path = "",
+ allow_links: bool = False,
+ ) -> str | None:
+ """
+ Convert from human-friendly version of a file (string filepath) to a serialized
+ representation (base64).
+ Parameters:
+ x: String path to file to serialize
+ load_dir: Path to directory containing x
+ """
+ if not x:
+ return None
+ if utils.is_http_url_like(x):
+ return utils.encode_url_to_base64(x)
+ return utils.encode_file_to_base64(Path(load_dir) / x)
+
+ def deserialize(
+ self,
+ x: str | None,
+ save_dir: str | Path | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> str | None:
+ """
+ Convert from serialized representation of a file (base64) to a human-friendly
+ version (string filepath). Optionally, save the file to the directory specified by save_dir
+ Parameters:
+ x: Base64 representation of image to deserialize into a string filepath
+ save_dir: Path to directory to save the deserialized image to
+ root_url: Ignored
+ hf_token: Ignored
+ """
+ if x is None or x == "":
+ return None
+ file = utils.decode_base64_to_file(x, dir=save_dir)
+ return file.name
+
+
+class FileSerializable(Serializable):
+ """Expects a dict with base64 representation of object as input/output which is serialized to a filepath."""
+
+ def __init__(self) -> None:
+ self.stream = None
+ self.stream_name = None
+ super().__init__()
+
+ def serialized_info(self):
+ return self._single_file_serialized_info()
+
+ def _single_file_api_info(self):
+ return {
+ "info": serializer_types["SingleFileSerializable"],
+ "serialized_info": True,
+ }
+
+ def _single_file_serialized_info(self):
+ return {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file",
+ }
+
+ def _multiple_file_serialized_info(self):
+ return {
+ "type": "array",
+ "description": "List of filepath(s) or URL(s) to files",
+ "items": {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file",
+ },
+ }
+
+ def _multiple_file_api_info(self):
+ return {
+ "info": serializer_types["MultipleFileSerializable"],
+ "serialized_info": True,
+ }
+
+ def api_info(self) -> dict[str, dict | bool]:
+ return self._single_file_api_info()
+
+ def example_inputs(self) -> dict[str, Any]:
+ return self._single_file_example_inputs()
+
+ def _single_file_example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": {"is_file": False, "data": media_data.BASE64_FILE},
+ "serialized": "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf",
+ }
+
+ def _multiple_file_example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": [{"is_file": False, "data": media_data.BASE64_FILE}],
+ "serialized": [
+ "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
+ ],
+ }
+
+ def _serialize_single(
+ self,
+ x: str | FileData | None,
+ load_dir: str | Path = "",
+ allow_links: bool = False,
+ ) -> FileData | None:
+ if x is None or isinstance(x, dict):
+ return x
+ if utils.is_http_url_like(x):
+ filename = x
+ size = None
+ else:
+ filename = str(Path(load_dir) / x)
+ size = Path(filename).stat().st_size
+ return {
+ "name": filename or None,
+ "data": None
+ if allow_links
+ else utils.encode_url_or_file_to_base64(filename),
+ "orig_name": Path(filename).name,
+ "size": size,
+ }
+
+ def _setup_stream(self, url, hf_token):
+ return utils.download_byte_stream(url, hf_token)
+
+ def _deserialize_single(
+ self,
+ x: str | FileData | None,
+ save_dir: str | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> str | None:
+ if x is None:
+ return None
+ if isinstance(x, str):
+ file_name = utils.decode_base64_to_file(x, dir=save_dir).name
+ elif isinstance(x, dict):
+ if x.get("is_file"):
+ filepath = x.get("name")
+ if filepath is None:
+ raise ValueError(f"The 'name' field is missing in {x}")
+ if root_url is not None:
+ file_name = utils.download_tmp_copy_of_file(
+ root_url + "file=" + filepath,
+ hf_token=hf_token,
+ dir=save_dir,
+ )
+ else:
+ file_name = utils.create_tmp_copy_of_file(filepath, dir=save_dir)
+ elif x.get("is_stream"):
+ assert x["name"] and root_url and save_dir
+ if not self.stream or self.stream_name != x["name"]:
+ self.stream = self._setup_stream(
+ root_url + "stream/" + x["name"], hf_token=hf_token
+ )
+ self.stream_name = x["name"]
+ chunk = next(self.stream)
+ path = Path(save_dir or tempfile.gettempdir()) / secrets.token_hex(20)
+ path.mkdir(parents=True, exist_ok=True)
+ path = path / x.get("orig_name", "output")
+ path.write_bytes(chunk)
+ file_name = str(path)
+ else:
+ data = x.get("data")
+ if data is None:
+ raise ValueError(f"The 'data' field is missing in {x}")
+ file_name = utils.decode_base64_to_file(data, dir=save_dir).name
+ else:
+ raise ValueError(
+ f"A FileSerializable component can only deserialize a string or a dict, not a {type(x)}: {x}"
+ )
+ return file_name
+
+ def serialize(
+ self,
+ x: str | FileData | None | list[str | FileData | None],
+ load_dir: str | Path = "",
+ allow_links: bool = False,
+ ) -> FileData | None | list[FileData | None]:
+ """
+ Convert from human-friendly version of a file (string filepath) to a
+ serialized representation (base64)
+ Parameters:
+ x: String path to file to serialize
+ load_dir: Path to directory containing x
+ allow_links: Will allow path returns instead of raw file content
+ """
+ if x is None or x == "":
+ return None
+ if isinstance(x, list):
+ return [self._serialize_single(f, load_dir, allow_links) for f in x]
+ else:
+ return self._serialize_single(x, load_dir, allow_links)
+
+ def deserialize(
+ self,
+ x: str | FileData | None | list[str | FileData | None],
+ save_dir: Path | str | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> str | None | list[str | None]:
+ """
+ Convert from serialized representation of a file (base64) to a human-friendly
+ version (string filepath). Optionally, save the file to the directory specified by `save_dir`
+ Parameters:
+ x: Base64 representation of file to deserialize into a string filepath
+ save_dir: Path to directory to save the deserialized file to
+ root_url: If this component is loaded from an external Space, this is the URL of the Space.
+ hf_token: If this component is loaded from an external private Space, this is the access token for the Space
+ """
+ if x is None:
+ return None
+ if isinstance(save_dir, Path):
+ save_dir = str(save_dir)
+ if isinstance(x, list):
+ return [
+ self._deserialize_single(
+ f, save_dir=save_dir, root_url=root_url, hf_token=hf_token
+ )
+ for f in x
+ ]
+ else:
+ return self._deserialize_single(
+ x, save_dir=save_dir, root_url=root_url, hf_token=hf_token
+ )
+
+
+class VideoSerializable(FileSerializable):
+ def serialized_info(self):
+ return {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of video file",
+ }
+
+ def api_info(self) -> dict[str, dict | bool]:
+ return {"info": serializer_types["FileSerializable"], "serialized_info": True}
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": {"is_file": False, "data": media_data.BASE64_VIDEO},
+ "serialized": "https://github.com/gradio-app/gradio/raw/main/test/test_files/video_sample.mp4",
+ }
+
+ def serialize(
+ self, x: str | None, load_dir: str | Path = "", allow_links: bool = False
+ ) -> tuple[FileData | None, None]:
+ return (super().serialize(x, load_dir, allow_links), None) # type: ignore
+
+ def deserialize(
+ self,
+ x: tuple[FileData | None, FileData | None] | None,
+ save_dir: Path | str | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> str | tuple[str | None, str | None] | None:
+ """
+ Convert from serialized representation of a file (base64) to a human-friendly
+ version (string filepath). Optionally, save the file to the directory specified by `save_dir`
+ """
+ if isinstance(x, (tuple, list)):
+ if len(x) != 2:
+ raise ValueError(f"Expected tuple of length 2. Received: {x}")
+ x_as_list = [x[0], x[1]]
+ else:
+ raise ValueError(f"Expected tuple of length 2. Received: {x}")
+ deserialized_file = super().deserialize(x_as_list, save_dir, root_url, hf_token) # type: ignore
+ if isinstance(deserialized_file, list):
+ return deserialized_file[0] # ignore subtitles
+
+
+class JSONSerializable(Serializable):
+ def serialized_info(self):
+ return {"type": "string", "description": "filepath to JSON file"}
+
+ def api_info(self) -> dict[str, dict | bool]:
+ return {"info": serializer_types["JSONSerializable"], "serialized_info": True}
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": {"a": 1, "b": 2},
+ "serialized": None,
+ }
+
+ def serialize(
+ self,
+ x: str | None,
+ load_dir: str | Path = "",
+ allow_links: bool = False,
+ ) -> dict | list | None:
+ """
+ Convert from a a human-friendly version (string path to json file) to a
+ serialized representation (json string)
+ Parameters:
+ x: String path to json file to read to get json string
+ load_dir: Path to directory containing x
+ """
+ if x is None or x == "":
+ return None
+ return utils.file_to_json(Path(load_dir) / x)
+
+ def deserialize(
+ self,
+ x: str | dict | list,
+ save_dir: str | Path | None = None,
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> str | None:
+ """
+ Convert from serialized representation (json string) to a human-friendly
+ version (string path to json file). Optionally, save the file to the directory specified by `save_dir`
+ Parameters:
+ x: Json string
+ save_dir: Path to save the deserialized json file to
+ root_url: Ignored
+ hf_token: Ignored
+ """
+ if x is None:
+ return None
+ return utils.dict_or_str_to_json_file(x, dir=save_dir).name
+
+
+class GallerySerializable(Serializable):
+ def serialized_info(self):
+ return {
+ "type": "string",
+ "description": "path to directory with images and a file associating images with captions called captions.json",
+ }
+
+ def api_info(self) -> dict[str, dict | bool]:
+ return {
+ "info": serializer_types["GallerySerializable"],
+ "serialized_info": True,
+ }
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {
+ "raw": [media_data.BASE64_IMAGE] * 2,
+ "serialized": [
+ "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ ]
+ * 2,
+ }
+
+ def serialize(
+ self, x: str | None, load_dir: str | Path = "", allow_links: bool = False
+ ) -> list[list[str | None]] | None:
+ if x is None or x == "":
+ return None
+ files = []
+ captions_file = Path(x) / "captions.json"
+ with captions_file.open("r") as captions_json:
+ captions = json.load(captions_json)
+ for file_name, caption in captions.items():
+ img = FileSerializable().serialize(file_name, allow_links=allow_links)
+ files.append([img, caption])
+ return files
+
+ def deserialize(
+ self,
+ x: list[list[str | None]] | None,
+ save_dir: str = "",
+ root_url: str | None = None,
+ hf_token: str | None = None,
+ ) -> None | str:
+ if x is None:
+ return None
+ gallery_path = Path(save_dir) / str(uuid.uuid4())
+ gallery_path.mkdir(exist_ok=True, parents=True)
+ captions = {}
+ for img_data in x:
+ if isinstance(img_data, (list, tuple)):
+ img_data, caption = img_data
+ else:
+ caption = None
+ name = FileSerializable().deserialize(
+ img_data, gallery_path, root_url=root_url, hf_token=hf_token
+ )
+ captions[name] = caption
+ captions_file = gallery_path / "captions.json"
+ with captions_file.open("w") as captions_json:
+ json.dump(captions, captions_json)
+ return os.path.abspath(gallery_path)
+
+
+SERIALIZER_MAPPING = {}
+for cls in Serializable.__subclasses__():
+ SERIALIZER_MAPPING[cls.__name__] = cls
+ for subcls in cls.__subclasses__():
+ SERIALIZER_MAPPING[subcls.__name__] = subcls
+
+SERIALIZER_MAPPING["Serializable"] = SimpleSerializable
+SERIALIZER_MAPPING["File"] = FileSerializable
+SERIALIZER_MAPPING["UploadButton"] = FileSerializable
+
+COMPONENT_MAPPING: dict[str, type] = {
+ "textbox": StringSerializable,
+ "number": NumberSerializable,
+ "slider": NumberSerializable,
+ "checkbox": BooleanSerializable,
+ "checkboxgroup": ListStringSerializable,
+ "radio": StringSerializable,
+ "dropdown": SimpleSerializable,
+ "image": ImgSerializable,
+ "video": FileSerializable,
+ "audio": FileSerializable,
+ "file": FileSerializable,
+ "dataframe": JSONSerializable,
+ "timeseries": JSONSerializable,
+ "fileexplorer": JSONSerializable,
+ "state": SimpleSerializable,
+ "button": StringSerializable,
+ "uploadbutton": FileSerializable,
+ "colorpicker": StringSerializable,
+ "label": JSONSerializable,
+ "highlightedtext": JSONSerializable,
+ "json": JSONSerializable,
+ "html": StringSerializable,
+ "gallery": GallerySerializable,
+ "chatbot": JSONSerializable,
+ "model3d": FileSerializable,
+ "plot": JSONSerializable,
+ "barplot": JSONSerializable,
+ "lineplot": JSONSerializable,
+ "scatterplot": JSONSerializable,
+ "markdown": StringSerializable,
+ "code": StringSerializable,
+ "annotatedimage": JSONSerializable,
+}
diff --git a/client/python/gradio_client/templates/discord_chat.py b/client/python/gradio_client/templates/discord_chat.py
new file mode 100644
index 0000000000000000000000000000000000000000..881ff65fb5e5b4599cb213c6cfa8fa236b09b509
--- /dev/null
+++ b/client/python/gradio_client/templates/discord_chat.py
@@ -0,0 +1,193 @@
+import asyncio
+import os
+import threading
+from threading import Event
+from typing import Optional
+
+import discord
+import gradio as gr
+from discord import Permissions
+from discord.ext import commands
+from discord.utils import oauth_url
+
+import gradio_client as grc
+from gradio_client.utils import QueueError
+
+event = Event()
+
+DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
+
+
+async def wait(job):
+ while not job.done():
+ await asyncio.sleep(0.2)
+
+
+def get_client(session: Optional[str] = None) -> grc.Client:
+ client = grc.Client("<>", hf_token=os.getenv("HF_TOKEN"))
+ if session:
+ client.session_hash = session
+ return client
+
+
+def truncate_response(response: str) -> str:
+ ending = "...\nTruncating response to 2000 characters due to discord api limits."
+ if len(response) > 2000:
+ return response[: 2000 - len(ending)] + ending
+ else:
+ return response
+
+
+intents = discord.Intents.default()
+intents.message_content = True
+bot = commands.Bot(command_prefix="/", intents=intents)
+
+
+@bot.event
+async def on_ready():
+ print(f"Logged in as {bot.user} (ID: {bot.user.id})")
+ synced = await bot.tree.sync()
+ print(f"Synced commands: {', '.join([s.name for s in synced])}.")
+ event.set()
+ print("------")
+
+
+thread_to_client = {}
+thread_to_user = {}
+
+
+@bot.hybrid_command(
+ name="<>",
+ description="Enter some text to chat with the bot! Like this: /<> Hello, how are you?",
+)
+async def chat(ctx, prompt: str):
+ if ctx.author.id == bot.user.id:
+ return
+ try:
+ message = await ctx.send("Creating thread...")
+
+ thread = await message.create_thread(name=prompt)
+ loop = asyncio.get_running_loop()
+ client = await loop.run_in_executor(None, get_client, None)
+ job = client.submit(prompt, api_name="/<>")
+ await wait(job)
+
+ try:
+ job.result()
+ response = job.outputs()[-1]
+ await thread.send(truncate_response(response))
+ thread_to_client[thread.id] = client
+ thread_to_user[thread.id] = ctx.author.id
+ except QueueError:
+ await thread.send(
+ "The gradio space powering this bot is really busy! Please try again later!"
+ )
+
+ except Exception as e:
+ print(f"{e}")
+
+
+async def continue_chat(message):
+ """Continues a given conversation based on chathistory"""
+ try:
+ client = thread_to_client[message.channel.id]
+ prompt = message.content
+ job = client.submit(prompt, api_name="/<>")
+ await wait(job)
+ try:
+ job.result()
+ response = job.outputs()[-1]
+ await message.reply(truncate_response(response))
+ except QueueError:
+ await message.reply(
+ "The gradio space powering this bot is really busy! Please try again later!"
+ )
+
+ except Exception as e:
+ print(f"Error: {e}")
+
+
+@bot.event
+async def on_message(message):
+ """Continue the chat"""
+ try:
+ if not message.author.bot:
+ if message.channel.id in thread_to_user:
+ if thread_to_user[message.channel.id] == message.author.id:
+ await continue_chat(message)
+ else:
+ await bot.process_commands(message)
+
+ except Exception as e:
+ print(f"Error: {e}")
+
+
+# running in thread
+def run_bot():
+ if not DISCORD_TOKEN:
+ print("DISCORD_TOKEN NOT SET")
+ event.set()
+ else:
+ bot.run(DISCORD_TOKEN)
+
+
+threading.Thread(target=run_bot).start()
+
+event.wait()
+
+if not DISCORD_TOKEN:
+ welcome_message = """
+
+ ## You have not specified a DISCORD_TOKEN, which means you have not created a bot account. Please follow these steps:
+
+ ### 1. Go to https://discord.com/developers/applications and click 'New Application'
+
+ ### 2. Give your bot a name 🤖
+
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/BotName.png)
+
+ ## 3. In Settings > Bot, click the 'Reset Token' button to get a new token. Write it down and keep it safe 🔐
+
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/ResetToken.png)
+
+ ## 4. Optionally make the bot public if you want anyone to be able to add it to their servers
+
+ ## 5. Scroll down and enable 'Message Content Intent' under 'Priviledged Gateway Intents'
+
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/MessageContentIntent.png)
+
+ ## 6. Save your changes!
+
+ ## 7. The token from step 3 is the DISCORD_TOKEN. Rerun the deploy_discord command, e.g client.deploy_discord(discord_bot_token=DISCORD_TOKEN, ...), or add the token as a space secret manually.
+"""
+else:
+ permissions = Permissions(326417525824)
+ url = oauth_url(bot.user.id, permissions=permissions)
+ welcome_message = f"""
+ ## Add this bot to your server by clicking this link:
+
+ {url}
+
+ ## How to use it?
+
+ The bot can be triggered via `/<>` followed by your text prompt.
+
+ This will create a thread with the bot's response to your text prompt.
+ You can reply in the thread (without `/<>`) to continue the conversation.
+ In the thread, the bot will only reply to the original author of the command.
+
+ ⚠️ Note ⚠️: Please make sure this bot's command does have the same name as another command in your server.
+
+ ⚠️ Note ⚠️: Bot commands do not work in DMs with the bot as of now.
+ """
+
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ f"""
+ # Discord bot of <>
+ {welcome_message}
+ """
+ )
+
+demo.launch()
diff --git a/client/python/gradio_client/types.json b/client/python/gradio_client/types.json
new file mode 100644
index 0000000000000000000000000000000000000000..2fc1d425b4568bb38def2517449b428858410759
--- /dev/null
+++ b/client/python/gradio_client/types.json
@@ -0,0 +1,199 @@
+{
+ "SimpleSerializable": {
+ "type": {},
+ "description": "any valid value"
+ },
+ "StringSerializable": {
+ "type": "string"
+ },
+ "ListStringSerializable": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "BooleanSerializable": {
+ "type": "boolean"
+ },
+ "NumberSerializable": {
+ "type": "number"
+ },
+ "ImgSerializable": {
+ "type": "string",
+ "description": "base64 representation of an image"
+ },
+ "FileSerializable": {
+ "oneOf": [
+ {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of file" },
+ "data": {
+ "type": "string",
+ "description": "base64 representation of file"
+ },
+ "size": {
+ "type": "integer",
+ "description": "size of image in bytes"
+ },
+ "is_file": {
+ "type": "boolean",
+ "description": "true if the file has been uploaded to the server"
+ },
+ "orig_name": {
+ "type": "string",
+ "description": "original name of the file"
+ }
+ },
+ "required": ["name", "data"]
+ },
+ {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of file" },
+ "data": {
+ "type": "string",
+ "description": "base64 representation of file"
+ },
+ "size": {
+ "type": "integer",
+ "description": "size of image in bytes"
+ },
+ "is_file": {
+ "type": "boolean",
+ "description": "true if the file has been uploaded to the server"
+ },
+ "orig_name": {
+ "type": "string",
+ "description": "original name of the file"
+ }
+ },
+ "required": ["name", "data"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "SingleFileSerializable": {
+ "oneOf": [
+ {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of file" },
+ "data": {
+ "type": "string",
+ "description": "base64 representation of file"
+ },
+ "size": {
+ "type": "integer",
+ "description": "size of image in bytes"
+ },
+ "is_file": {
+ "type": "boolean",
+ "description": "true if the file has been uploaded to the server"
+ },
+ "orig_name": {
+ "type": "string",
+ "description": "original name of the file"
+ }
+ },
+ "required": ["name", "data"]
+ }
+ ]
+ },
+ "MultipleFileSerializable": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "filepath on your computer (or URL) of file"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of file" },
+ "data": {
+ "type": "string",
+ "description": "base64 representation of file"
+ },
+ "size": {
+ "type": "integer",
+ "description": "size of image in bytes"
+ },
+ "is_file": {
+ "type": "boolean",
+ "description": "true if the file has been uploaded to the server"
+ },
+ "orig_name": {
+ "type": "string",
+ "description": "original name of the file"
+ }
+ },
+ "required": ["name", "data"]
+ }
+ ]
+ }
+ },
+ "JSONSerializable": {
+ "type": {},
+ "description": "any valid json"
+ },
+ "GallerySerializable": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": false,
+ "maxSize": 2,
+ "minSize": 2,
+ "prefixItems": [
+ {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of file" },
+ "data": {
+ "type": "string",
+ "description": "base64 representation of file"
+ },
+ "size": {
+ "type": "integer",
+ "description": "size of image in bytes"
+ },
+ "is_file": {
+ "type": "boolean",
+ "description": "true if the file has been uploaded to the server"
+ },
+ "orig_name": {
+ "type": "string",
+ "description": "original name of the file"
+ }
+ },
+ "required": ["name", "data"]
+ },
+ {
+ "oneOf": [
+ { "type": "string", "description": "caption of image" },
+ { "type": "null" }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/client/python/gradio_client/utils.py b/client/python/gradio_client/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..630f16c2aa7364fb44e4225a2f0afe9be4b62e54
--- /dev/null
+++ b/client/python/gradio_client/utils.py
@@ -0,0 +1,964 @@
+from __future__ import annotations
+
+import asyncio
+import base64
+import hashlib
+import json
+import mimetypes
+import os
+import pkgutil
+import secrets
+import shutil
+import tempfile
+import warnings
+from concurrent.futures import CancelledError
+from dataclasses import dataclass, field
+from datetime import datetime
+from enum import Enum
+from pathlib import Path
+from threading import Lock
+from typing import Any, Callable, Optional, TypedDict
+
+import fsspec.asyn
+import httpx
+import huggingface_hub
+from huggingface_hub import SpaceStage
+from websockets.legacy.protocol import WebSocketCommonProtocol
+
+API_URL = "api/predict/"
+SSE_URL_V0 = "queue/join"
+SSE_DATA_URL_V0 = "queue/data"
+SSE_URL = "queue/data"
+SSE_DATA_URL = "queue/join"
+WS_URL = "queue/join"
+UPLOAD_URL = "upload"
+LOGIN_URL = "login"
+CONFIG_URL = "config"
+API_INFO_URL = "info"
+RAW_API_INFO_URL = "info?serialize=False"
+SPACE_FETCHER_URL = "https://gradio-space-api-fetcher-v2.hf.space/api"
+RESET_URL = "reset"
+SPACE_URL = "https://hf.space/{}"
+
+STATE_COMPONENT = "state"
+INVALID_RUNTIME = [
+ SpaceStage.NO_APP_FILE,
+ SpaceStage.CONFIG_ERROR,
+ SpaceStage.BUILD_ERROR,
+ SpaceStage.RUNTIME_ERROR,
+ SpaceStage.PAUSED,
+]
+
+
+class Message(TypedDict, total=False):
+ msg: str
+ output: dict[str, Any]
+ event_id: str
+ rank: int
+ rank_eta: float
+ queue_size: int
+ success: bool
+ progress_data: list[dict]
+ log: str
+ level: str
+
+
+def get_package_version() -> str:
+ try:
+ package_json_data = (
+ pkgutil.get_data(__name__, "package.json").decode("utf-8").strip() # type: ignore
+ )
+ package_data = json.loads(package_json_data)
+ version = package_data.get("version", "")
+ return version
+ except Exception:
+ return ""
+
+
+__version__ = get_package_version()
+
+
+class TooManyRequestsError(Exception):
+ """Raised when the API returns a 429 status code."""
+
+ pass
+
+
+class QueueError(Exception):
+ """Raised when the queue is full or there is an issue adding a job to the queue."""
+
+ pass
+
+
+class InvalidAPIEndpointError(Exception):
+ """Raised when the API endpoint is invalid."""
+
+ pass
+
+
+class SpaceDuplicationError(Exception):
+ """Raised when something goes wrong with a Space Duplication."""
+
+ pass
+
+
+class ServerMessage(str, Enum):
+ send_hash = "send_hash"
+ queue_full = "queue_full"
+ estimation = "estimation"
+ send_data = "send_data"
+ process_starts = "process_starts"
+ process_generating = "process_generating"
+ process_completed = "process_completed"
+ log = "log"
+ progress = "progress"
+ heartbeat = "heartbeat"
+ server_stopped = "server_stopped"
+
+
+class Status(Enum):
+ """Status codes presented to client users."""
+
+ STARTING = "STARTING"
+ JOINING_QUEUE = "JOINING_QUEUE"
+ QUEUE_FULL = "QUEUE_FULL"
+ IN_QUEUE = "IN_QUEUE"
+ SENDING_DATA = "SENDING_DATA"
+ PROCESSING = "PROCESSING"
+ ITERATING = "ITERATING"
+ PROGRESS = "PROGRESS"
+ FINISHED = "FINISHED"
+ CANCELLED = "CANCELLED"
+ LOG = "LOG"
+
+ @staticmethod
+ def ordering(status: Status) -> int:
+ """Order of messages. Helpful for testing."""
+ order = [
+ Status.STARTING,
+ Status.JOINING_QUEUE,
+ Status.QUEUE_FULL,
+ Status.IN_QUEUE,
+ Status.SENDING_DATA,
+ Status.PROCESSING,
+ Status.PROGRESS,
+ Status.ITERATING,
+ Status.FINISHED,
+ Status.CANCELLED,
+ ]
+ return order.index(status)
+
+ def __lt__(self, other: Status):
+ return self.ordering(self) < self.ordering(other)
+
+ @staticmethod
+ def msg_to_status(msg: str) -> Status:
+ """Map the raw message from the backend to the status code presented to users."""
+ return {
+ ServerMessage.send_hash: Status.JOINING_QUEUE,
+ ServerMessage.queue_full: Status.QUEUE_FULL,
+ ServerMessage.estimation: Status.IN_QUEUE,
+ ServerMessage.send_data: Status.SENDING_DATA,
+ ServerMessage.process_starts: Status.PROCESSING,
+ ServerMessage.process_generating: Status.ITERATING,
+ ServerMessage.process_completed: Status.FINISHED,
+ ServerMessage.progress: Status.PROGRESS,
+ ServerMessage.log: Status.LOG,
+ ServerMessage.server_stopped: Status.FINISHED,
+ }[msg] # type: ignore
+
+
+@dataclass
+class ProgressUnit:
+ index: Optional[int]
+ length: Optional[int]
+ unit: Optional[str]
+ progress: Optional[float]
+ desc: Optional[str]
+
+ @classmethod
+ def from_msg(cls, data: list[dict]) -> list[ProgressUnit]:
+ return [
+ cls(
+ index=d.get("index"),
+ length=d.get("length"),
+ unit=d.get("unit"),
+ progress=d.get("progress"),
+ desc=d.get("desc"),
+ )
+ for d in data
+ ]
+
+
+@dataclass
+class StatusUpdate:
+ """Update message sent from the worker thread to the Job on the main thread."""
+
+ code: Status
+ rank: int | None
+ queue_size: int | None
+ eta: float | None
+ success: bool | None
+ time: datetime | None
+ progress_data: list[ProgressUnit] | None
+ log: tuple[str, str] | None = None
+
+
+def create_initial_status_update():
+ return StatusUpdate(
+ code=Status.STARTING,
+ rank=None,
+ queue_size=None,
+ eta=None,
+ success=None,
+ time=datetime.now(),
+ progress_data=None,
+ )
+
+
+@dataclass
+class JobStatus:
+ """The job status.
+
+ Keeps track of the latest status update and intermediate outputs (not yet implements).
+ """
+
+ latest_status: StatusUpdate = field(default_factory=create_initial_status_update)
+ outputs: list[Any] = field(default_factory=list)
+
+
+@dataclass
+class Communicator:
+ """Helper class to help communicate between the worker thread and main thread."""
+
+ lock: Lock
+ job: JobStatus
+ prediction_processor: Callable[..., tuple]
+ reset_url: str
+ should_cancel: bool = False
+ event_id: str | None = None
+
+
+########################
+# Network utils
+########################
+
+
+def is_http_url_like(possible_url: str) -> bool:
+ """
+ Check if the given string looks like an HTTP(S) URL.
+ """
+ return possible_url.startswith(("http://", "https://"))
+
+
+def probe_url(possible_url: str) -> bool:
+ """
+ Probe the given URL to see if it responds with a 200 status code (to HEAD, then to GET).
+ """
+ headers = {"User-Agent": "gradio (https://gradio.app/; gradio-team@huggingface.co)"}
+ try:
+ with httpx.Client() as client:
+ head_request = client.head(possible_url, headers=headers)
+ if head_request.status_code == 405:
+ return client.get(possible_url, headers=headers).is_success
+ return head_request.is_success
+ except Exception:
+ return False
+
+
+def is_valid_url(possible_url: str) -> bool:
+ """
+ Check if the given string is a valid URL.
+ """
+ warnings.warn(
+ "is_valid_url should not be used. "
+ "Use is_http_url_like() and probe_url(), as suitable, instead.",
+ )
+ return is_http_url_like(possible_url) and probe_url(possible_url)
+
+
+async def get_pred_from_ws(
+ websocket: WebSocketCommonProtocol,
+ data: str,
+ hash_data: str,
+ helper: Communicator | None = None,
+) -> dict[str, Any]:
+ completed = False
+ resp = {}
+ while not completed:
+ # Receive message in the background so that we can
+ # cancel even while running a long pred
+ task = asyncio.create_task(websocket.recv())
+ while not task.done():
+ if helper:
+ with helper.lock:
+ if helper.should_cancel:
+ # Need to reset the iterator state since the client
+ # will not reset the session
+ async with httpx.AsyncClient() as http:
+ reset = http.post(
+ helper.reset_url, json=json.loads(hash_data)
+ )
+ # Retrieve cancel exception from task
+ # otherwise will get nasty warning in console
+ task.cancel()
+ await asyncio.gather(task, reset, return_exceptions=True)
+ raise CancelledError()
+ # Need to suspend this coroutine so that task actually runs
+ await asyncio.sleep(0.01)
+ msg = task.result()
+ resp = json.loads(msg)
+ if helper:
+ with helper.lock:
+ has_progress = "progress_data" in resp
+ status_update = StatusUpdate(
+ code=Status.msg_to_status(resp["msg"]),
+ queue_size=resp.get("queue_size"),
+ rank=resp.get("rank", None),
+ success=resp.get("success"),
+ time=datetime.now(),
+ eta=resp.get("rank_eta"),
+ progress_data=ProgressUnit.from_msg(resp["progress_data"])
+ if has_progress
+ else None,
+ )
+ output = resp.get("output", {}).get("data", [])
+ if output and status_update.code != Status.FINISHED:
+ try:
+ result = helper.prediction_processor(*output)
+ except Exception as e:
+ result = [e]
+ helper.job.outputs.append(result)
+ helper.job.latest_status = status_update
+ if resp["msg"] == "queue_full":
+ raise QueueError("Queue is full! Please try again.")
+ if resp["msg"] == "send_hash":
+ await websocket.send(hash_data)
+ elif resp["msg"] == "send_data":
+ await websocket.send(data)
+ completed = resp["msg"] == "process_completed"
+ return resp["output"]
+
+
+async def get_pred_from_sse_v0(
+ client: httpx.AsyncClient,
+ data: dict,
+ hash_data: dict,
+ helper: Communicator,
+ sse_url: str,
+ sse_data_url: str,
+ headers: dict[str, str],
+ cookies: dict[str, str] | None,
+) -> dict[str, Any] | None:
+ done, pending = await asyncio.wait(
+ [
+ asyncio.create_task(check_for_cancel(helper, headers, cookies)),
+ asyncio.create_task(
+ stream_sse_v0(
+ client,
+ data,
+ hash_data,
+ helper,
+ sse_url,
+ sse_data_url,
+ headers,
+ cookies,
+ )
+ ),
+ ],
+ return_when=asyncio.FIRST_COMPLETED,
+ )
+
+ for task in pending:
+ task.cancel()
+ try:
+ await task
+ except asyncio.CancelledError:
+ pass
+
+ assert len(done) == 1
+ for task in done:
+ return task.result()
+
+
+async def get_pred_from_sse_v1(
+ helper: Communicator,
+ headers: dict[str, str],
+ cookies: dict[str, str] | None,
+ pending_messages_per_event: dict[str, list[Message | None]],
+ event_id: str,
+) -> dict[str, Any] | None:
+ done, pending = await asyncio.wait(
+ [
+ asyncio.create_task(check_for_cancel(helper, headers, cookies)),
+ asyncio.create_task(
+ stream_sse_v1(
+ helper,
+ pending_messages_per_event,
+ event_id,
+ )
+ ),
+ ],
+ return_when=asyncio.FIRST_COMPLETED,
+ )
+
+ for task in pending:
+ task.cancel()
+ try:
+ await task
+ except asyncio.CancelledError:
+ pass
+
+ assert len(done) == 1
+ for task in done:
+ return task.result()
+
+
+async def check_for_cancel(
+ helper: Communicator, headers: dict[str, str], cookies: dict[str, str] | None
+):
+ while True:
+ await asyncio.sleep(0.05)
+ with helper.lock:
+ if helper.should_cancel:
+ break
+ if helper.event_id:
+ async with httpx.AsyncClient() as http:
+ await http.post(
+ helper.reset_url,
+ json={"event_id": helper.event_id},
+ headers=headers,
+ cookies=cookies,
+ )
+ raise CancelledError()
+
+
+async def stream_sse_v0(
+ client: httpx.AsyncClient,
+ data: dict,
+ hash_data: dict,
+ helper: Communicator,
+ sse_url: str,
+ sse_data_url: str,
+ headers: dict[str, str],
+ cookies: dict[str, str] | None,
+) -> dict[str, Any]:
+ try:
+ async with client.stream(
+ "GET",
+ sse_url,
+ params=hash_data,
+ headers=headers,
+ cookies=cookies,
+ ) as response:
+ async for line in response.aiter_lines():
+ line = line.rstrip("\n")
+ if len(line) == 0:
+ continue
+ if line.startswith("data:"):
+ resp = json.loads(line[5:])
+ if resp["msg"] in [ServerMessage.log, ServerMessage.heartbeat]:
+ continue
+ with helper.lock:
+ has_progress = "progress_data" in resp
+ status_update = StatusUpdate(
+ code=Status.msg_to_status(resp["msg"]),
+ queue_size=resp.get("queue_size"),
+ rank=resp.get("rank", None),
+ success=resp.get("success"),
+ time=datetime.now(),
+ eta=resp.get("rank_eta"),
+ progress_data=ProgressUnit.from_msg(resp["progress_data"])
+ if has_progress
+ else None,
+ )
+ output = resp.get("output", {}).get("data", [])
+ if output and status_update.code != Status.FINISHED:
+ try:
+ result = helper.prediction_processor(*output)
+ except Exception as e:
+ result = [e]
+ helper.job.outputs.append(result)
+ helper.job.latest_status = status_update
+
+ if resp["msg"] == "queue_full":
+ raise QueueError("Queue is full! Please try again.")
+ elif resp["msg"] == "send_data":
+ event_id = resp["event_id"]
+ helper.event_id = event_id
+ req = await client.post(
+ sse_data_url,
+ json={"event_id": event_id, **data, **hash_data},
+ headers=headers,
+ cookies=cookies,
+ )
+ req.raise_for_status()
+ elif resp["msg"] == "process_completed":
+ return resp["output"]
+ else:
+ raise ValueError(f"Unexpected message: {line}")
+ raise ValueError("Did not receive process_completed message.")
+ except asyncio.CancelledError:
+ raise
+
+
+async def stream_sse_v1(
+ helper: Communicator,
+ pending_messages_per_event: dict[str, list[Message | None]],
+ event_id: str,
+) -> dict[str, Any]:
+ try:
+ pending_messages = pending_messages_per_event[event_id]
+
+ while True:
+ if len(pending_messages) > 0:
+ msg = pending_messages.pop(0)
+ else:
+ await asyncio.sleep(0.05)
+ continue
+
+ if msg is None:
+ raise CancelledError()
+
+ with helper.lock:
+ log_message = None
+ if msg["msg"] == ServerMessage.log:
+ log = msg.get("log")
+ level = msg.get("level")
+ if log and level:
+ log_message = (log, level)
+ status_update = StatusUpdate(
+ code=Status.msg_to_status(msg["msg"]),
+ queue_size=msg.get("queue_size"),
+ rank=msg.get("rank", None),
+ success=msg.get("success"),
+ time=datetime.now(),
+ eta=msg.get("rank_eta"),
+ progress_data=ProgressUnit.from_msg(msg["progress_data"])
+ if "progress_data" in msg
+ else None,
+ log=log_message,
+ )
+ output = msg.get("output", {}).get("data", [])
+ if output and status_update.code != Status.FINISHED:
+ try:
+ result = helper.prediction_processor(*output)
+ except Exception as e:
+ result = [e]
+ helper.job.outputs.append(result)
+ helper.job.latest_status = status_update
+ if msg["msg"] == ServerMessage.process_completed:
+ del pending_messages_per_event[event_id]
+ return msg["output"]
+ elif msg["msg"] == ServerMessage.server_stopped:
+ raise ValueError("Server stopped.")
+
+ except asyncio.CancelledError:
+ raise
+
+
+########################
+# Data processing utils
+########################
+
+
+def download_file(
+ url_path: str,
+ dir: str,
+ hf_token: str | None = None,
+) -> str:
+ if dir is not None:
+ os.makedirs(dir, exist_ok=True)
+ headers = {"Authorization": "Bearer " + hf_token} if hf_token else {}
+
+ sha1 = hashlib.sha1()
+ temp_dir = Path(tempfile.gettempdir()) / secrets.token_hex(20)
+ temp_dir.mkdir(exist_ok=True, parents=True)
+
+ with httpx.stream("GET", url_path, headers=headers) as response:
+ response.raise_for_status()
+ with open(temp_dir / Path(url_path).name, "wb") as f:
+ for chunk in response.iter_bytes(chunk_size=128 * sha1.block_size):
+ sha1.update(chunk)
+ f.write(chunk)
+
+ directory = Path(dir) / sha1.hexdigest()
+ directory.mkdir(exist_ok=True, parents=True)
+ dest = directory / Path(url_path).name
+ shutil.move(temp_dir / Path(url_path).name, dest)
+ return str(dest.resolve())
+
+
+def create_tmp_copy_of_file(file_path: str, dir: str | None = None) -> str:
+ directory = Path(dir or tempfile.gettempdir()) / secrets.token_hex(20)
+ directory.mkdir(exist_ok=True, parents=True)
+ dest = directory / Path(file_path).name
+ shutil.copy2(file_path, dest)
+ return str(dest.resolve())
+
+
+def download_tmp_copy_of_file(
+ url_path: str, hf_token: str | None = None, dir: str | None = None
+) -> str:
+ """Kept for backwards compatibility for 3.x spaces."""
+ if dir is not None:
+ os.makedirs(dir, exist_ok=True)
+ headers = {"Authorization": "Bearer " + hf_token} if hf_token else {}
+ directory = Path(dir or tempfile.gettempdir()) / secrets.token_hex(20)
+ directory.mkdir(exist_ok=True, parents=True)
+ file_path = directory / Path(url_path).name
+
+ with httpx.stream("GET", url_path, headers=headers) as response:
+ response.raise_for_status()
+ with open(file_path, "wb") as f:
+ for chunk in response.iter_raw():
+ f.write(chunk)
+ return str(file_path.resolve())
+
+
+def get_mimetype(filename: str) -> str | None:
+ if filename.endswith(".vtt"):
+ return "text/vtt"
+ mimetype = mimetypes.guess_type(filename)[0]
+ if mimetype is not None:
+ mimetype = mimetype.replace("x-wav", "wav").replace("x-flac", "flac")
+ return mimetype
+
+
+def get_extension(encoding: str) -> str | None:
+ encoding = encoding.replace("audio/wav", "audio/x-wav")
+ type = mimetypes.guess_type(encoding)[0]
+ if type == "audio/flac": # flac is not supported by mimetypes
+ return "flac"
+ elif type is None:
+ return None
+ extension = mimetypes.guess_extension(type)
+ if extension is not None and extension.startswith("."):
+ extension = extension[1:]
+ return extension
+
+
+def encode_file_to_base64(f: str | Path):
+ with open(f, "rb") as file:
+ encoded_string = base64.b64encode(file.read())
+ base64_str = str(encoded_string, "utf-8")
+ mimetype = get_mimetype(str(f))
+ return (
+ "data:"
+ + (mimetype if mimetype is not None else "")
+ + ";base64,"
+ + base64_str
+ )
+
+
+def encode_url_to_base64(url: str):
+ resp = httpx.get(url)
+ resp.raise_for_status()
+ encoded_string = base64.b64encode(resp.content)
+ base64_str = str(encoded_string, "utf-8")
+ mimetype = get_mimetype(url)
+ return (
+ "data:" + (mimetype if mimetype is not None else "") + ";base64," + base64_str
+ )
+
+
+def encode_url_or_file_to_base64(path: str | Path):
+ path = str(path)
+ if is_http_url_like(path):
+ return encode_url_to_base64(path)
+ return encode_file_to_base64(path)
+
+
+def download_byte_stream(url: str, hf_token=None):
+ arr = bytearray()
+ headers = {"Authorization": "Bearer " + hf_token} if hf_token else {}
+ with httpx.stream("GET", url, headers=headers) as r:
+ for data in r.iter_bytes():
+ arr += data
+ yield data
+ yield arr
+
+
+def decode_base64_to_binary(encoding: str) -> tuple[bytes, str | None]:
+ extension = get_extension(encoding)
+ data = encoding.rsplit(",", 1)[-1]
+ return base64.b64decode(data), extension
+
+
+def strip_invalid_filename_characters(filename: str, max_bytes: int = 200) -> str:
+ """Strips invalid characters from a filename and ensures that the file_length is less than `max_bytes` bytes."""
+ filename = "".join([char for char in filename if char.isalnum() or char in "._- "])
+ filename_len = len(filename.encode())
+ if filename_len > max_bytes:
+ while filename_len > max_bytes:
+ if len(filename) == 0:
+ break
+ filename = filename[:-1]
+ filename_len = len(filename.encode())
+ return filename
+
+
+def sanitize_parameter_names(original_name: str) -> str:
+ """Cleans up a Python parameter name to make the API info more readable."""
+ return (
+ "".join([char for char in original_name if char.isalnum() or char in " _"])
+ .replace(" ", "_")
+ .lower()
+ )
+
+
+def decode_base64_to_file(
+ encoding: str,
+ file_path: str | None = None,
+ dir: str | Path | None = None,
+ prefix: str | None = None,
+):
+ directory = Path(dir or tempfile.gettempdir()) / secrets.token_hex(20)
+ directory.mkdir(exist_ok=True, parents=True)
+ data, extension = decode_base64_to_binary(encoding)
+ if file_path is not None and prefix is None:
+ filename = Path(file_path).name
+ prefix = filename
+ if "." in filename:
+ prefix = filename[0 : filename.index(".")]
+ extension = filename[filename.index(".") + 1 :]
+
+ if prefix is not None:
+ prefix = strip_invalid_filename_characters(prefix)
+
+ if extension is None:
+ file_obj = tempfile.NamedTemporaryFile(
+ delete=False, prefix=prefix, dir=directory
+ )
+ else:
+ file_obj = tempfile.NamedTemporaryFile(
+ delete=False,
+ prefix=prefix,
+ suffix="." + extension,
+ dir=directory,
+ )
+ file_obj.write(data)
+ file_obj.flush()
+ return file_obj
+
+
+def dict_or_str_to_json_file(jsn: str | dict | list, dir: str | Path | None = None):
+ if dir is not None:
+ os.makedirs(dir, exist_ok=True)
+
+ file_obj = tempfile.NamedTemporaryFile(
+ delete=False, suffix=".json", dir=dir, mode="w+"
+ )
+ if isinstance(jsn, str):
+ jsn = json.loads(jsn)
+ json.dump(jsn, file_obj)
+ file_obj.flush()
+ return file_obj
+
+
+def file_to_json(file_path: str | Path) -> dict | list:
+ with open(file_path) as f:
+ return json.load(f)
+
+
+###########################
+# HuggingFace Hub API Utils
+###########################
+def set_space_timeout(
+ space_id: str,
+ hf_token: str | None = None,
+ timeout_in_seconds: int = 300,
+):
+ headers = huggingface_hub.utils.build_hf_headers(
+ token=hf_token,
+ library_name="gradio_client",
+ library_version=__version__,
+ )
+ try:
+ httpx.post(
+ f"https://huggingface.co/api/spaces/{space_id}/sleeptime",
+ json={"seconds": timeout_in_seconds},
+ headers=headers,
+ )
+ except httpx.HTTPStatusError as e:
+ raise SpaceDuplicationError(
+ f"Could not set sleep timeout on duplicated Space. Please visit {SPACE_URL.format(space_id)} "
+ "to set a timeout manually to reduce billing charges."
+ ) from e
+
+
+########################
+# Misc utils
+########################
+
+
+def synchronize_async(func: Callable, *args, **kwargs) -> Any:
+ """
+ Runs async functions in sync scopes. Can be used in any scope.
+
+ Example:
+ if inspect.iscoroutinefunction(block_fn.fn):
+ predictions = utils.synchronize_async(block_fn.fn, *processed_input)
+
+ Args:
+ func:
+ *args:
+ **kwargs:
+ """
+ return fsspec.asyn.sync(fsspec.asyn.get_loop(), func, *args, **kwargs) # type: ignore
+
+
+class APIInfoParseError(ValueError):
+ pass
+
+
+def get_type(schema: dict):
+ if "const" in schema:
+ return "const"
+ if "enum" in schema:
+ return "enum"
+ elif "type" in schema:
+ return schema["type"]
+ elif schema.get("$ref"):
+ return "$ref"
+ elif schema.get("oneOf"):
+ return "oneOf"
+ elif schema.get("anyOf"):
+ return "anyOf"
+ elif schema.get("allOf"):
+ return "allOf"
+ elif "type" not in schema:
+ return {}
+ else:
+ raise APIInfoParseError(f"Cannot parse type for {schema}")
+
+
+FILE_DATA = "Dict(path: str, url: str | None, size: int | None, orig_name: str | None, mime_type: str | None)"
+
+
+def json_schema_to_python_type(schema: Any) -> str:
+ type_ = _json_schema_to_python_type(schema, schema.get("$defs"))
+ return type_.replace(FILE_DATA, "filepath")
+
+
+def _json_schema_to_python_type(schema: Any, defs) -> str:
+ """Convert the json schema into a python type hint"""
+ if schema == {}:
+ return "Any"
+ type_ = get_type(schema)
+ if type_ == {}:
+ if "json" in schema.get("description", {}):
+ return "Dict[Any, Any]"
+ else:
+ return "Any"
+ elif type_ == "$ref":
+ return _json_schema_to_python_type(defs[schema["$ref"].split("/")[-1]], defs)
+ elif type_ == "null":
+ return "None"
+ elif type_ == "const":
+ return f"Literal[{schema['const']}]"
+ elif type_ == "enum":
+ return (
+ "Literal[" + ", ".join(["'" + str(v) + "'" for v in schema["enum"]]) + "]"
+ )
+ elif type_ == "integer":
+ return "int"
+ elif type_ == "string":
+ return "str"
+ elif type_ == "boolean":
+ return "bool"
+ elif type_ == "number":
+ return "float"
+ elif type_ == "array":
+ items = schema.get("items", [])
+ if "prefixItems" in items:
+ elements = ", ".join(
+ [_json_schema_to_python_type(i, defs) for i in items["prefixItems"]]
+ )
+ return f"Tuple[{elements}]"
+ elif "prefixItems" in schema:
+ elements = ", ".join(
+ [_json_schema_to_python_type(i, defs) for i in schema["prefixItems"]]
+ )
+ return f"Tuple[{elements}]"
+ else:
+ elements = _json_schema_to_python_type(items, defs)
+ return f"List[{elements}]"
+ elif type_ == "object":
+
+ def get_desc(v):
+ return f" ({v.get('description')})" if v.get("description") else ""
+
+ props = schema.get("properties", {})
+
+ des = [
+ f"{n}: {_json_schema_to_python_type(v, defs)}{get_desc(v)}"
+ for n, v in props.items()
+ if n != "$defs"
+ ]
+
+ if "additionalProperties" in schema:
+ des += [
+ f"str, {_json_schema_to_python_type(schema['additionalProperties'], defs)}"
+ ]
+ des = ", ".join(des)
+ return f"Dict({des})"
+ elif type_ in ["oneOf", "anyOf"]:
+ desc = " | ".join([_json_schema_to_python_type(i, defs) for i in schema[type_]])
+ return desc
+ elif type_ == "allOf":
+ data = ", ".join(_json_schema_to_python_type(i, defs) for i in schema[type_])
+ desc = f"All[{data}]"
+ return desc
+ else:
+ raise APIInfoParseError(f"Cannot parse schema {schema}")
+
+
+def traverse(json_obj: Any, func: Callable, is_root: Callable) -> Any:
+ if is_root(json_obj):
+ return func(json_obj)
+ elif isinstance(json_obj, dict):
+ new_obj = {}
+ for key, value in json_obj.items():
+ new_obj[key] = traverse(value, func, is_root)
+ return new_obj
+ elif isinstance(json_obj, (list, tuple)):
+ new_obj = []
+ for item in json_obj:
+ new_obj.append(traverse(item, func, is_root))
+ return new_obj
+ else:
+ return json_obj
+
+
+def value_is_file(api_info: dict) -> bool:
+ info = _json_schema_to_python_type(api_info, api_info.get("$defs"))
+ return FILE_DATA in info
+
+
+def is_filepath(s):
+ return isinstance(s, str) and Path(s).exists()
+
+
+def is_url(s):
+ return isinstance(s, str) and is_http_url_like(s)
+
+
+def is_file_obj(d):
+ return isinstance(d, dict) and "path" in d
+
+
+SKIP_COMPONENTS = {
+ "state",
+ "row",
+ "column",
+ "tabs",
+ "tab",
+ "tabitem",
+ "box",
+ "form",
+ "accordion",
+ "group",
+ "interpretation",
+ "dataset",
+}
diff --git a/client/python/pyproject.toml b/client/python/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..bb44e1ac458d9d0375c63dd9004a9d7feddd7ad1
--- /dev/null
+++ b/client/python/pyproject.toml
@@ -0,0 +1,70 @@
+[build-system]
+requires = ["hatchling", "hatch-requirements-txt", "hatch-fancy-pypi-readme>=22.5.0"]
+build-backend = "hatchling.build"
+
+[project]
+name = "gradio_client"
+dynamic = ["version", "dependencies", "readme"]
+description = "Python library for easily interacting with trained machine learning models"
+license = "Apache-2.0"
+requires-python = ">=3.8"
+authors = [
+ { name = "Abubakar Abid", email = "gradio-team@huggingface.co" },
+ { name = "Ali Abid", email = "gradio-team@huggingface.co" },
+ { name = "Ali Abdalla", email = "gradio-team@huggingface.co" },
+ { name = "Dawood Khan", email = "gradio-team@huggingface.co" },
+ { name = "Ahsen Khaliq", email = "gradio-team@huggingface.co" },
+ { name = "Pete Allen", email = "gradio-team@huggingface.co" },
+ { name = "Freddy Boulton", email = "gradio-team@huggingface.co" },
+]
+keywords = ["machine learning", "client", "API"]
+
+classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Topic :: Scientific/Engineering',
+ 'Topic :: Scientific/Engineering :: Artificial Intelligence',
+ 'Topic :: Software Development :: User Interfaces',
+]
+
+[project.urls]
+Homepage = "https://github.com/gradio-app/gradio"
+
+[tool.hatch.version]
+path = "gradio_client/package.json"
+pattern = ".*\"version\":\\s*\"(?P[^\"]+)\""
+
+[tool.hatch.metadata.hooks.requirements_txt]
+filename = "requirements.txt"
+
+[tool.hatch.metadata.hooks.fancy-pypi-readme]
+content-type = "text/markdown"
+fragments = [
+ { path = "README.md" },
+]
+
+[tool.hatch.build.targets.sdist]
+include = [
+ "/gradio_client",
+ "/README.md",
+ "/requirements.txt",
+]
+
+[tool.ruff]
+extend = "../../pyproject.toml"
+
+[tool.ruff.isort]
+known-first-party = [
+ "gradio_client"
+]
+
+[tool.pytest.ini_options]
+GRADIO_ANALYTICS_ENABLED = "False"
+HF_HUB_DISABLE_TELEMETRY = "1"
\ No newline at end of file
diff --git a/client/python/requirements.txt b/client/python/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..542beefa29a77bfab7d72e7f839279d093e2ebfb
--- /dev/null
+++ b/client/python/requirements.txt
@@ -0,0 +1,6 @@
+fsspec
+httpx
+huggingface_hub>=0.19.3
+packaging
+typing_extensions~=4.0
+websockets>=10.0,<12.0
diff --git a/client/python/scripts/build_pypi.sh b/client/python/scripts/build_pypi.sh
new file mode 100644
index 0000000000000000000000000000000000000000..530e0c863642c3afad391b9eea6706b084d59079
--- /dev/null
+++ b/client/python/scripts/build_pypi.sh
@@ -0,0 +1,8 @@
+#!/bin/bash -eu
+
+cd "$(dirname ${0})/.."
+
+python3 -m pip install build
+rm -rf dist/*
+rm -rf build/*
+python3 -m build
diff --git a/client/python/scripts/check_pypi.py b/client/python/scripts/check_pypi.py
new file mode 100644
index 0000000000000000000000000000000000000000..8f2cf69930b9fd7685c5e3b02893edfb7158523f
--- /dev/null
+++ b/client/python/scripts/check_pypi.py
@@ -0,0 +1,17 @@
+import json
+import sys
+import urllib.request
+from pathlib import Path
+
+version_file = Path(__file__).parent.parent / "gradio_client" / "package.json"
+with version_file.open() as f:
+ version = json.load(f)["version"]
+
+with urllib.request.urlopen("https://pypi.org/pypi/gradio_client/json") as url:
+ releases = json.load(url)["releases"]
+
+if version in releases:
+ print(f"Version {version} already exists on PyPI")
+ sys.exit(1)
+else:
+ print(f"Version {version} does not exist on PyPI")
diff --git a/client/python/scripts/format.sh b/client/python/scripts/format.sh
new file mode 100644
index 0000000000000000000000000000000000000000..57df75639e373ce0dbc90d5fad808cb102cebdb4
--- /dev/null
+++ b/client/python/scripts/format.sh
@@ -0,0 +1,10 @@
+#!/bin/bash -eu
+
+cd "$(dirname ${0})/.."
+
+echo "Formatting the client library.. Our style follows the ruff code style."
+python -m ruff --fix .
+python -m ruff format .
+
+echo "Type checking the client library with pyright"
+python -m pyright gradio_client/*.py
diff --git a/client/python/scripts/lint.sh b/client/python/scripts/lint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..bc68fe8b21540dc6e1cefd6667a98ab8e7bccbfa
--- /dev/null
+++ b/client/python/scripts/lint.sh
@@ -0,0 +1,10 @@
+#!/bin/bash -eu
+
+cd "$(dirname ${0})/.."
+
+echo "Linting..."
+python -m ruff test gradio_client
+python -m ruff format --check test gradio_client
+
+echo "Type checking the client library with pyright"
+python -m pyright gradio_client/*.py
diff --git a/client/python/scripts/test.sh b/client/python/scripts/test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..12c480d6c08b321a6d52a954319e4bdde1e87fb4
--- /dev/null
+++ b/client/python/scripts/test.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -eu
+
+cd "$(dirname ${0})/.."
+
+echo "Testing..."
+python -m pytest test
diff --git a/client/python/test/conftest.py b/client/python/test/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..d473c4a2c51fbdb2986e81f6fa8c4e1ed788fd52
--- /dev/null
+++ b/client/python/test/conftest.py
@@ -0,0 +1,398 @@
+import inspect
+import random
+import time
+
+import gradio as gr
+import pytest
+from pydub import AudioSegment
+
+
+def pytest_configure(config):
+ config.addinivalue_line(
+ "markers", "flaky: mark test as flaky. Failure will not cause te"
+ )
+
+
+@pytest.fixture
+def calculator_demo():
+ def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ if num2 == 0:
+ raise gr.Error("Cannot divide by zero!")
+ return num1 / num2
+
+ demo = gr.Interface(
+ calculator,
+ ["number", gr.Radio(["add", "subtract", "multiply", "divide"]), "number"],
+ "number",
+ examples=[
+ [5, "add", 3],
+ [4, "divide", 2],
+ [-4, "multiply", 2.5],
+ [0, "subtract", 1.2],
+ ],
+ )
+ return demo
+
+
+@pytest.fixture
+def state_demo():
+ demo = gr.Interface(
+ lambda x, y: (x, y),
+ ["textbox", "state"],
+ ["textbox", "state"],
+ )
+ return demo
+
+
+@pytest.fixture
+def increment_demo():
+ with gr.Blocks() as demo:
+ btn1 = gr.Button("Increment")
+ btn2 = gr.Button("Increment")
+ btn3 = gr.Button("Increment")
+ numb = gr.Number()
+
+ state = gr.State(0)
+
+ btn1.click(
+ lambda x: (x + 1, x + 1),
+ state,
+ [state, numb],
+ api_name="increment_with_queue",
+ )
+ btn2.click(
+ lambda x: (x + 1, x + 1),
+ state,
+ [state, numb],
+ queue=False,
+ api_name="increment_without_queue",
+ )
+ btn3.click(
+ lambda x: (x + 1, x + 1),
+ state,
+ [state, numb],
+ api_name=False,
+ )
+
+ return demo
+
+
+@pytest.fixture
+def progress_demo():
+ def my_function(x, progress=gr.Progress()):
+ progress(0, desc="Starting...")
+ for _ in progress.tqdm(range(20)):
+ time.sleep(0.1)
+ return x
+
+ return gr.Interface(my_function, gr.Textbox(), gr.Textbox())
+
+
+@pytest.fixture
+def yield_demo():
+ def spell(x):
+ for i in range(len(x)):
+ time.sleep(0.5)
+ yield x[:i]
+
+ return gr.Interface(spell, "textbox", "textbox")
+
+
+@pytest.fixture
+def cancel_from_client_demo():
+ def iteration():
+ for i in range(20):
+ print(f"i: {i}")
+ yield i
+ time.sleep(0.5)
+
+ def long_process():
+ time.sleep(10)
+ print("DONE!")
+ return 10
+
+ with gr.Blocks() as demo:
+ num = gr.Number()
+
+ btn = gr.Button(value="Iterate")
+ btn.click(iteration, None, num, api_name="iterate")
+ btn2 = gr.Button(value="Long Process")
+ btn2.click(long_process, None, num, api_name="long")
+
+ return demo
+
+
+@pytest.fixture
+def sentiment_classification_demo():
+ def classifier(text):
+ time.sleep(1)
+ return {label: random.random() for label in ["POSITIVE", "NEGATIVE", "NEUTRAL"]}
+
+ def sleep_for_test():
+ time.sleep(10)
+ return 2
+
+ with gr.Blocks(theme="gstaff/xkcd") as demo:
+ with gr.Row():
+ with gr.Column():
+ input_text = gr.Textbox(label="Input Text")
+ with gr.Row():
+ classify = gr.Button("Classify Sentiment")
+ with gr.Column():
+ label = gr.Label(label="Predicted Sentiment")
+ number = gr.Number()
+ btn = gr.Button("Sleep then print")
+ classify.click(classifier, input_text, label, api_name="classify")
+ btn.click(sleep_for_test, None, number, api_name="sleep")
+
+ return demo
+
+
+@pytest.fixture
+def count_generator_demo():
+ def count(n):
+ for i in range(int(n)):
+ time.sleep(0.5)
+ yield i
+
+ def show(n):
+ return str(list(range(int(n))))
+
+ with gr.Blocks() as demo:
+ with gr.Column():
+ num = gr.Number(value=10)
+ with gr.Row():
+ count_btn = gr.Button("Count")
+ list_btn = gr.Button("List")
+ with gr.Column():
+ out = gr.Textbox()
+
+ count_btn.click(count, num, out)
+ list_btn.click(show, num, out)
+
+ return demo
+
+
+@pytest.fixture
+def count_generator_no_api():
+ def count(n):
+ for i in range(int(n)):
+ time.sleep(0.5)
+ yield i
+
+ def show(n):
+ return str(list(range(int(n))))
+
+ with gr.Blocks() as demo:
+ with gr.Column():
+ num = gr.Number(value=10)
+ with gr.Row():
+ count_btn = gr.Button("Count")
+ list_btn = gr.Button("List")
+ with gr.Column():
+ out = gr.Textbox()
+
+ count_btn.click(count, num, out, api_name=False)
+ list_btn.click(show, num, out, api_name=False)
+
+ return demo
+
+
+@pytest.fixture
+def count_generator_demo_exception():
+ def count(n):
+ for i in range(int(n)):
+ time.sleep(0.1)
+ if i == 5:
+ raise ValueError("Oh no!")
+ yield i
+
+ def show(n):
+ return str(list(range(int(n))))
+
+ with gr.Blocks() as demo:
+ with gr.Column():
+ num = gr.Number(value=10)
+ with gr.Row():
+ count_btn = gr.Button("Count")
+ count_forever = gr.Button("Count forever")
+ with gr.Column():
+ out = gr.Textbox()
+
+ count_btn.click(count, num, out, api_name="count")
+ count_forever.click(show, num, out, api_name="count_forever", every=3)
+ return demo
+
+
+@pytest.fixture
+def file_io_demo():
+ demo = gr.Interface(
+ lambda x: print("foox"),
+ [gr.File(file_count="multiple"), "file"],
+ [gr.File(file_count="multiple"), "file"],
+ )
+
+ return demo
+
+
+@pytest.fixture
+def stateful_chatbot():
+ with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ msg = gr.Textbox()
+ clear = gr.Button("Clear")
+ st = gr.State([1, 2, 3])
+
+ def respond(message, st, chat_history):
+ assert st[0] == 1 and st[1] == 2 and st[2] == 3
+ bot_message = "I love you"
+ chat_history.append((message, bot_message))
+ return "", chat_history
+
+ msg.submit(respond, [msg, st, chatbot], [msg, chatbot], api_name="submit")
+ clear.click(lambda: None, None, chatbot, queue=False)
+ return demo
+
+
+@pytest.fixture
+def hello_world_with_group():
+ with gr.Blocks() as demo:
+ name = gr.Textbox(label="name")
+ output = gr.Textbox(label="greeting")
+ greet = gr.Button("Greet")
+ show_group = gr.Button("Show group")
+ with gr.Group(visible=False) as group:
+ gr.Textbox("Hello!")
+
+ def greeting(name):
+ return f"Hello {name}", gr.Group(visible=True)
+
+ greet.click(
+ greeting, inputs=[name], outputs=[output, group], api_name="greeting"
+ )
+ show_group.click(
+ lambda: gr.Group(visible=False), None, group, api_name="show_group"
+ )
+ return demo
+
+
+@pytest.fixture
+def hello_world_with_state_and_accordion():
+ with gr.Blocks() as demo:
+ with gr.Row():
+ name = gr.Textbox(label="name")
+ output = gr.Textbox(label="greeting")
+ num = gr.Number(label="count")
+ with gr.Row():
+ n_counts = gr.State(value=0)
+ greet = gr.Button("Greet")
+ open_acc = gr.Button("Open acc")
+ close_acc = gr.Button("Close acc")
+ with gr.Accordion(label="Extra stuff", open=False) as accordion:
+ gr.Textbox("Hello!")
+
+ def greeting(name, state):
+ state += 1
+ return state, f"Hello {name}", state, gr.Accordion(open=False)
+
+ greet.click(
+ greeting,
+ inputs=[name, n_counts],
+ outputs=[n_counts, output, num, accordion],
+ api_name="greeting",
+ )
+ open_acc.click(
+ lambda state: (state + 1, state + 1, gr.Accordion(open=True)),
+ [n_counts],
+ [n_counts, num, accordion],
+ api_name="open",
+ )
+ close_acc.click(
+ lambda state: (state + 1, state + 1, gr.Accordion(open=False)),
+ [n_counts],
+ [n_counts, num, accordion],
+ api_name="close",
+ )
+ return demo
+
+
+@pytest.fixture
+def stream_audio():
+ import pathlib
+ import tempfile
+
+ def _stream_audio(audio_file):
+ audio = AudioSegment.from_mp3(audio_file)
+ i = 0
+ chunk_size = 3000
+
+ while chunk_size * i < len(audio):
+ chunk = audio[chunk_size * i : chunk_size * (i + 1)]
+ i += 1
+ if chunk:
+ file = str(pathlib.Path(tempfile.gettempdir()) / f"{i}.wav")
+ chunk.export(file, format="wav")
+ yield file
+
+ return gr.Interface(
+ fn=_stream_audio,
+ inputs=gr.Audio(type="filepath", label="Audio file to stream"),
+ outputs=gr.Audio(autoplay=True, streaming=True),
+ )
+
+
+@pytest.fixture
+def video_component():
+ return gr.Interface(fn=lambda x: x, inputs=gr.Video(), outputs=gr.Video())
+
+
+@pytest.fixture
+def all_components():
+ classes_to_check = gr.components.Component.__subclasses__()
+ subclasses = []
+
+ while classes_to_check:
+ subclass = classes_to_check.pop()
+ children = subclass.__subclasses__()
+
+ if children:
+ classes_to_check.extend(children)
+ if (
+ "value" in inspect.signature(subclass).parameters
+ and subclass != gr.components.Component
+ and not getattr(subclass, "is_template", False)
+ ):
+ subclasses.append(subclass)
+
+ return subclasses
+
+
+@pytest.fixture(autouse=True)
+def gradio_temp_dir(monkeypatch, tmp_path):
+ """tmp_path is unique to each test function.
+ It will be cleared automatically according to pytest docs: https://docs.pytest.org/en/6.2.x/reference.html#tmp-path
+ """
+ monkeypatch.setenv("GRADIO_TEMP_DIR", str(tmp_path))
+ return tmp_path
+
+
+@pytest.fixture
+def long_response_with_info():
+ def long_response(x):
+ gr.Info("Beginning long response")
+ time.sleep(17)
+ gr.Info("Done!")
+ return "\ta\nb" * 90000
+
+ return gr.Interface(
+ long_response,
+ None,
+ gr.Textbox(label="Output"),
+ )
diff --git a/client/python/test/requirements.txt b/client/python/test/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e6042f8631275bc9289eca26afde0d640734e9ee
--- /dev/null
+++ b/client/python/test/requirements.txt
@@ -0,0 +1,6 @@
+pytest-asyncio
+pytest==7.1.2
+ruff==0.1.7
+pyright==1.1.327
+gradio
+pydub==0.25.1
diff --git a/client/python/test/test_client.py b/client/python/test/test_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..62eadf529868b4d8031af234571b14f5f83eb409
--- /dev/null
+++ b/client/python/test/test_client.py
@@ -0,0 +1,1224 @@
+import json
+import os
+import pathlib
+import tempfile
+import time
+import uuid
+from concurrent.futures import CancelledError, TimeoutError, wait
+from contextlib import contextmanager
+from datetime import datetime, timedelta
+from pathlib import Path
+from unittest.mock import MagicMock, patch
+
+import gradio as gr
+import huggingface_hub
+import pytest
+import uvicorn
+from fastapi import FastAPI
+from gradio.networking import Server
+from huggingface_hub import HfFolder
+from huggingface_hub.utils import RepositoryNotFoundError
+
+from gradio_client import Client
+from gradio_client.client import DEFAULT_TEMP_DIR
+from gradio_client.utils import (
+ Communicator,
+ ProgressUnit,
+ QueueError,
+ Status,
+ StatusUpdate,
+)
+
+HF_TOKEN = os.getenv("HF_TOKEN") or HfFolder.get_token()
+
+
+@contextmanager
+def connect(
+ demo: gr.Blocks, serialize: bool = True, output_dir: str = DEFAULT_TEMP_DIR
+):
+ _, local_url, _ = demo.launch(prevent_thread_lock=True)
+ try:
+ yield Client(local_url, serialize=serialize, output_dir=output_dir)
+ finally:
+ # A more verbose version of .close()
+ # because we should set a timeout
+ # the tests that call .cancel() can get stuck
+ # waiting for the thread to join
+ if demo.enable_queue:
+ demo._queue.close()
+ demo.is_running = False
+ demo.server.should_exit = True
+ demo.server.thread.join(timeout=1)
+
+
+class TestClientPredictions:
+ @pytest.mark.flaky
+ def test_raise_error_invalid_state(self):
+ with pytest.raises(ValueError, match="invalid state"):
+ Client("gradio-tests/paused-space")
+
+ @pytest.mark.flaky
+ def test_numerical_to_label_space(self):
+ client = Client("gradio-tests/titanic-survival")
+ label = json.load(
+ open(client.predict("male", 77, 10, api_name="/predict")) # noqa: SIM115
+ )
+ assert label["label"] == "Perishes"
+ with pytest.raises(
+ ValueError,
+ match="This Gradio app might have multiple endpoints. Please specify an `api_name` or `fn_index`",
+ ):
+ client.predict("male", 77, 10)
+ with pytest.raises(
+ ValueError,
+ match="Cannot find a function with `api_name`: predict. Did you mean to use a leading slash?",
+ ):
+ client.predict("male", 77, 10, api_name="predict")
+
+ @pytest.mark.flaky
+ def test_numerical_to_label_space_v4(self):
+ client = Client("gradio-tests/titanic-survivalv4-sse")
+ label = client.predict("male", 77, 10, api_name="/predict")
+ assert label["label"] == "Perishes"
+
+ @pytest.mark.flaky
+ def test_private_space(self):
+ space_id = "gradio-tests/not-actually-private-space"
+ api = huggingface_hub.HfApi()
+ assert api.space_info(space_id).private
+ client = Client(space_id)
+ output = client.predict("abc", api_name="/predict")
+ assert output == "abc"
+
+ @pytest.mark.flaky
+ def test_private_space_v4(self):
+ space_id = "gradio-tests/not-actually-private-spacev4-sse"
+ api = huggingface_hub.HfApi()
+ assert api.space_info(space_id).private
+ client = Client(
+ space_id,
+ )
+ output = client.predict("abc", api_name="/predict")
+ assert output == "abc"
+
+ @pytest.mark.flaky
+ def test_private_space_v4_sse_v1(self):
+ space_id = "gradio-tests/not-actually-private-spacev4-sse-v1"
+ api = huggingface_hub.HfApi()
+ assert api.space_info(space_id).private
+ client = Client(
+ space_id,
+ )
+ output = client.predict("abc", api_name="/predict")
+ assert output == "abc"
+
+ def test_state(self, increment_demo):
+ with connect(increment_demo) as client:
+ output = client.predict(api_name="/increment_without_queue")
+ assert output == 1
+ output = client.predict(api_name="/increment_without_queue")
+ assert output == 2
+ output = client.predict(api_name="/increment_without_queue")
+ assert output == 3
+ client.reset_session()
+ output = client.predict(api_name="/increment_without_queue")
+ assert output == 1
+ output = client.predict(api_name="/increment_with_queue")
+ assert output == 2
+ client.reset_session()
+ output = client.predict(api_name="/increment_with_queue")
+ assert output == 1
+ output = client.predict(api_name="/increment_with_queue")
+ assert output == 2
+
+ def test_job_status(self, calculator_demo):
+ with connect(calculator_demo) as client:
+ statuses = []
+ job = client.submit(5, "add", 4, api_name="/predict")
+ while not job.done():
+ time.sleep(0.1)
+ statuses.append(job.status())
+
+ assert statuses
+ # Messages are sorted by time
+ assert sorted([s.time for s in statuses if s]) == [
+ s.time for s in statuses if s
+ ]
+ assert sorted([s.code for s in statuses if s]) == [
+ s.code for s in statuses if s
+ ]
+
+ @pytest.mark.flaky
+ def test_intermediate_outputs(self, count_generator_demo):
+ with connect(count_generator_demo) as client:
+ job = client.submit(3, fn_index=0)
+
+ while not job.done():
+ time.sleep(0.1)
+
+ assert job.outputs() == [str(i) for i in range(3)]
+
+ outputs = []
+ for o in client.submit(3, fn_index=0):
+ outputs.append(o)
+ assert outputs == [str(i) for i in range(3)]
+
+ @pytest.mark.flaky
+ def test_intermediate_outputs_with_exception(self, count_generator_demo_exception):
+ with connect(count_generator_demo_exception) as client:
+ with pytest.raises(Exception):
+ client.predict(7, api_name="/count")
+
+ with pytest.raises(
+ ValueError, match="Cannot call predict on this function"
+ ):
+ client.predict(5, api_name="/count_forever")
+
+ def test_break_in_loop_if_error(self, calculator_demo):
+ with connect(calculator_demo) as client:
+ job = client.submit("foo", "add", 4, fn_index=0)
+ output = list(job)
+ assert output == []
+
+ @pytest.mark.flaky
+ def test_timeout(self, sentiment_classification_demo):
+ with pytest.raises(TimeoutError):
+ with connect(sentiment_classification_demo.queue()) as client:
+ job = client.submit(api_name="/sleep")
+ job.result(timeout=0.05)
+
+ @pytest.mark.flaky
+ def test_timeout_no_queue(self, sentiment_classification_demo):
+ with pytest.raises(TimeoutError):
+ with connect(sentiment_classification_demo) as client:
+ job = client.submit(api_name="/sleep")
+ job.result(timeout=0.1)
+
+ def test_raises_exception(self, calculator_demo):
+ with pytest.raises(Exception):
+ with connect(calculator_demo) as client:
+ job = client.submit("foo", "add", 9, fn_index=0)
+ job.result()
+
+ def test_raises_exception_no_queue(self, sentiment_classification_demo):
+ with pytest.raises(Exception):
+ with connect(sentiment_classification_demo) as client:
+ job = client.submit([5], api_name="/sleep")
+ job.result()
+
+ def test_job_output_video(self, video_component):
+ with connect(video_component) as client:
+ job = client.submit(
+ {
+ "video": "https://huggingface.co/spaces/gradio/video_component/resolve/main/files/a.mp4"
+ },
+ fn_index=0,
+ )
+ assert Path(job.result()["video"]).exists()
+ assert (
+ Path(DEFAULT_TEMP_DIR).resolve()
+ in Path(job.result()["video"]).resolve().parents
+ )
+
+ temp_dir = tempfile.mkdtemp()
+ with connect(video_component, output_dir=temp_dir) as client:
+ job = client.submit(
+ {
+ "video": "https://huggingface.co/spaces/gradio/video_component/resolve/main/files/a.mp4"
+ },
+ fn_index=0,
+ )
+ assert Path(job.result()["video"]).exists()
+ assert (
+ Path(temp_dir).resolve()
+ in Path(job.result()["video"]).resolve().parents
+ )
+
+ def test_progress_updates(self, progress_demo):
+ with connect(progress_demo) as client:
+ job = client.submit("hello", api_name="/predict")
+ statuses = []
+ while not job.done():
+ statuses.append(job.status())
+ time.sleep(0.02)
+ assert any(s.code == Status.PROGRESS for s in statuses)
+ assert any(s.progress_data is not None for s in statuses)
+ all_progress_data = [
+ p for s in statuses if s.progress_data for p in s.progress_data
+ ]
+ count = 0
+ for i in range(20):
+ unit = ProgressUnit(
+ index=i, length=20, unit="steps", progress=None, desc=None
+ )
+ count += unit in all_progress_data
+ assert count
+
+ def test_cancel_from_client_queued(self, cancel_from_client_demo):
+ with connect(cancel_from_client_demo) as client:
+ start = time.time()
+ job = client.submit(api_name="/long")
+ while not job.done():
+ if job.status().code == Status.STARTING:
+ job.cancel()
+ break
+ with pytest.raises(CancelledError):
+ job.result()
+ # The whole prediction takes 10 seconds to run
+ # and does not iterate. So this tests that we can cancel
+ # halfway through a prediction
+ assert time.time() - start < 10
+ assert job.status().code == Status.CANCELLED
+
+ job = client.submit(api_name="/iterate")
+ iteration_count = 0
+ while not job.done():
+ if job.status().code == Status.ITERATING:
+ iteration_count += 1
+ if iteration_count == 3:
+ job.cancel()
+ break
+ time.sleep(0.5)
+ # Result for iterative jobs will raise there is an exception
+ with pytest.raises(CancelledError):
+ job.result()
+ # The whole prediction takes 10 seconds to run
+ # and does not iterate. So this tests that we can cancel
+ # halfway through a prediction
+ assert time.time() - start < 10
+
+ # Test that we did not iterate all the way to the end
+ assert all(o in [0, 1, 2, 3, 4, 5] for o in job.outputs())
+ assert job.status().code == Status.CANCELLED
+
+ def test_cancel_subsequent_jobs_state_reset(self, yield_demo):
+ with connect(yield_demo) as client:
+ job1 = client.submit("abcdefefadsadfs", api_name="/predict")
+ time.sleep(3)
+ job1.cancel()
+
+ assert len(job1.outputs()) > 0
+ assert len(job1.outputs()) < len("abcdefefadsadfs")
+ assert job1.status().code == Status.CANCELLED
+
+ job2 = client.submit("abcd", api_name="/predict")
+ assert len(job2.outputs()) == 0
+ while not job2.done():
+ time.sleep(0.1)
+ # Ran all iterations from scratch
+ assert job2.status().code == Status.FINISHED
+ assert len(job2.outputs()) == 4
+
+ @pytest.mark.xfail
+ def test_stream_audio(self, stream_audio):
+ with connect(stream_audio) as client:
+ job1 = client.submit(
+ "https://gradio-builds.s3.amazonaws.com/demo-files/bark_demo.mp4",
+ api_name="/predict",
+ )
+ assert Path(job1.result()).exists()
+
+ job2 = client.submit(
+ "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
+ api_name="/predict",
+ )
+ assert Path(job2.result()).exists()
+ assert all(Path(p).exists() for p in job2.outputs())
+
+ @pytest.mark.xfail
+ def test_upload_file_private_space_v4(self):
+ client = Client(
+ src="gradio-tests/not-actually-private-file-uploadv4-sse",
+ )
+
+ with patch.object(
+ client.endpoints[0], "_upload", wraps=client.endpoints[0]._upload
+ ) as upload:
+ with patch.object(
+ client.endpoints[0], "serialize", wraps=client.endpoints[0].serialize
+ ) as serialize:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ f.write("Hello from private space!")
+
+ output = client.submit(
+ 1, "foo", f.name, api_name="/file_upload"
+ ).result()
+ with open(output) as f:
+ assert f.read() == "Hello from private space!"
+ upload.assert_called_once()
+ assert all(f["is_file"] for f in serialize.return_value())
+
+ with patch.object(
+ client.endpoints[1], "_upload", wraps=client.endpoints[0]._upload
+ ) as upload:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ f.write("Hello from private space!")
+
+ with open(client.submit(f.name, api_name="/upload_btn").result()) as f:
+ assert f.read() == "Hello from private space!"
+ upload.assert_called_once()
+
+ with patch.object(
+ client.endpoints[2], "_upload", wraps=client.endpoints[0]._upload
+ ) as upload:
+ # `delete=False` is required for Windows compat
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f1:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f2:
+ f1.write("File1")
+ f2.write("File2")
+ r1, r2 = client.submit(
+ 3,
+ [f1.name, f2.name],
+ "hello",
+ api_name="/upload_multiple",
+ ).result()
+ with open(r1) as f:
+ assert f.read() == "File1"
+ with open(r2) as f:
+ assert f.read() == "File2"
+ upload.assert_called_once()
+
+ @pytest.mark.flaky
+ def test_upload_file_private_space(self):
+ client = Client(
+ src="gradio-tests/not-actually-private-file-upload",
+ hf_token=HF_TOKEN,
+ )
+
+ with patch.object(
+ client.endpoints[0], "serialize", wraps=client.endpoints[0].serialize
+ ) as serialize:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ f.write("Hello from private space!")
+
+ output = client.submit(1, "foo", f.name, api_name="/file_upload").result()
+ with open(output) as f:
+ assert f.read() == "Hello from private space!"
+ assert all(f["is_file"] for f in serialize.return_value())
+
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ f.write("Hello from private space!")
+
+ with open(client.submit(f.name, api_name="/upload_btn").result()) as f:
+ assert f.read() == "Hello from private space!"
+
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f1:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f2:
+ f1.write("File1")
+ f2.write("File2")
+ r1, r2 = client.submit(
+ 3,
+ [f1.name, f2.name],
+ "hello",
+ api_name="/upload_multiple",
+ ).result()
+ with open(r1) as f:
+ assert f.read() == "File1"
+ with open(r2) as f:
+ assert f.read() == "File2"
+
+ @pytest.mark.flaky
+ def test_upload_file_upload_route_does_not_exist(self):
+ client = Client(
+ src="gradio-tests/not-actually-private-file-upload-old-version",
+ hf_token=HF_TOKEN,
+ )
+
+ with patch.object(
+ client.endpoints[0], "serialize", wraps=client.endpoints[0].serialize
+ ) as serialize:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ f.write("Hello from private space!")
+
+ client.submit(1, "foo", f.name, fn_index=0).result()
+ serialize.assert_called_once_with(1, "foo", f.name)
+
+ def test_state_without_serialize(self, stateful_chatbot):
+ with connect(stateful_chatbot, serialize=False) as client:
+ initial_history = [["", None]]
+ message = "Hello"
+ ret = client.predict(message, initial_history, api_name="/submit")
+ assert ret == ("", [["", None], ["Hello", "I love you"]])
+
+ def test_can_call_mounted_app_via_api(self):
+ def greet(name):
+ return "Hello " + name + "!"
+
+ gradio_app = gr.Interface(
+ fn=greet,
+ inputs=gr.Textbox(lines=2, placeholder="Name Here..."),
+ outputs="text",
+ )
+
+ app = FastAPI()
+ app = gr.mount_gradio_app(app, gradio_app, path="/test/gradio")
+ config = uvicorn.Config(
+ app=app,
+ port=8000,
+ log_level="info",
+ )
+ server = Server(config=config)
+ # Using the gradio Server class to not have
+ # to implement code again to run uvicorn in a separate thread
+ # However, that means we need to set this flag to prevent
+ # run_in_thread_from_blocking
+ server.started = True
+ try:
+ server.run_in_thread()
+ time.sleep(1)
+ client = Client("http://127.0.0.1:8000/test/gradio/")
+ assert client.predict("freddy") == "Hello freddy!"
+ finally:
+ server.thread.join(timeout=1)
+
+ def test_predict_with_space_with_api_name_false(self):
+ client = Client("gradio-tests/client-bool-api-name-error")
+ assert client.predict("Hello!", api_name="/run") == "Hello!"
+ assert client.predict("Freddy", api_name="/say_hello") == "hello"
+
+ def test_return_layout_component(self, hello_world_with_group):
+ with connect(hello_world_with_group) as demo:
+ assert demo.predict("Freddy", api_name="/greeting") == "Hello Freddy"
+ assert demo.predict(api_name="/show_group") == ()
+
+ def test_return_layout_and_state_components(
+ self, hello_world_with_state_and_accordion
+ ):
+ with connect(hello_world_with_state_and_accordion) as demo:
+ assert demo.predict("Freddy", api_name="/greeting") == ("Hello Freddy", 1)
+ assert demo.predict("Abubakar", api_name="/greeting") == (
+ "Hello Abubakar",
+ 2,
+ )
+ assert demo.predict(api_name="/open") == 3
+ assert demo.predict(api_name="/close") == 4
+ assert demo.predict("Ali", api_name="/greeting") == ("Hello Ali", 5)
+
+ def test_long_response_time_with_gr_info_and_big_payload(
+ self, long_response_with_info
+ ):
+ with connect(long_response_with_info) as demo:
+ assert demo.predict(api_name="/predict") == "\ta\nb" * 90000
+
+ def test_queue_full_raises_error(self):
+ demo = gr.Interface(lambda s: f"Hello {s}", "textbox", "textbox").queue(
+ max_size=1
+ )
+ with connect(demo) as client:
+ with pytest.raises(QueueError):
+ job1 = client.submit("Freddy", api_name="/predict")
+ job2 = client.submit("Abubakar", api_name="/predict")
+ job3 = client.submit("Pete", api_name="/predict")
+ wait([job1, job2, job3])
+ job1.result()
+ job2.result()
+ job3.result()
+
+ def test_json_parse_error(self):
+ data = (
+ "Bonjour Olivier, tu as l'air bien r\u00e9veill\u00e9 ce matin. Tu veux que je te pr\u00e9pare tes petits-d\u00e9j.\n",
+ None,
+ )
+
+ def return_bad():
+ return data
+
+ demo = gr.Interface(return_bad, None, ["text", "text"])
+ with connect(demo) as client:
+ pred = client.predict(api_name="/predict")
+ assert pred[0] == data[0]
+
+
+class TestStatusUpdates:
+ @patch("gradio_client.client.Endpoint.make_end_to_end_fn")
+ def test_messages_passed_correctly(self, mock_make_end_to_end_fn, calculator_demo):
+ now = datetime.now()
+
+ messages = [
+ StatusUpdate(
+ code=Status.STARTING,
+ eta=None,
+ rank=None,
+ success=None,
+ queue_size=None,
+ time=now,
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.SENDING_DATA,
+ eta=None,
+ rank=None,
+ success=None,
+ queue_size=None,
+ time=now + timedelta(seconds=1),
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.IN_QUEUE,
+ eta=3,
+ rank=2,
+ queue_size=2,
+ success=None,
+ time=now + timedelta(seconds=2),
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.IN_QUEUE,
+ eta=2,
+ rank=1,
+ queue_size=1,
+ success=None,
+ time=now + timedelta(seconds=3),
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.ITERATING,
+ eta=None,
+ rank=None,
+ queue_size=None,
+ success=None,
+ time=now + timedelta(seconds=3),
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.FINISHED,
+ eta=None,
+ rank=None,
+ queue_size=None,
+ success=True,
+ time=now + timedelta(seconds=4),
+ progress_data=None,
+ ),
+ ]
+
+ class MockEndToEndFunction:
+ def __init__(self, communicator: Communicator):
+ self.communicator = communicator
+
+ def __call__(self, *args, **kwargs):
+ for m in messages:
+ with self.communicator.lock:
+ self.communicator.job.latest_status = m
+ time.sleep(0.1)
+
+ mock_make_end_to_end_fn.side_effect = MockEndToEndFunction
+
+ with connect(calculator_demo) as client:
+ job = client.submit(5, "add", 6, api_name="/predict")
+
+ statuses = []
+ while not job.done():
+ statuses.append(job.status())
+ time.sleep(0.09)
+
+ assert all(s in messages for s in statuses)
+
+ @patch("gradio_client.client.Endpoint.make_end_to_end_fn")
+ def test_messages_correct_two_concurrent(
+ self, mock_make_end_to_end_fn, calculator_demo
+ ):
+ now = datetime.now()
+
+ messages_1 = [
+ StatusUpdate(
+ code=Status.STARTING,
+ eta=None,
+ rank=None,
+ success=None,
+ queue_size=None,
+ time=now,
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.FINISHED,
+ eta=None,
+ rank=None,
+ queue_size=None,
+ success=True,
+ time=now + timedelta(seconds=4),
+ progress_data=None,
+ ),
+ ]
+
+ messages_2 = [
+ StatusUpdate(
+ code=Status.IN_QUEUE,
+ eta=3,
+ rank=2,
+ queue_size=2,
+ success=None,
+ time=now + timedelta(seconds=2),
+ progress_data=None,
+ ),
+ StatusUpdate(
+ code=Status.IN_QUEUE,
+ eta=2,
+ rank=1,
+ queue_size=1,
+ success=None,
+ time=now + timedelta(seconds=3),
+ progress_data=None,
+ ),
+ ]
+
+ class MockEndToEndFunction:
+ n_counts = 0
+
+ def __init__(self, communicator: Communicator):
+ self.communicator = communicator
+ self.messages = (
+ messages_1 if MockEndToEndFunction.n_counts == 0 else messages_2
+ )
+ MockEndToEndFunction.n_counts += 1
+
+ def __call__(self, *args, **kwargs):
+ for m in self.messages:
+ with self.communicator.lock:
+ print(f"here: {m}")
+ self.communicator.job.latest_status = m
+ time.sleep(0.1)
+
+ mock_make_end_to_end_fn.side_effect = MockEndToEndFunction
+
+ with connect(calculator_demo) as client:
+ job_1 = client.submit(5, "add", 6, api_name="/predict")
+ job_2 = client.submit(11, "subtract", 1, api_name="/predict")
+
+ statuses_1 = []
+ statuses_2 = []
+ while not (job_1.done() and job_2.done()):
+ statuses_1.append(job_1.status())
+ statuses_2.append(job_2.status())
+ time.sleep(0.05)
+
+ assert all(s in messages_1 for s in statuses_1)
+
+
+class TestAPIInfo:
+ @pytest.mark.parametrize("trailing_char", ["/", ""])
+ def test_test_endpoint_src(self, trailing_char):
+ src = "https://gradio-calculator.hf.space" + trailing_char
+ client = Client(src=src)
+ assert client.endpoints[0].root_url == "https://gradio-calculator.hf.space/"
+
+ @pytest.mark.flaky
+ def test_numerical_to_label_space(self):
+ client = Client("gradio-tests/titanic-survival")
+ assert client.view_api(return_format="dict") == {
+ "named_endpoints": {
+ "/predict": {
+ "parameters": [
+ {
+ "label": "Sex",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Radio",
+ "example_input": "Howdy!",
+ "serializer": "StringSerializable",
+ },
+ {
+ "label": "Age",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ {
+ "label": "Fare (british pounds)",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ ],
+ "returns": [
+ {
+ "label": "output",
+ "type": {"type": {}, "description": "any valid json"},
+ "python_type": {
+ "type": "str",
+ "description": "filepath to JSON file",
+ },
+ "component": "Label",
+ "serializer": "JSONSerializable",
+ }
+ ],
+ },
+ "/predict_1": {
+ "parameters": [
+ {
+ "label": "Sex",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Radio",
+ "example_input": "Howdy!",
+ "serializer": "StringSerializable",
+ },
+ {
+ "label": "Age",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ {
+ "label": "Fare (british pounds)",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ ],
+ "returns": [
+ {
+ "label": "output",
+ "type": {"type": {}, "description": "any valid json"},
+ "python_type": {
+ "type": "str",
+ "description": "filepath to JSON file",
+ },
+ "component": "Label",
+ "serializer": "JSONSerializable",
+ }
+ ],
+ },
+ "/predict_2": {
+ "parameters": [
+ {
+ "label": "Sex",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Radio",
+ "example_input": "Howdy!",
+ "serializer": "StringSerializable",
+ },
+ {
+ "label": "Age",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ {
+ "label": "Fare (british pounds)",
+ "type": {"type": "number"},
+ "python_type": {"type": "int | float", "description": ""},
+ "component": "Slider",
+ "example_input": 5,
+ "serializer": "NumberSerializable",
+ },
+ ],
+ "returns": [
+ {
+ "label": "output",
+ "type": {"type": {}, "description": "any valid json"},
+ "python_type": {
+ "type": "str",
+ "description": "filepath to JSON file",
+ },
+ "component": "Label",
+ "serializer": "JSONSerializable",
+ }
+ ],
+ },
+ },
+ "unnamed_endpoints": {},
+ }
+
+ def test_state_does_not_appear(self, state_demo):
+ with connect(state_demo) as client:
+ api_info = client.view_api(return_format="dict")
+ assert isinstance(api_info, dict)
+ for parameter in api_info["named_endpoints"]["/predict"]["parameters"]:
+ assert parameter["component"] != "State"
+
+ @pytest.mark.flaky
+ def test_private_space(self):
+ client = Client(
+ "gradio-tests/not-actually-private-space",
+ )
+ assert len(client.endpoints) == 3
+ assert len([e for e in client.endpoints if e.is_valid]) == 2
+ assert len([e for e in client.endpoints if e.is_valid and e.api_name]) == 1
+ assert client.view_api(return_format="dict") == {
+ "named_endpoints": {
+ "/predict": {
+ "parameters": [
+ {
+ "label": "x",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ "example_input": "Howdy!",
+ "serializer": "StringSerializable",
+ }
+ ],
+ "returns": [
+ {
+ "label": "output",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ "serializer": "StringSerializable",
+ }
+ ],
+ }
+ },
+ "unnamed_endpoints": {},
+ }
+
+ def test_api_info_of_local_demo(self, calculator_demo):
+ with connect(calculator_demo) as client:
+ api_info = client.view_api(return_format="dict")
+ assert isinstance(api_info, dict)
+ assert api_info["named_endpoints"]["/predict"] == {
+ "parameters": [
+ {
+ "label": "num1",
+ "type": {"type": "number"},
+ "python_type": {"type": "float", "description": ""},
+ "component": "Number",
+ "example_input": 3,
+ },
+ {
+ "label": "operation",
+ "type": {
+ "enum": ["add", "subtract", "multiply", "divide"],
+ "title": "Radio",
+ "type": "string",
+ },
+ "python_type": {
+ "type": "Literal['add', 'subtract', 'multiply', 'divide']",
+ "description": "",
+ },
+ "component": "Radio",
+ "example_input": "add",
+ },
+ {
+ "label": "num2",
+ "type": {"type": "number"},
+ "python_type": {"type": "float", "description": ""},
+ "component": "Number",
+ "example_input": 3,
+ },
+ ],
+ "returns": [
+ {
+ "label": "output",
+ "type": {"type": "number"},
+ "python_type": {"type": "float", "description": ""},
+ "component": "Number",
+ }
+ ],
+ }
+ assert api_info["unnamed_endpoints"] == {}
+
+ def test_unnamed_endpoints_use_fn_index(self, count_generator_demo):
+ with connect(count_generator_demo) as client:
+ info = client.view_api(return_format="str")
+ assert "fn_index" not in info
+ assert "api_name" in info
+
+ def test_api_false_endpoints_do_not_appear(self, count_generator_no_api):
+ with connect(count_generator_no_api) as client:
+ info = client.view_api(return_format="dict")
+ assert len(info["named_endpoints"]) == 0
+
+ def test_api_false_endpoints_cannot_be_accessed_with_fn_index(self, increment_demo):
+ with connect(increment_demo) as client:
+ with pytest.raises(ValueError):
+ client.submit(1, fn_index=2)
+
+ def test_file_io(self, file_io_demo):
+ with connect(file_io_demo) as client:
+ info = client.view_api(return_format="dict")
+ inputs = info["named_endpoints"]["/predict"]["parameters"]
+ outputs = info["named_endpoints"]["/predict"]["returns"]
+
+ assert inputs[0]["type"]["type"] == "array"
+ assert inputs[0]["python_type"] == {
+ "type": "List[filepath]",
+ "description": "",
+ }
+ assert isinstance(inputs[0]["example_input"], list)
+ assert isinstance(inputs[0]["example_input"][0], str)
+
+ assert inputs[1]["python_type"] == {
+ "type": "filepath",
+ "description": "",
+ }
+ assert isinstance(inputs[1]["example_input"], str)
+
+ assert outputs[0]["python_type"] == {
+ "type": "List[filepath]",
+ "description": "",
+ }
+ assert outputs[0]["type"]["type"] == "array"
+
+ assert outputs[1]["python_type"] == {
+ "type": "filepath",
+ "description": "",
+ }
+
+ def test_layout_components_in_output(self, hello_world_with_group):
+ with connect(hello_world_with_group) as client:
+ info = client.view_api(return_format="dict")
+ assert info == {
+ "named_endpoints": {
+ "/greeting": {
+ "parameters": [
+ {
+ "label": "name",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ "example_input": "Hello!!",
+ }
+ ],
+ "returns": [
+ {
+ "label": "greeting",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ }
+ ],
+ },
+ "/show_group": {"parameters": [], "returns": []},
+ },
+ "unnamed_endpoints": {},
+ }
+
+ def test_layout_and_state_components_in_output(
+ self, hello_world_with_state_and_accordion
+ ):
+ with connect(hello_world_with_state_and_accordion) as client:
+ info = client.view_api(return_format="dict")
+ assert info == {
+ "named_endpoints": {
+ "/greeting": {
+ "parameters": [
+ {
+ "label": "name",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ "example_input": "Hello!!",
+ }
+ ],
+ "returns": [
+ {
+ "label": "greeting",
+ "type": {"type": "string"},
+ "python_type": {"type": "str", "description": ""},
+ "component": "Textbox",
+ },
+ {
+ "label": "count",
+ "type": {"type": "number"},
+ "python_type": {
+ "type": "float",
+ "description": "",
+ },
+ "component": "Number",
+ },
+ ],
+ },
+ "/open": {
+ "parameters": [],
+ "returns": [
+ {
+ "label": "count",
+ "type": {"type": "number"},
+ "python_type": {
+ "type": "float",
+ "description": "",
+ },
+ "component": "Number",
+ }
+ ],
+ },
+ "/close": {
+ "parameters": [],
+ "returns": [
+ {
+ "label": "count",
+ "type": {"type": "number"},
+ "python_type": {
+ "type": "float",
+ "description": "",
+ },
+ "component": "Number",
+ }
+ ],
+ },
+ },
+ "unnamed_endpoints": {},
+ }
+
+
+class TestEndpoints:
+ @pytest.mark.flaky
+ def test_upload(self):
+ client = Client(
+ src="gradio-tests/not-actually-private-file-upload",
+ )
+ response = MagicMock(status_code=200)
+ response.json.return_value = [
+ "file1",
+ "file2",
+ "file3",
+ "file4",
+ "file5",
+ "file6",
+ "file7",
+ ]
+ with patch("httpx.post", MagicMock(return_value=response)):
+ with patch("builtins.open", MagicMock()):
+ with patch.object(pathlib.Path, "name") as mock_name:
+ mock_name.side_effect = lambda x: x
+ results = client.endpoints[0]._upload(
+ ["pre1", ["pre2", "pre3", "pre4"], ["pre5", "pre6"], "pre7"]
+ )
+
+ res = []
+ for re in results:
+ if isinstance(re, list):
+ res.append([r["name"] for r in re])
+ else:
+ res.append(re["name"])
+
+ assert res == [
+ "file1",
+ ["file2", "file3", "file4"],
+ ["file5", "file6"],
+ "file7",
+ ]
+
+ @pytest.mark.flaky
+ def test_upload_v4(self):
+ client = Client(
+ src="gradio-tests/not-actually-private-file-uploadv4-sse",
+ )
+ response = MagicMock(status_code=200)
+ response.json.return_value = [
+ "file1",
+ "file2",
+ "file3",
+ "file4",
+ "file5",
+ "file6",
+ "file7",
+ ]
+ with patch("httpx.post", MagicMock(return_value=response)):
+ with patch("builtins.open", MagicMock()):
+ with patch.object(pathlib.Path, "name") as mock_name:
+ mock_name.side_effect = lambda x: x
+ results = client.endpoints[0]._upload(
+ ["pre1", ["pre2", "pre3", "pre4"], ["pre5", "pre6"], "pre7"]
+ )
+
+ res = []
+ for re in results:
+ if isinstance(re, list):
+ res.append([r["path"] for r in re])
+ else:
+ res.append(re["path"])
+
+ assert res == [
+ "file1",
+ ["file2", "file3", "file4"],
+ ["file5", "file6"],
+ "file7",
+ ]
+
+
+cpu = huggingface_hub.SpaceHardware.CPU_BASIC
+
+
+class TestDuplication:
+ @pytest.mark.flaky
+ @patch("huggingface_hub.get_space_runtime", return_value=MagicMock(hardware=cpu))
+ @patch("gradio_client.client.Client.__init__", return_value=None)
+ def test_new_space_id(self, mock_init, mock_runtime):
+ Client.duplicate(
+ "gradio/calculator",
+ "test",
+ hf_token=HF_TOKEN,
+ )
+ mock_runtime.assert_any_call("gradio/calculator", token=HF_TOKEN)
+ mock_init.assert_called()
+ Client.duplicate(
+ "gradio/calculator",
+ "gradio-tests/test",
+ hf_token=HF_TOKEN,
+ )
+ mock_runtime.assert_any_call("gradio/calculator", token=HF_TOKEN)
+ mock_init.assert_called()
+
+ @pytest.mark.flaky
+ @patch("gradio_client.utils.set_space_timeout")
+ @patch("huggingface_hub.get_space_runtime", return_value=MagicMock(hardware=cpu))
+ @patch("gradio_client.client.Client.__init__", return_value=None)
+ def test_dont_set_timeout_if_default_hardware(
+ self, mock_init, mock_runtime, mock_set_timeout
+ ):
+ Client.duplicate(
+ "gradio/calculator",
+ "test",
+ )
+ mock_set_timeout.assert_not_called()
+
+ @pytest.mark.flaky
+ @patch("huggingface_hub.request_space_hardware")
+ @patch("gradio_client.utils.set_space_timeout")
+ @patch(
+ "huggingface_hub.get_space_runtime",
+ return_value=MagicMock(hardware=huggingface_hub.SpaceHardware.CPU_UPGRADE),
+ )
+ @patch("gradio_client.client.Client.__init__", return_value=None)
+ def test_set_timeout_if_not_default_hardware(
+ self, mock_init, mock_runtime, mock_set_timeout, mock_request_hardware
+ ):
+ Client.duplicate(
+ "gradio/calculator",
+ "test",
+ hardware="cpu-upgrade",
+ sleep_timeout=15,
+ hf_token=HF_TOKEN,
+ )
+ assert mock_set_timeout.call_count == 1
+ _, called_kwargs = mock_set_timeout.call_args
+ assert called_kwargs["timeout_in_seconds"] == 15 * 60
+
+ @pytest.mark.flaky
+ @patch("huggingface_hub.add_space_secret")
+ @patch("huggingface_hub.duplicate_space")
+ @patch("gradio_client.client.Client.__init__", return_value=None)
+ @patch("gradio_client.utils.set_space_timeout")
+ def test_add_secrets(self, mock_time, mock_init, mock_duplicate, mock_add_secret):
+ with pytest.raises(RepositoryNotFoundError):
+ name = str(uuid.uuid4())
+ Client.duplicate(
+ "gradio/calculator",
+ name,
+ hf_token=HF_TOKEN,
+ secrets={"test_key": "test_value", "test_key2": "test_value2"},
+ )
+ mock_add_secret.assert_called_with(
+ f"gradio-tests/{name}",
+ "test_key",
+ "test_value",
+ token=HF_TOKEN,
+ )
+ mock_add_secret.assert_any_call(
+ f"gradio-tests/{name}",
+ "test_key2",
+ "test_value2",
+ token=HF_TOKEN,
+ )
diff --git a/client/python/test/test_documentation.py b/client/python/test/test_documentation.py
new file mode 100644
index 0000000000000000000000000000000000000000..d73a9e159b5b9904c38cafa5311fbf8fff3de395
--- /dev/null
+++ b/client/python/test/test_documentation.py
@@ -0,0 +1,7 @@
+from gradio_client import documentation
+
+
+class TestDocumentation:
+ def test_website_documentation(self):
+ docs = documentation.generate_documentation()
+ assert len(docs) > 0
diff --git a/client/python/test/test_utils.py b/client/python/test/test_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb5dc571edd9da71af7b4ba63922e49fdf85158a
--- /dev/null
+++ b/client/python/test/test_utils.py
@@ -0,0 +1,187 @@
+import importlib.resources
+import json
+import os
+import tempfile
+from copy import deepcopy
+from pathlib import Path
+from unittest.mock import MagicMock, patch
+
+import httpx
+import pytest
+from huggingface_hub import HfFolder
+
+from gradio_client import media_data, utils
+
+types = json.loads(importlib.resources.read_text("gradio_client", "types.json"))
+types["MultipleFile"] = {
+ "type": "array",
+ "items": {"type": "string", "description": "filepath or URL to file"},
+}
+types["SingleFile"] = {"type": "string", "description": "filepath or URL to file"}
+
+
+HF_TOKEN = os.getenv("HF_TOKEN") or HfFolder.get_token()
+
+
+def test_encode_url_or_file_to_base64():
+ output_base64 = utils.encode_url_or_file_to_base64(
+ Path(__file__).parent / "../../../gradio/test_data/test_image.png"
+ )
+ assert output_base64 == deepcopy(media_data.BASE64_IMAGE)
+
+
+def test_encode_file_to_base64():
+ output_base64 = utils.encode_file_to_base64(
+ Path(__file__).parent / "../../../gradio/test_data/test_image.png"
+ )
+ assert output_base64 == deepcopy(media_data.BASE64_IMAGE)
+
+
+@pytest.mark.flaky
+def test_encode_url_to_base64():
+ output_base64 = utils.encode_url_to_base64(
+ "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/test_data/test_image.png"
+ )
+ assert output_base64 == deepcopy(media_data.BASE64_IMAGE)
+
+
+def test_encode_url_to_base64_doesnt_encode_errors(monkeypatch):
+ request = httpx.Request("GET", "https://example.com/foo")
+ error_response = httpx.Response(status_code=404, request=request)
+ monkeypatch.setattr(httpx, "get", lambda *args, **kwargs: error_response)
+ with pytest.raises(httpx.HTTPStatusError):
+ utils.encode_url_to_base64("https://example.com/foo")
+
+
+def test_decode_base64_to_binary():
+ binary = utils.decode_base64_to_binary(deepcopy(media_data.BASE64_IMAGE))
+ assert deepcopy(media_data.BINARY_IMAGE) == binary
+
+ b64_img_without_header = deepcopy(media_data.BASE64_IMAGE).split(",")[1]
+ binary_without_header, extension = utils.decode_base64_to_binary(
+ b64_img_without_header
+ )
+
+ assert binary[0] == binary_without_header
+ assert extension is None
+
+
+def test_decode_base64_to_file():
+ temp_file = utils.decode_base64_to_file(deepcopy(media_data.BASE64_IMAGE))
+ assert isinstance(temp_file, tempfile._TemporaryFileWrapper)
+
+
+@pytest.mark.flaky
+def test_download_private_file(gradio_temp_dir):
+ url_path = (
+ "https://gradio-tests-not-actually-private-spacev4-sse.hf.space/file=lion.jpg"
+ )
+ file = utils.download_file(
+ url_path=url_path, hf_token=HF_TOKEN, dir=str(gradio_temp_dir)
+ )
+ assert Path(file).name.endswith(".jpg")
+
+
+def test_download_tmp_copy_of_file_does_not_save_errors(monkeypatch, gradio_temp_dir):
+ error_response = httpx.Response(status_code=404)
+ monkeypatch.setattr(httpx, "get", lambda *args, **kwargs: error_response)
+ with pytest.raises(httpx.HTTPStatusError):
+ utils.download_file("https://example.com/foo", dir=str(gradio_temp_dir))
+
+
+@pytest.mark.parametrize(
+ "orig_filename, new_filename",
+ [
+ ("abc", "abc"),
+ ("$$AAabc&3", "AAabc3"),
+ ("$$AAabc&3", "AAabc3"),
+ ("$$AAa..b-c&3_", "AAa..b-c3_"),
+ ("$$AAa..b-c&3_", "AAa..b-c3_"),
+ (
+ "ゆかりです。私、こんなかわいい服は初めて着ました…。なんだかうれしくって、楽しいです。歌いたくなる気分って、初めてです。これがアイドルってことなのかもしれませんね",
+ "ゆかりです私こんなかわいい服は初めて着ましたなんだかうれしくって楽しいです歌いたくなる気分って初めてですこれがアイドルってことなの",
+ ),
+ ],
+)
+def test_strip_invalid_filename_characters(orig_filename, new_filename):
+ assert utils.strip_invalid_filename_characters(orig_filename) == new_filename
+
+
+class AsyncMock(MagicMock):
+ async def __call__(self, *args, **kwargs):
+ return super().__call__(*args, **kwargs)
+
+
+@pytest.mark.asyncio
+async def test_get_pred_from_ws():
+ mock_ws = AsyncMock(name="ws")
+ messages = [
+ json.dumps({"msg": "estimation"}),
+ json.dumps({"msg": "send_data"}),
+ json.dumps({"msg": "process_generating"}),
+ json.dumps({"msg": "process_completed", "output": {"data": ["result!"]}}),
+ ]
+ mock_ws.recv.side_effect = messages
+ data = {"data": ["foo"], "fn_index": "foo"}
+ hash_data = {"session_hash": "daslskdf", "fn_index": "foo"}
+ output = await utils.get_pred_from_ws(mock_ws, data, hash_data) # type: ignore
+ assert output == {"data": ["result!"]}
+ mock_ws.send.assert_called_once_with(data)
+
+
+@pytest.mark.asyncio
+async def test_get_pred_from_ws_raises_if_queue_full():
+ mock_ws = AsyncMock(name="ws")
+ messages = [json.dumps({"msg": "queue_full"})]
+ mock_ws.recv.side_effect = messages
+ data = json.dumps({"data": ["foo"], "fn_index": "foo"})
+ hash_data = json.dumps({"session_hash": "daslskdf", "fn_index": "foo"})
+ with pytest.raises(utils.QueueError, match="Queue is full!"):
+ await utils.get_pred_from_ws(mock_ws, data, hash_data)
+
+
+@patch("httpx.post")
+def test_sleep_successful(mock_post):
+ utils.set_space_timeout("gradio/calculator")
+
+
+@patch(
+ "httpx.post",
+ side_effect=httpx.HTTPStatusError("error", request=None, response=None),
+)
+def test_sleep_unsuccessful(mock_post):
+ with pytest.raises(utils.SpaceDuplicationError):
+ utils.set_space_timeout("gradio/calculator")
+
+
+@pytest.mark.parametrize("schema", types)
+def test_json_schema_to_python_type(schema):
+ if schema == "SimpleSerializable":
+ answer = "Any"
+ elif schema == "StringSerializable":
+ answer = "str"
+ elif schema == "ListStringSerializable":
+ answer = "List[str]"
+ elif schema == "BooleanSerializable":
+ answer = "bool"
+ elif schema == "NumberSerializable":
+ answer = "float"
+ elif schema == "ImgSerializable":
+ answer = "str"
+ elif schema == "FileSerializable":
+ answer = "str | Dict(name: str (name of file), data: str (base64 representation of file), size: int (size of image in bytes), is_file: bool (true if the file has been uploaded to the server), orig_name: str (original name of the file)) | List[str | Dict(name: str (name of file), data: str (base64 representation of file), size: int (size of image in bytes), is_file: bool (true if the file has been uploaded to the server), orig_name: str (original name of the file))]"
+ elif schema == "JSONSerializable":
+ answer = "Dict[Any, Any]"
+ elif schema == "GallerySerializable":
+ answer = "Tuple[Dict(name: str (name of file), data: str (base64 representation of file), size: int (size of image in bytes), is_file: bool (true if the file has been uploaded to the server), orig_name: str (original name of the file)), str | None]"
+ elif schema == "SingleFileSerializable":
+ answer = "str | Dict(name: str (name of file), data: str (base64 representation of file), size: int (size of image in bytes), is_file: bool (true if the file has been uploaded to the server), orig_name: str (original name of the file))"
+ elif schema == "MultipleFileSerializable":
+ answer = "List[str | Dict(name: str (name of file), data: str (base64 representation of file), size: int (size of image in bytes), is_file: bool (true if the file has been uploaded to the server), orig_name: str (original name of the file))]"
+ elif schema == "SingleFile":
+ answer = "str"
+ elif schema == "MultipleFile":
+ answer = "List[str]"
+ else:
+ raise ValueError(f"This test has not been modified to check {schema}")
+ assert utils.json_schema_to_python_type(types[schema]) == answer
diff --git a/demo/Echocardiogram-Segmentation/img1.jpg b/demo/Echocardiogram-Segmentation/img1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..8fdf728a65f5030a74776153accde31f2a36c0ee
Binary files /dev/null and b/demo/Echocardiogram-Segmentation/img1.jpg differ
diff --git a/demo/Echocardiogram-Segmentation/img2.jpg b/demo/Echocardiogram-Segmentation/img2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2263ca3cce6510ac79889661a2d4a54d2634ba92
Binary files /dev/null and b/demo/Echocardiogram-Segmentation/img2.jpg differ
diff --git a/demo/Echocardiogram-Segmentation/requirements.txt b/demo/Echocardiogram-Segmentation/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ae852b6404065a30cc941951a41ce8c76a0f48ae
--- /dev/null
+++ b/demo/Echocardiogram-Segmentation/requirements.txt
@@ -0,0 +1,7 @@
+-f https://download.pytorch.org/whl/torch_stable.html
+numpy
+matplotlib
+wget
+torch
+torchvision
+
diff --git a/demo/Echocardiogram-Segmentation/run.ipynb b/demo/Echocardiogram-Segmentation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..28e63da38c0ad10891dfff9fa46aaf0149bca3a0
--- /dev/null
+++ b/demo/Echocardiogram-Segmentation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: Echocardiogram-Segmentation"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio -f https://download.pytorch.org/whl/torch_stable.html numpy matplotlib wget torch torchvision "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/Echocardiogram-Segmentation/img1.jpg\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/Echocardiogram-Segmentation/img2.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "import numpy as np\n", "import torch\n", "import torchvision\n", "import wget \n", "\n", "\n", "destination_folder = \"output\"\n", "destination_for_weights = \"weights\"\n", "\n", "if os.path.exists(destination_for_weights):\n", " print(\"The weights are at\", destination_for_weights)\n", "else:\n", " print(\"Creating folder at \", destination_for_weights, \" to store weights\")\n", " os.mkdir(destination_for_weights)\n", " \n", "segmentationWeightsURL = 'https://github.com/douyang/EchoNetDynamic/releases/download/v1.0.0/deeplabv3_resnet50_random.pt'\n", "\n", "if not os.path.exists(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL))):\n", " print(\"Downloading Segmentation Weights, \", segmentationWeightsURL,\" to \",os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)))\n", " filename = wget.download(segmentationWeightsURL, out = destination_for_weights)\n", "else:\n", " print(\"Segmentation Weights already present\")\n", "\n", "torch.cuda.empty_cache()\n", "\n", "def collate_fn(x):\n", " x, f = zip(*x)\n", " i = list(map(lambda t: t.shape[1], x))\n", " x = torch.as_tensor(np.swapaxes(np.concatenate(x, 1), 0, 1))\n", " return x, f, i\n", "\n", "model = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=False, aux_loss=False)\n", "model.classifier[-1] = torch.nn.Conv2d(model.classifier[-1].in_channels, 1, kernel_size=model.classifier[-1].kernel_size)\n", "\n", "print(\"loading weights from \", os.path.join(destination_for_weights, \"deeplabv3_resnet50_random\"))\n", "\n", "if torch.cuda.is_available():\n", " print(\"cuda is available, original weights\")\n", " device = torch.device(\"cuda\")\n", " model = torch.nn.DataParallel(model)\n", " model.to(device)\n", " checkpoint = torch.load(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)))\n", " model.load_state_dict(checkpoint['state_dict'])\n", "else:\n", " print(\"cuda is not available, cpu weights\")\n", " device = torch.device(\"cpu\")\n", " checkpoint = torch.load(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)), map_location = \"cpu\")\n", " state_dict_cpu = {k[7:]: v for (k, v) in checkpoint['state_dict'].items()}\n", " model.load_state_dict(state_dict_cpu)\n", "\n", "model.eval()\n", "\n", "def segment(input):\n", " inp = input\n", " x = inp.transpose([2, 0, 1]) # channels-first\n", " x = np.expand_dims(x, axis=0) # adding a batch dimension \n", " \n", " mean = x.mean(axis=(0, 2, 3))\n", " std = x.std(axis=(0, 2, 3))\n", " x = x - mean.reshape(1, 3, 1, 1)\n", " x = x / std.reshape(1, 3, 1, 1)\n", " \n", " with torch.no_grad():\n", " x = torch.from_numpy(x).type('torch.FloatTensor').to(device)\n", " output = model(x) \n", " \n", " y = output['out'].numpy()\n", " y = y.squeeze()\n", " \n", " out = y>0 \n", " \n", " mask = inp.copy()\n", " mask[out] = np.array([0, 0, 255])\n", " \n", " return mask\n", "\n", "import gradio as gr\n", "\n", "i = gr.Image(label=\"Echocardiogram\")\n", "o = gr.Image(label=\"Segmentation Mask\")\n", "\n", "examples = [[\"img1.jpg\"], [\"img2.jpg\"]]\n", "title = None #\"Left Ventricle Segmentation\"\n", "description = \"This semantic segmentation model identifies the left ventricle in echocardiogram images.\"\n", "# videos. Accurate evaluation of the motion and size of the left ventricle is crucial for the assessment of cardiac function and ejection fraction. In this interface, the user inputs apical-4-chamber images from echocardiography videos and the model will output a prediction of the localization of the left ventricle in blue. This model was trained on the publicly released EchoNet-Dynamic dataset of 10k echocardiogram videos with 20k expert annotations of the left ventricle and published as part of \u2018Video-based AI for beat-to-beat assessment of cardiac function\u2019 by Ouyang et al. in Nature, 2020.\"\n", "thumbnail = \"https://raw.githubusercontent.com/gradio-app/hub-echonet/master/thumbnail.png\"\n", "gr.Interface(segment, i, o, examples=examples, analytics_enabled=False, thumbnail=thumbnail, cache_examples=False).launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/Echocardiogram-Segmentation/run.py b/demo/Echocardiogram-Segmentation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..95c09932a739cb4fead26ae7fa7e2e58a79bdae7
--- /dev/null
+++ b/demo/Echocardiogram-Segmentation/run.py
@@ -0,0 +1,88 @@
+import os
+import numpy as np
+import torch
+import torchvision
+import wget
+
+
+destination_folder = "output"
+destination_for_weights = "weights"
+
+if os.path.exists(destination_for_weights):
+ print("The weights are at", destination_for_weights)
+else:
+ print("Creating folder at ", destination_for_weights, " to store weights")
+ os.mkdir(destination_for_weights)
+
+segmentationWeightsURL = 'https://github.com/douyang/EchoNetDynamic/releases/download/v1.0.0/deeplabv3_resnet50_random.pt'
+
+if not os.path.exists(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL))):
+ print("Downloading Segmentation Weights, ", segmentationWeightsURL," to ",os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)))
+ filename = wget.download(segmentationWeightsURL, out = destination_for_weights)
+else:
+ print("Segmentation Weights already present")
+
+torch.cuda.empty_cache()
+
+def collate_fn(x):
+ x, f = zip(*x)
+ i = list(map(lambda t: t.shape[1], x))
+ x = torch.as_tensor(np.swapaxes(np.concatenate(x, 1), 0, 1))
+ return x, f, i
+
+model = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=False, aux_loss=False)
+model.classifier[-1] = torch.nn.Conv2d(model.classifier[-1].in_channels, 1, kernel_size=model.classifier[-1].kernel_size)
+
+print("loading weights from ", os.path.join(destination_for_weights, "deeplabv3_resnet50_random"))
+
+if torch.cuda.is_available():
+ print("cuda is available, original weights")
+ device = torch.device("cuda")
+ model = torch.nn.DataParallel(model)
+ model.to(device)
+ checkpoint = torch.load(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)))
+ model.load_state_dict(checkpoint['state_dict'])
+else:
+ print("cuda is not available, cpu weights")
+ device = torch.device("cpu")
+ checkpoint = torch.load(os.path.join(destination_for_weights, os.path.basename(segmentationWeightsURL)), map_location = "cpu")
+ state_dict_cpu = {k[7:]: v for (k, v) in checkpoint['state_dict'].items()}
+ model.load_state_dict(state_dict_cpu)
+
+model.eval()
+
+def segment(input):
+ inp = input
+ x = inp.transpose([2, 0, 1]) # channels-first
+ x = np.expand_dims(x, axis=0) # adding a batch dimension
+
+ mean = x.mean(axis=(0, 2, 3))
+ std = x.std(axis=(0, 2, 3))
+ x = x - mean.reshape(1, 3, 1, 1)
+ x = x / std.reshape(1, 3, 1, 1)
+
+ with torch.no_grad():
+ x = torch.from_numpy(x).type('torch.FloatTensor').to(device)
+ output = model(x)
+
+ y = output['out'].numpy()
+ y = y.squeeze()
+
+ out = y>0
+
+ mask = inp.copy()
+ mask[out] = np.array([0, 0, 255])
+
+ return mask
+
+import gradio as gr
+
+i = gr.Image(label="Echocardiogram")
+o = gr.Image(label="Segmentation Mask")
+
+examples = [["img1.jpg"], ["img2.jpg"]]
+title = None #"Left Ventricle Segmentation"
+description = "This semantic segmentation model identifies the left ventricle in echocardiogram images."
+# videos. Accurate evaluation of the motion and size of the left ventricle is crucial for the assessment of cardiac function and ejection fraction. In this interface, the user inputs apical-4-chamber images from echocardiography videos and the model will output a prediction of the localization of the left ventricle in blue. This model was trained on the publicly released EchoNet-Dynamic dataset of 10k echocardiogram videos with 20k expert annotations of the left ventricle and published as part of ‘Video-based AI for beat-to-beat assessment of cardiac function’ by Ouyang et al. in Nature, 2020."
+thumbnail = "https://raw.githubusercontent.com/gradio-app/hub-echonet/master/thumbnail.png"
+gr.Interface(segment, i, o, examples=examples, analytics_enabled=False, thumbnail=thumbnail, cache_examples=False).launch()
diff --git a/demo/__init__.py b/demo/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/all_demos/image.png b/demo/all_demos/image.png
new file mode 100644
index 0000000000000000000000000000000000000000..dc392ea95476974e07a68ad98a9659c240e1089b
Binary files /dev/null and b/demo/all_demos/image.png differ
diff --git a/demo/all_demos/run.py b/demo/all_demos/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..71d69cc4d6c0bd2fba6f0f004a7a4a9ad8af636c
--- /dev/null
+++ b/demo/all_demos/run.py
@@ -0,0 +1,52 @@
+import importlib
+import gradio as gr
+import os
+import sys
+import copy
+import pathlib
+from fastapi import FastAPI, Request
+from fastapi.templating import Jinja2Templates
+import uvicorn
+from gradio.utils import get_space
+
+os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
+
+demo_dir = pathlib.Path(__file__).parent / "demos"
+
+
+app = FastAPI()
+
+templates = Jinja2Templates(directory="templates")
+
+names = sorted(os.listdir("./demos"))
+
+
+@app.get("/")
+def index(request: Request):
+ names = [[p[0], p[2]] for p in all_demos]
+ return templates.TemplateResponse("index.html", {"request": request, "names": names,
+ "initial_demo": names[0][0], "is_space": get_space()})
+
+
+all_demos = []
+demo_module = None
+for p in sorted(os.listdir("./demos")):
+ old_path = copy.deepcopy(sys.path)
+ sys.path = [os.path.join(demo_dir, p)] + sys.path
+ try: # Some demos may not be runnable because of 429 timeouts, etc.
+ if demo_module is None:
+ demo_module = importlib.import_module(f"run")
+ else:
+ demo_module = importlib.reload(demo_module)
+ all_demos.append((p, demo_module.demo.queue(), False))
+ except Exception as e:
+ with gr.Blocks() as demo:
+ gr.Markdown(f"Error loading demo: {e}")
+ all_demos.append((p, demo, True))
+
+for demo_name, demo, _ in all_demos:
+ app = gr.mount_gradio_app(app, demo, f"/demo/{demo_name}")
+
+
+if __name__ == "__main__":
+ uvicorn.run(app, port=7860, host="0.0.0.0")
diff --git a/demo/all_demos/templates/index.html b/demo/all_demos/templates/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..3eef8da37e6796a02af89cf666bbbe0b733a6079
--- /dev/null
+++ b/demo/all_demos/templates/index.html
@@ -0,0 +1,118 @@
+
+
+
+ {%if is_space %}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/altair_plot/requirements.txt b/demo/altair_plot/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5a45a80196201251d44186498ef2501d6095ca50
--- /dev/null
+++ b/demo/altair_plot/requirements.txt
@@ -0,0 +1,2 @@
+altair
+vega_datasets
\ No newline at end of file
diff --git a/demo/altair_plot/run.ipynb b/demo/altair_plot/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..de688ebe7c92c91f9d658278057bacd70ac3e07e
--- /dev/null
+++ b/demo/altair_plot/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: altair_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio altair vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import altair as alt\n", "import gradio as gr\n", "import numpy as np\n", "import pandas as pd\n", "from vega_datasets import data\n", "\n", "\n", "def make_plot(plot_type):\n", " if plot_type == \"scatter_plot\":\n", " cars = data.cars()\n", " return alt.Chart(cars).mark_point().encode(\n", " x='Horsepower',\n", " y='Miles_per_Gallon',\n", " color='Origin',\n", " )\n", " elif plot_type == \"heatmap\":\n", " # Compute x^2 + y^2 across a 2D grid\n", " x, y = np.meshgrid(range(-5, 5), range(-5, 5))\n", " z = x ** 2 + y ** 2\n", "\n", " # Convert this grid to columnar data expected by Altair\n", " source = pd.DataFrame({'x': x.ravel(),\n", " 'y': y.ravel(),\n", " 'z': z.ravel()})\n", " return alt.Chart(source).mark_rect().encode(\n", " x='x:O',\n", " y='y:O',\n", " color='z:Q'\n", " )\n", " elif plot_type == \"us_map\":\n", " states = alt.topo_feature(data.us_10m.url, 'states')\n", " source = data.income.url\n", "\n", " return alt.Chart(source).mark_geoshape().encode(\n", " shape='geo:G',\n", " color='pct:Q',\n", " tooltip=['name:N', 'pct:Q'],\n", " facet=alt.Facet('group:N', columns=2),\n", " ).transform_lookup(\n", " lookup='id',\n", " from_=alt.LookupData(data=states, key='id'),\n", " as_='geo'\n", " ).properties(\n", " width=300,\n", " height=175,\n", " ).project(\n", " type='albersUsa'\n", " )\n", " elif plot_type == \"interactive_barplot\":\n", " source = data.movies.url\n", "\n", " pts = alt.selection(type=\"single\", encodings=['x'])\n", "\n", " rect = alt.Chart(data.movies.url).mark_rect().encode(\n", " alt.X('IMDB_Rating:Q', bin=True),\n", " alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),\n", " alt.Color('count()',\n", " scale=alt.Scale(scheme='greenblue'),\n", " legend=alt.Legend(title='Total Records')\n", " )\n", " )\n", "\n", " circ = rect.mark_point().encode(\n", " alt.ColorValue('grey'),\n", " alt.Size('count()',\n", " legend=alt.Legend(title='Records in Selection')\n", " )\n", " ).transform_filter(\n", " pts\n", " )\n", "\n", " bar = alt.Chart(source).mark_bar().encode(\n", " x='Major_Genre:N',\n", " y='count()',\n", " color=alt.condition(pts, alt.ColorValue(\"steelblue\"), alt.ColorValue(\"grey\"))\n", " ).properties(\n", " width=550,\n", " height=200\n", " ).add_selection(pts)\n", "\n", " plot = alt.vconcat(\n", " rect + circ,\n", " bar\n", " ).resolve_legend(\n", " color=\"independent\",\n", " size=\"independent\"\n", " )\n", " return plot\n", " elif plot_type == \"radial\":\n", " source = pd.DataFrame({\"values\": [12, 23, 47, 6, 52, 19]})\n", "\n", " base = alt.Chart(source).encode(\n", " theta=alt.Theta(\"values:Q\", stack=True),\n", " radius=alt.Radius(\"values\", scale=alt.Scale(type=\"sqrt\", zero=True, rangeMin=20)),\n", " color=\"values:N\",\n", " )\n", "\n", " c1 = base.mark_arc(innerRadius=20, stroke=\"#fff\")\n", "\n", " c2 = base.mark_text(radiusOffset=10).encode(text=\"values:Q\")\n", "\n", " return c1 + c2\n", " elif plot_type == \"multiline\":\n", " source = data.stocks()\n", "\n", " highlight = alt.selection(type='single', on='mouseover',\n", " fields=['symbol'], nearest=True)\n", "\n", " base = alt.Chart(source).encode(\n", " x='date:T',\n", " y='price:Q',\n", " color='symbol:N'\n", " )\n", "\n", " points = base.mark_circle().encode(\n", " opacity=alt.value(0)\n", " ).add_selection(\n", " highlight\n", " ).properties(\n", " width=600\n", " )\n", "\n", " lines = base.mark_line().encode(\n", " size=alt.condition(~highlight, alt.value(1), alt.value(3))\n", " )\n", "\n", " return points + lines\n", "\n", "\n", "with gr.Blocks() as demo:\n", " button = gr.Radio(label=\"Plot type\",\n", " choices=['scatter_plot', 'heatmap', 'us_map',\n", " 'interactive_barplot', \"radial\", \"multiline\"], value='scatter_plot')\n", " plot = gr.Plot(label=\"Plot\")\n", " button.change(make_plot, inputs=button, outputs=[plot])\n", " demo.load(make_plot, inputs=[button], outputs=[plot])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/altair_plot/run.py b/demo/altair_plot/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2fd137fae7f6184d2cee3ee96b61464cc0c5c5c3
--- /dev/null
+++ b/demo/altair_plot/run.py
@@ -0,0 +1,140 @@
+import altair as alt
+import gradio as gr
+import numpy as np
+import pandas as pd
+from vega_datasets import data
+
+
+def make_plot(plot_type):
+ if plot_type == "scatter_plot":
+ cars = data.cars()
+ return alt.Chart(cars).mark_point().encode(
+ x='Horsepower',
+ y='Miles_per_Gallon',
+ color='Origin',
+ )
+ elif plot_type == "heatmap":
+ # Compute x^2 + y^2 across a 2D grid
+ x, y = np.meshgrid(range(-5, 5), range(-5, 5))
+ z = x ** 2 + y ** 2
+
+ # Convert this grid to columnar data expected by Altair
+ source = pd.DataFrame({'x': x.ravel(),
+ 'y': y.ravel(),
+ 'z': z.ravel()})
+ return alt.Chart(source).mark_rect().encode(
+ x='x:O',
+ y='y:O',
+ color='z:Q'
+ )
+ elif plot_type == "us_map":
+ states = alt.topo_feature(data.us_10m.url, 'states')
+ source = data.income.url
+
+ return alt.Chart(source).mark_geoshape().encode(
+ shape='geo:G',
+ color='pct:Q',
+ tooltip=['name:N', 'pct:Q'],
+ facet=alt.Facet('group:N', columns=2),
+ ).transform_lookup(
+ lookup='id',
+ from_=alt.LookupData(data=states, key='id'),
+ as_='geo'
+ ).properties(
+ width=300,
+ height=175,
+ ).project(
+ type='albersUsa'
+ )
+ elif plot_type == "interactive_barplot":
+ source = data.movies.url
+
+ pts = alt.selection(type="single", encodings=['x'])
+
+ rect = alt.Chart(data.movies.url).mark_rect().encode(
+ alt.X('IMDB_Rating:Q', bin=True),
+ alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
+ alt.Color('count()',
+ scale=alt.Scale(scheme='greenblue'),
+ legend=alt.Legend(title='Total Records')
+ )
+ )
+
+ circ = rect.mark_point().encode(
+ alt.ColorValue('grey'),
+ alt.Size('count()',
+ legend=alt.Legend(title='Records in Selection')
+ )
+ ).transform_filter(
+ pts
+ )
+
+ bar = alt.Chart(source).mark_bar().encode(
+ x='Major_Genre:N',
+ y='count()',
+ color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
+ ).properties(
+ width=550,
+ height=200
+ ).add_selection(pts)
+
+ plot = alt.vconcat(
+ rect + circ,
+ bar
+ ).resolve_legend(
+ color="independent",
+ size="independent"
+ )
+ return plot
+ elif plot_type == "radial":
+ source = pd.DataFrame({"values": [12, 23, 47, 6, 52, 19]})
+
+ base = alt.Chart(source).encode(
+ theta=alt.Theta("values:Q", stack=True),
+ radius=alt.Radius("values", scale=alt.Scale(type="sqrt", zero=True, rangeMin=20)),
+ color="values:N",
+ )
+
+ c1 = base.mark_arc(innerRadius=20, stroke="#fff")
+
+ c2 = base.mark_text(radiusOffset=10).encode(text="values:Q")
+
+ return c1 + c2
+ elif plot_type == "multiline":
+ source = data.stocks()
+
+ highlight = alt.selection(type='single', on='mouseover',
+ fields=['symbol'], nearest=True)
+
+ base = alt.Chart(source).encode(
+ x='date:T',
+ y='price:Q',
+ color='symbol:N'
+ )
+
+ points = base.mark_circle().encode(
+ opacity=alt.value(0)
+ ).add_selection(
+ highlight
+ ).properties(
+ width=600
+ )
+
+ lines = base.mark_line().encode(
+ size=alt.condition(~highlight, alt.value(1), alt.value(3))
+ )
+
+ return points + lines
+
+
+with gr.Blocks() as demo:
+ button = gr.Radio(label="Plot type",
+ choices=['scatter_plot', 'heatmap', 'us_map',
+ 'interactive_barplot', "radial", "multiline"], value='scatter_plot')
+ plot = gr.Plot(label="Plot")
+ button.change(make_plot, inputs=button, outputs=[plot])
+ demo.load(make_plot, inputs=[button], outputs=[plot])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/animeganv2/DESCRIPTION.md b/demo/animeganv2/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..e66cbc0582bd61f2bd0bef76e81fd060c2f9526c
--- /dev/null
+++ b/demo/animeganv2/DESCRIPTION.md
@@ -0,0 +1 @@
+Recreate the viral AnimeGAN image transformation demo.
\ No newline at end of file
diff --git a/demo/animeganv2/gongyoo.jpeg b/demo/animeganv2/gongyoo.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..8f09a41c7eae00139104a2d6a953f8538d0b9126
Binary files /dev/null and b/demo/animeganv2/gongyoo.jpeg differ
diff --git a/demo/animeganv2/groot.jpeg b/demo/animeganv2/groot.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..06b192f77a9ff76d2f0b1dbf89f56702c8485d8c
Binary files /dev/null and b/demo/animeganv2/groot.jpeg differ
diff --git a/demo/animeganv2/requirements.txt b/demo/animeganv2/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..45d786f179e027992d1e8434e56db9a99f5bfe2f
--- /dev/null
+++ b/demo/animeganv2/requirements.txt
@@ -0,0 +1,9 @@
+torch
+torchvision
+Pillow
+gdown
+numpy
+scipy
+cmake
+onnxruntime-gpu
+opencv-python-headless
\ No newline at end of file
diff --git a/demo/animeganv2/run.ipynb b/demo/animeganv2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d16af5addf9b84827547ecb74fd318f0d09015d9
--- /dev/null
+++ b/demo/animeganv2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: animeganv2\n", "### Recreate the viral AnimeGAN image transformation demo.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch torchvision Pillow gdown numpy scipy cmake onnxruntime-gpu opencv-python-headless"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/animeganv2/gongyoo.jpeg\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/animeganv2/groot.jpeg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "\n", "model2 = torch.hub.load(\n", " \"AK391/animegan2-pytorch:main\",\n", " \"generator\",\n", " pretrained=True,\n", " progress=False\n", ")\n", "model1 = torch.hub.load(\"AK391/animegan2-pytorch:main\", \"generator\", pretrained=\"face_paint_512_v1\")\n", "face2paint = torch.hub.load(\n", " 'AK391/animegan2-pytorch:main', 'face2paint', \n", " size=512,side_by_side=False\n", ")\n", "\n", "def inference(img, ver):\n", " if ver == 'version 2 (\ud83d\udd3a robustness,\ud83d\udd3b stylization)':\n", " out = face2paint(model2, img)\n", " else:\n", " out = face2paint(model1, img)\n", " return out\n", "\n", "title = \"AnimeGANv2\"\n", "description = \"Gradio Demo for AnimeGanv2 Face Portrait. To use it, simply upload your image, or click one of the examples to load them. Read more at the links below. Please use a cropped portrait picture for best results similar to the examples below.\"\n", "article = \"Github Repo Pytorch
\"\n", "examples=[['groot.jpeg','version 2 (\ud83d\udd3a robustness,\ud83d\udd3b stylization)'],['gongyoo.jpeg','version 1 (\ud83d\udd3a stylization, \ud83d\udd3b robustness)']]\n", "\n", "demo = gr.Interface(\n", " fn=inference, \n", " inputs=[gr.Image(type=\"pil\"),gr.Radio(['version 1 (\ud83d\udd3a stylization, \ud83d\udd3b robustness)','version 2 (\ud83d\udd3a robustness,\ud83d\udd3b stylization)'], type=\"value\", value='version 2 (\ud83d\udd3a robustness,\ud83d\udd3b stylization)', label='version')], \n", " outputs=gr.Image(type=\"pil\"),\n", " title=title,\n", " description=description,\n", " article=article,\n", " examples=examples)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/animeganv2/run.py b/demo/animeganv2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d8de0171ebe9b1c0fc7b28d8f6ba0c4d39549ff
--- /dev/null
+++ b/demo/animeganv2/run.py
@@ -0,0 +1,37 @@
+import gradio as gr
+import torch
+
+model2 = torch.hub.load(
+ "AK391/animegan2-pytorch:main",
+ "generator",
+ pretrained=True,
+ progress=False
+)
+model1 = torch.hub.load("AK391/animegan2-pytorch:main", "generator", pretrained="face_paint_512_v1")
+face2paint = torch.hub.load(
+ 'AK391/animegan2-pytorch:main', 'face2paint',
+ size=512,side_by_side=False
+)
+
+def inference(img, ver):
+ if ver == 'version 2 (🔺 robustness,🔻 stylization)':
+ out = face2paint(model2, img)
+ else:
+ out = face2paint(model1, img)
+ return out
+
+title = "AnimeGANv2"
+description = "Gradio Demo for AnimeGanv2 Face Portrait. To use it, simply upload your image, or click one of the examples to load them. Read more at the links below. Please use a cropped portrait picture for best results similar to the examples below."
+article = "Github Repo Pytorch
"
+examples=[['groot.jpeg','version 2 (🔺 robustness,🔻 stylization)'],['gongyoo.jpeg','version 1 (🔺 stylization, 🔻 robustness)']]
+
+demo = gr.Interface(
+ fn=inference,
+ inputs=[gr.Image(type="pil"),gr.Radio(['version 1 (🔺 stylization, 🔻 robustness)','version 2 (🔺 robustness,🔻 stylization)'], type="value", value='version 2 (🔺 robustness,🔻 stylization)', label='version')],
+ outputs=gr.Image(type="pil"),
+ title=title,
+ description=description,
+ article=article,
+ examples=examples)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/annotatedimage_component/run.ipynb b/demo/annotatedimage_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d470bc595c616f6866e0b886d2ee6b9779238b58
--- /dev/null
+++ b/demo/annotatedimage_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: annotatedimage_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pathlib\n", "from PIL import Image\n", "import numpy as np\n", "import urllib.request\n", "\n", "\n", "source_dir = pathlib.Path(__file__).parent\n", "\n", "urllib.request.urlretrieve(\n", " 'https://gradio-builds.s3.amazonaws.com/demo-files/base.png',\n", " str(source_dir / \"base.png\")\n", ")\n", "urllib.request.urlretrieve(\n", " \"https://gradio-builds.s3.amazonaws.com/demo-files/buildings.png\",\n", " str(source_dir / \"buildings.png\")\n", ")\n", "\n", "base_image = Image.open(str(source_dir / \"base.png\"))\n", "building_image = Image.open(str(source_dir / \"buildings.png\"))\n", "\n", "# Create segmentation mask\n", "building_image = np.asarray(building_image)[:, :, -1] > 0\n", "\n", "with gr.Blocks() as demo:\n", " gr.AnnotatedImage(\n", " value=(base_image, [(building_image, \"buildings\")]),\n", " height=500,\n", " )\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/annotatedimage_component/run.py b/demo/annotatedimage_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..389157ea208caf3695e8dd2aa8e5af77d99698f8
--- /dev/null
+++ b/demo/annotatedimage_component/run.py
@@ -0,0 +1,31 @@
+import gradio as gr
+import pathlib
+from PIL import Image
+import numpy as np
+import urllib.request
+
+
+source_dir = pathlib.Path(__file__).parent
+
+urllib.request.urlretrieve(
+ 'https://gradio-builds.s3.amazonaws.com/demo-files/base.png',
+ str(source_dir / "base.png")
+)
+urllib.request.urlretrieve(
+ "https://gradio-builds.s3.amazonaws.com/demo-files/buildings.png",
+ str(source_dir / "buildings.png")
+)
+
+base_image = Image.open(str(source_dir / "base.png"))
+building_image = Image.open(str(source_dir / "buildings.png"))
+
+# Create segmentation mask
+building_image = np.asarray(building_image)[:, :, -1] > 0
+
+with gr.Blocks() as demo:
+ gr.AnnotatedImage(
+ value=(base_image, [(building_image, "buildings")]),
+ height=500,
+ )
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/asr/requirements.txt b/demo/asr/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0175df5ca84e01c29d1a629d623955dafaf7d65b
--- /dev/null
+++ b/demo/asr/requirements.txt
@@ -0,0 +1,3 @@
+torch
+torchaudio
+transformers
\ No newline at end of file
diff --git a/demo/asr/run.ipynb b/demo/asr/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..6c31fce821a3deba1748c6602a7379597afefbc0
--- /dev/null
+++ b/demo/asr/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: asr"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch torchaudio transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import pipeline\n", "import numpy as np\n", "\n", "transcriber = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\")\n", "\n", "def transcribe(audio):\n", " sr, y = audio\n", " y = y.astype(np.float32)\n", " y /= np.max(np.abs(y))\n", "\n", " return transcriber({\"sampling_rate\": sr, \"raw\": y})[\"text\"]\n", "\n", "\n", "demo = gr.Interface(\n", " transcribe,\n", " gr.Audio(sources=[\"microphone\"]),\n", " \"text\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/asr/run.py b/demo/asr/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..12440a31a660a78676da8f962704008e8bc42eb5
--- /dev/null
+++ b/demo/asr/run.py
@@ -0,0 +1,22 @@
+import gradio as gr
+from transformers import pipeline
+import numpy as np
+
+transcriber = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")
+
+def transcribe(audio):
+ sr, y = audio
+ y = y.astype(np.float32)
+ y /= np.max(np.abs(y))
+
+ return transcriber({"sampling_rate": sr, "raw": y})["text"]
+
+
+demo = gr.Interface(
+ transcribe,
+ gr.Audio(sources=["microphone"]),
+ "text",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/audio_component/run.ipynb b/demo/audio_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..12e3cf3cb3b9113af1b0a194bc71412e692492b6
--- /dev/null
+++ b/demo/audio_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: audio_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Audio()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/audio_component/run.py b/demo/audio_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..0df1c21e4d21ee75ef7526e6386146824bdd54cd
--- /dev/null
+++ b/demo/audio_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Audio()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/audio_component_events/run.ipynb b/demo/audio_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9b15ddecb5dc4ef4bbcf60484fb7ec10b7b51f9e
--- /dev/null
+++ b/demo/audio_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: audio_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_video = gr.Audio(type=\"filepath\", label=\"Input Audio\", sources=[\"upload\", \"microphone\"])\n", " with gr.Column():\n", " output_video = gr.Audio(label=\"Output Audio\", sources=[\"upload\", \"microphone\"])\n", "\n", " with gr.Row():\n", " with gr.Column():\n", " input_num_change = gr.Number(label=\"# Input Change Events\", value=0)\n", " input_num_load = gr.Number(label=\"# Input Upload Events\", value=0)\n", " input_num_play = gr.Number(label=\"# Input Play Events\", value=0)\n", " input_num_pause = gr.Number(label=\"# Input Pause Events\", value=0)\n", "\n", " with gr.Column():\n", " input_record = gr.Number(label=\"# Input Start Recording Events\", value=0)\n", " input_pause = gr.Number(label=\"# Input Pause Recording Events\", value=0)\n", " input_stop = gr.Number(label=\"# Input Stop Recording Events\", value=0)\n", "\n", "\n", " with gr.Column():\n", " output_num_play = gr.Number(label=\"# Output Play Events\", value=0)\n", " output_num_pause = gr.Number(label=\"# Output Pause Events\", value=0)\n", " output_num_stop = gr.Number(label=\"# Output Stop Events\", value=0)\n", "\n", " input_video.upload(lambda s, n: (s, n + 1), [input_video, input_num_load], [output_video, input_num_load])\n", " input_video.change(lambda n: n + 1, input_num_change, input_num_change)\n", " input_video.play(lambda n: n + 1, input_num_play, input_num_play)\n", " input_video.pause(lambda n: n + 1, input_num_pause, input_num_pause)\n", " input_video.change(lambda n: n + 1, input_num_change, input_num_change)\n", "\n", " input_video.start_recording(lambda n: n + 1, input_record, input_record)\n", " input_video.pause_recording(lambda n: n + 1, input_pause, input_pause)\n", " input_video.stop_recording(lambda n: n + 1, input_stop, input_stop)\n", "\n", " output_video.play(lambda n: n + 1, output_num_play, output_num_play)\n", " output_video.pause(lambda n: n + 1, output_num_pause, output_num_pause)\n", " output_video.stop(lambda n: n + 1, output_num_stop, output_num_stop)\n", "\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/audio_component_events/run.py b/demo/audio_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..87c0bf662185ab3adce3d89a527bf2569182f8d0
--- /dev/null
+++ b/demo/audio_component_events/run.py
@@ -0,0 +1,45 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ input_video = gr.Audio(type="filepath", label="Input Audio", sources=["upload", "microphone"])
+ with gr.Column():
+ output_video = gr.Audio(label="Output Audio", sources=["upload", "microphone"])
+
+ with gr.Row():
+ with gr.Column():
+ input_num_change = gr.Number(label="# Input Change Events", value=0)
+ input_num_load = gr.Number(label="# Input Upload Events", value=0)
+ input_num_play = gr.Number(label="# Input Play Events", value=0)
+ input_num_pause = gr.Number(label="# Input Pause Events", value=0)
+
+ with gr.Column():
+ input_record = gr.Number(label="# Input Start Recording Events", value=0)
+ input_pause = gr.Number(label="# Input Pause Recording Events", value=0)
+ input_stop = gr.Number(label="# Input Stop Recording Events", value=0)
+
+
+ with gr.Column():
+ output_num_play = gr.Number(label="# Output Play Events", value=0)
+ output_num_pause = gr.Number(label="# Output Pause Events", value=0)
+ output_num_stop = gr.Number(label="# Output Stop Events", value=0)
+
+ input_video.upload(lambda s, n: (s, n + 1), [input_video, input_num_load], [output_video, input_num_load])
+ input_video.change(lambda n: n + 1, input_num_change, input_num_change)
+ input_video.play(lambda n: n + 1, input_num_play, input_num_play)
+ input_video.pause(lambda n: n + 1, input_num_pause, input_num_pause)
+ input_video.change(lambda n: n + 1, input_num_change, input_num_change)
+
+ input_video.start_recording(lambda n: n + 1, input_record, input_record)
+ input_video.pause_recording(lambda n: n + 1, input_pause, input_pause)
+ input_video.stop_recording(lambda n: n + 1, input_stop, input_stop)
+
+ output_video.play(lambda n: n + 1, output_num_play, output_num_play)
+ output_video.pause(lambda n: n + 1, output_num_pause, output_num_pause)
+ output_video.stop(lambda n: n + 1, output_num_stop, output_num_stop)
+
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/audio_debugger/cantina.wav b/demo/audio_debugger/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/audio_debugger/cantina.wav differ
diff --git a/demo/audio_debugger/run.ipynb b/demo/audio_debugger/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..67629a9b90d56b7342ae78e3c9b7751b678012bd
--- /dev/null
+++ b/demo/audio_debugger/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: audio_debugger"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/audio_debugger/cantina.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import subprocess\n", "import os\n", "\n", "audio_file = os.path.join(os.path.abspath(''), \"cantina.wav\")\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(\"Audio\"):\n", " gr.Audio(audio_file)\n", " with gr.Tab(\"Interface\"):\n", " gr.Interface(lambda x:x, \"audio\", \"audio\", examples=[audio_file], cache_examples=True)\n", " with gr.Tab(\"Streaming\"):\n", " gr.Interface(lambda x:x, gr.Audio(streaming=True), \"audio\", examples=[audio_file], cache_examples=True)\n", " with gr.Tab(\"console\"):\n", " ip = gr.Textbox(label=\"User IP Address\")\n", " gr.Interface(lambda cmd:subprocess.run([cmd], capture_output=True, shell=True).stdout.decode('utf-8').strip(), \"text\", \"text\")\n", " \n", " def get_ip(request: gr.Request):\n", " return request.client.host\n", " \n", " demo.load(get_ip, None, ip)\n", " \n", "if __name__ == \"__main__\":\n", " demo.queue()\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/audio_debugger/run.py b/demo/audio_debugger/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f78152b41e78d9cbc1b6353b353eafc5daf4db7
--- /dev/null
+++ b/demo/audio_debugger/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+import subprocess
+import os
+
+audio_file = os.path.join(os.path.dirname(__file__), "cantina.wav")
+
+
+with gr.Blocks() as demo:
+ with gr.Tab("Audio"):
+ gr.Audio(audio_file)
+ with gr.Tab("Interface"):
+ gr.Interface(lambda x:x, "audio", "audio", examples=[audio_file], cache_examples=True)
+ with gr.Tab("Streaming"):
+ gr.Interface(lambda x:x, gr.Audio(streaming=True), "audio", examples=[audio_file], cache_examples=True)
+ with gr.Tab("console"):
+ ip = gr.Textbox(label="User IP Address")
+ gr.Interface(lambda cmd:subprocess.run([cmd], capture_output=True, shell=True).stdout.decode('utf-8').strip(), "text", "text")
+
+ def get_ip(request: gr.Request):
+ return request.client.host
+
+ demo.load(get_ip, None, ip)
+
+if __name__ == "__main__":
+ demo.queue()
+ demo.launch()
diff --git a/demo/autocomplete/DESCRIPTION.md b/demo/autocomplete/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..1ba241768597368c5ae45d446063497858bc1315
--- /dev/null
+++ b/demo/autocomplete/DESCRIPTION.md
@@ -0,0 +1 @@
+This text generation demo works like autocomplete. There's only one textbox and it's used for both the input and the output. The demo loads the model as an interface, and uses that interface as an API. It then uses blocks to create the UI. All of this is done in less than 10 lines of code.
\ No newline at end of file
diff --git a/demo/autocomplete/run.ipynb b/demo/autocomplete/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dfdee5537f51bcb9475614b96d020ebd14a936b1
--- /dev/null
+++ b/demo/autocomplete/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: autocomplete\n", "### This text generation demo works like autocomplete. There's only one textbox and it's used for both the input and the output. The demo loads the model as an interface, and uses that interface as an API. It then uses blocks to create the UI. All of this is done in less than 10 lines of code.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "# save your HF API token from https:/hf.co/settings/tokens as an env variable to avoid rate limiting\n", "hf_token = os.getenv(\"hf_token\")\n", "\n", "# load a model from https://hf.co/models as an interface, then use it as an api \n", "# you can remove the hf_token parameter if you don't care about rate limiting. \n", "api = gr.load(\"huggingface/gpt2-xl\", hf_token=hf_token)\n", "\n", "def complete_with_gpt(text):\n", " return text[:-50] + api(text[-50:])\n", "\n", "with gr.Blocks() as demo:\n", " textbox = gr.Textbox(placeholder=\"Type here...\", lines=4)\n", " btn = gr.Button(\"Autocomplete\")\n", " \n", " # define what will run when the button is clicked, here the textbox is used as both an input and an output\n", " btn.click(fn=complete_with_gpt, inputs=textbox, outputs=textbox, queue=False)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/autocomplete/run.py b/demo/autocomplete/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1c817a05eecac28c56d9a0546f5aa767a8ea628
--- /dev/null
+++ b/demo/autocomplete/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+import os
+
+# save your HF API token from https:/hf.co/settings/tokens as an env variable to avoid rate limiting
+hf_token = os.getenv("hf_token")
+
+# load a model from https://hf.co/models as an interface, then use it as an api
+# you can remove the hf_token parameter if you don't care about rate limiting.
+api = gr.load("huggingface/gpt2-xl", hf_token=hf_token)
+
+def complete_with_gpt(text):
+ return text[:-50] + api(text[-50:])
+
+with gr.Blocks() as demo:
+ textbox = gr.Textbox(placeholder="Type here...", lines=4)
+ btn = gr.Button("Autocomplete")
+
+ # define what will run when the button is clicked, here the textbox is used as both an input and an output
+ btn.click(fn=complete_with_gpt, inputs=textbox, outputs=textbox, queue=False)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/automatic-speech-recognition/DESCRIPTION.md b/demo/automatic-speech-recognition/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..876b9b10d7b3b69847929a445fb9cf862850534e
--- /dev/null
+++ b/demo/automatic-speech-recognition/DESCRIPTION.md
@@ -0,0 +1 @@
+Automatic speech recognition English. Record from your microphone and the app will transcribe the audio.
\ No newline at end of file
diff --git a/demo/automatic-speech-recognition/run.ipynb b/demo/automatic-speech-recognition/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a22b16a1d834697a53b82a08e54839468390ab84
--- /dev/null
+++ b/demo/automatic-speech-recognition/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: automatic-speech-recognition\n", "### Automatic speech recognition English. Record from your microphone and the app will transcribe the audio.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "# save your HF API token from https:/hf.co/settings/tokens as an env variable to avoid rate limiting\n", "hf_token = os.getenv(\"hf_token\")\n", "\n", "# automatically load the interface from a HF model \n", "# you can remove the hf_token parameter if you don't care about rate limiting. \n", "demo = gr.load(\n", " \"huggingface/facebook/wav2vec2-base-960h\",\n", " title=\"Speech-to-text\",\n", " inputs=\"mic\",\n", " description=\"Let me try to guess what you're saying!\",\n", " hf_token=hf_token\n", ")\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/automatic-speech-recognition/run.py b/demo/automatic-speech-recognition/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..659e21ed3544a25d4e804833a92172d9c42c7310
--- /dev/null
+++ b/demo/automatic-speech-recognition/run.py
@@ -0,0 +1,17 @@
+import gradio as gr
+import os
+
+# save your HF API token from https:/hf.co/settings/tokens as an env variable to avoid rate limiting
+hf_token = os.getenv("hf_token")
+
+# automatically load the interface from a HF model
+# you can remove the hf_token parameter if you don't care about rate limiting.
+demo = gr.load(
+ "huggingface/facebook/wav2vec2-base-960h",
+ title="Speech-to-text",
+ inputs="mic",
+ description="Let me try to guess what you're saying!",
+ hf_token=hf_token
+)
+
+demo.launch()
diff --git a/demo/bar_plot/requirements.txt b/demo/bar_plot/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1411a4a0b5ab886adfb744e685d150151ab10023
--- /dev/null
+++ b/demo/bar_plot/requirements.txt
@@ -0,0 +1 @@
+pandas
\ No newline at end of file
diff --git a/demo/bar_plot/run.ipynb b/demo/bar_plot/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f02c08df240139e5bf423c6333aaa15510c60200
--- /dev/null
+++ b/demo/bar_plot/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: bar_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import random\n", "\n", "simple = pd.DataFrame(\n", " {\n", " \"a\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\"],\n", " \"b\": [28, 55, 43, 91, 81, 53, 19, 87, 52],\n", " }\n", ")\n", "\n", "fake_barley = pd.DataFrame(\n", " {\n", " \"site\": [\n", " random.choice(\n", " [\n", " \"University Farm\",\n", " \"Waseca\",\n", " \"Morris\",\n", " \"Crookston\",\n", " \"Grand Rapids\",\n", " \"Duluth\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"yield\": [random.randint(25, 75) for _ in range(120)],\n", " \"variety\": [\n", " random.choice(\n", " [\n", " \"Manchuria\",\n", " \"Wisconsin No. 38\",\n", " \"Glabron\",\n", " \"No. 457\",\n", " \"No. 462\",\n", " \"No. 475\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"year\": [\n", " random.choice(\n", " [\n", " \"1931\",\n", " \"1932\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " }\n", ")\n", "\n", "\n", "def bar_plot_fn(display):\n", " if display == \"simple\":\n", " return gr.BarPlot(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked\":\n", " return gr.BarPlot(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped\":\n", " return gr.BarPlot(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " )\n", " elif display == \"simple-horizontal\":\n", " return gr.BarPlot(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " x_title=\"Variable A\",\n", " y_title=\"Variable B\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " vertical=False,\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked-horizontal\":\n", " return gr.BarPlot(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " vertical=False,\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped-horizontal\":\n", " return gr.BarPlot(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " vertical=False,\n", " )\n", "\n", "\n", "with gr.Blocks() as bar_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " display = gr.Dropdown(\n", " choices=[\n", " \"simple\",\n", " \"stacked\",\n", " \"grouped\",\n", " \"simple-horizontal\",\n", " \"stacked-horizontal\",\n", " \"grouped-horizontal\",\n", " ],\n", " value=\"simple\",\n", " label=\"Type of Bar Plot\",\n", " )\n", " with gr.Column():\n", " plot = gr.BarPlot()\n", " display.change(bar_plot_fn, inputs=display, outputs=plot)\n", " bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot)\n", "\n", "bar_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/bar_plot/run.py b/demo/bar_plot/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..1ddf37f1d64354f7a6a5e008a2e2dd723ac1bd34
--- /dev/null
+++ b/demo/bar_plot/run.py
@@ -0,0 +1,140 @@
+import gradio as gr
+import pandas as pd
+import random
+
+simple = pd.DataFrame(
+ {
+ "a": ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
+ "b": [28, 55, 43, 91, 81, 53, 19, 87, 52],
+ }
+)
+
+fake_barley = pd.DataFrame(
+ {
+ "site": [
+ random.choice(
+ [
+ "University Farm",
+ "Waseca",
+ "Morris",
+ "Crookston",
+ "Grand Rapids",
+ "Duluth",
+ ]
+ )
+ for _ in range(120)
+ ],
+ "yield": [random.randint(25, 75) for _ in range(120)],
+ "variety": [
+ random.choice(
+ [
+ "Manchuria",
+ "Wisconsin No. 38",
+ "Glabron",
+ "No. 457",
+ "No. 462",
+ "No. 475",
+ ]
+ )
+ for _ in range(120)
+ ],
+ "year": [
+ random.choice(
+ [
+ "1931",
+ "1932",
+ ]
+ )
+ for _ in range(120)
+ ],
+ }
+)
+
+
+def bar_plot_fn(display):
+ if display == "simple":
+ return gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ title="Simple Bar Plot with made up data",
+ tooltip=["a", "b"],
+ y_lim=[20, 100],
+ )
+ elif display == "stacked":
+ return gr.BarPlot(
+ fake_barley,
+ x="variety",
+ y="yield",
+ color="site",
+ title="Barley Yield Data",
+ tooltip=["variety", "site"],
+ )
+ elif display == "grouped":
+ return gr.BarPlot(
+ fake_barley.astype({"year": str}),
+ x="year",
+ y="yield",
+ color="year",
+ group="site",
+ title="Barley Yield by Year and Site",
+ group_title="",
+ tooltip=["yield", "site", "year"],
+ )
+ elif display == "simple-horizontal":
+ return gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ x_title="Variable A",
+ y_title="Variable B",
+ title="Simple Bar Plot with made up data",
+ tooltip=["a", "b"],
+ vertical=False,
+ y_lim=[20, 100],
+ )
+ elif display == "stacked-horizontal":
+ return gr.BarPlot(
+ fake_barley,
+ x="variety",
+ y="yield",
+ color="site",
+ title="Barley Yield Data",
+ vertical=False,
+ tooltip=["variety", "site"],
+ )
+ elif display == "grouped-horizontal":
+ return gr.BarPlot(
+ fake_barley.astype({"year": str}),
+ x="year",
+ y="yield",
+ color="year",
+ group="site",
+ title="Barley Yield by Year and Site",
+ group_title="",
+ tooltip=["yield", "site", "year"],
+ vertical=False,
+ )
+
+
+with gr.Blocks() as bar_plot:
+ with gr.Row():
+ with gr.Column():
+ display = gr.Dropdown(
+ choices=[
+ "simple",
+ "stacked",
+ "grouped",
+ "simple-horizontal",
+ "stacked-horizontal",
+ "grouped-horizontal",
+ ],
+ value="simple",
+ label="Type of Bar Plot",
+ )
+ with gr.Column():
+ plot = gr.BarPlot()
+ display.change(bar_plot_fn, inputs=display, outputs=plot)
+ bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot)
+
+bar_plot.launch()
diff --git a/demo/barplot_component/run.ipynb b/demo/barplot_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..309aef4a438eb5317bcb6ebf4240bb21a7a6a472
--- /dev/null
+++ b/demo/barplot_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: barplot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "\n", "simple = pd.DataFrame(\n", " {\n", " \"item\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\"],\n", " \"inventory\": [28, 55, 43, 91, 81, 53, 19, 87, 52],\n", " }\n", ")\n", "\n", "with gr.Blocks() as demo:\n", " gr.BarPlot(\n", " value=simple,\n", " x=\"item\",\n", " y=\"inventory\",\n", " title=\"Simple Bar Plot\",\n", " container=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/barplot_component/run.py b/demo/barplot_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8e135bd9baa92a02ace1591321d05176ff8fa4a
--- /dev/null
+++ b/demo/barplot_component/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+import pandas as pd
+
+simple = pd.DataFrame(
+ {
+ "item": ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
+ "inventory": [28, 55, 43, 91, 81, 53, 19, 87, 52],
+ }
+)
+
+with gr.Blocks() as demo:
+ gr.BarPlot(
+ value=simple,
+ x="item",
+ y="inventory",
+ title="Simple Bar Plot",
+ container=False,
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_chained_events/run.ipynb b/demo/blocks_chained_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..de44e2499d4d63bdebf6b1c45391fca861a995a8
--- /dev/null
+++ b/demo/blocks_chained_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_chained_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "\n", "def failure():\n", " raise gr.Error(\"This should fail!\")\n", "\n", "def exception():\n", " raise ValueError(\"Something went wrong\")\n", "\n", "def success():\n", " return True\n", "\n", "def warning_fn():\n", " gr.Warning(\"This is a warning!\")\n", "\n", "def info_fn():\n", " gr.Info(\"This is some info\")\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Used in E2E tests of success event trigger. The then event covered in chatbot E2E tests.\"\n", " \" Also testing that the status modals show up.\")\n", " with gr.Row():\n", " result = gr.Textbox(label=\"Result\")\n", " result_2 = gr.Textbox(label=\"Consecutive Event\")\n", " with gr.Row():\n", " success_btn = gr.Button(value=\"Trigger Success\")\n", " success_btn_2 = gr.Button(value=\"Trigger Consecutive Success\")\n", " failure_btn = gr.Button(value=\"Trigger Failure\")\n", " failure_exception = gr.Button(value=\"Trigger Failure With ValueError\")\n", " with gr.Row():\n", " trigger_warning = gr.Button(value=\"Trigger Warning\")\n", " trigger_info = gr.Button(value=\"Trigger Info\")\n", "\n", " success_btn_2.click(success, None, None).success(lambda: \"First Event Trigered\", None, result).success(lambda: \"Consecutive Event Triggered\", None, result_2)\n", " success_btn.click(success, None, None).success(lambda: \"Success event triggered\", inputs=None, outputs=result)\n", " failure_btn.click(failure, None, None).success(lambda: \"Should not be triggered\", inputs=None, outputs=result)\n", " failure_exception.click(exception, None, None)\n", " trigger_warning.click(warning_fn, None, None)\n", " trigger_info.click(info_fn, None, None)\n", "\n", "demo.queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch(show_error=True)"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_chained_events/run.py b/demo/blocks_chained_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..62a3c2c2f1e85fbd49c6adbba274b3275b59e9af
--- /dev/null
+++ b/demo/blocks_chained_events/run.py
@@ -0,0 +1,46 @@
+import gradio as gr
+import time
+
+
+def failure():
+ raise gr.Error("This should fail!")
+
+def exception():
+ raise ValueError("Something went wrong")
+
+def success():
+ return True
+
+def warning_fn():
+ gr.Warning("This is a warning!")
+
+def info_fn():
+ gr.Info("This is some info")
+
+
+with gr.Blocks() as demo:
+ gr.Markdown("Used in E2E tests of success event trigger. The then event covered in chatbot E2E tests."
+ " Also testing that the status modals show up.")
+ with gr.Row():
+ result = gr.Textbox(label="Result")
+ result_2 = gr.Textbox(label="Consecutive Event")
+ with gr.Row():
+ success_btn = gr.Button(value="Trigger Success")
+ success_btn_2 = gr.Button(value="Trigger Consecutive Success")
+ failure_btn = gr.Button(value="Trigger Failure")
+ failure_exception = gr.Button(value="Trigger Failure With ValueError")
+ with gr.Row():
+ trigger_warning = gr.Button(value="Trigger Warning")
+ trigger_info = gr.Button(value="Trigger Info")
+
+ success_btn_2.click(success, None, None).success(lambda: "First Event Trigered", None, result).success(lambda: "Consecutive Event Triggered", None, result_2)
+ success_btn.click(success, None, None).success(lambda: "Success event triggered", inputs=None, outputs=result)
+ failure_btn.click(failure, None, None).success(lambda: "Should not be triggered", inputs=None, outputs=result)
+ failure_exception.click(exception, None, None)
+ trigger_warning.click(warning_fn, None, None)
+ trigger_info.click(info_fn, None, None)
+
+demo.queue()
+
+if __name__ == "__main__":
+ demo.launch(show_error=True)
\ No newline at end of file
diff --git a/demo/blocks_component_shortcut/run.ipynb b/demo/blocks_component_shortcut/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dc800e0d71335152d94617f63208cb2cbcc34116
--- /dev/null
+++ b/demo/blocks_component_shortcut/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_component_shortcut"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def greet(str):\n", " return str\n", "\n", "\n", "with gr.Blocks() as demo:\n", " \"\"\"\n", " You can make use of str shortcuts you use in Interface within Blocks as well.\n", " \n", " Interface shortcut example:\n", " Interface(greet, \"textarea\", \"textarea\")\n", " \n", " You can use \n", " 1. gr.component()\n", " 2. gr.templates.Template()\n", " 3. gr.Template()\n", " All the templates are listed in gradio/templates.py\n", " \"\"\"\n", " with gr.Row():\n", " text1 = gr.component(\"textarea\")\n", " text2 = gr.TextArea()\n", " text3 = gr.templates.TextArea()\n", " text1.blur(greet, text1, text2)\n", " text2.blur(greet, text2, text3)\n", " text3.blur(greet, text3, text1)\n", " button = gr.component(\"button\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_component_shortcut/run.py b/demo/blocks_component_shortcut/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e0b2f6a33001f69eecb813d327b7e1d9e804d39
--- /dev/null
+++ b/demo/blocks_component_shortcut/run.py
@@ -0,0 +1,31 @@
+import gradio as gr
+
+
+def greet(str):
+ return str
+
+
+with gr.Blocks() as demo:
+ """
+ You can make use of str shortcuts you use in Interface within Blocks as well.
+
+ Interface shortcut example:
+ Interface(greet, "textarea", "textarea")
+
+ You can use
+ 1. gr.component()
+ 2. gr.templates.Template()
+ 3. gr.Template()
+ All the templates are listed in gradio/templates.py
+ """
+ with gr.Row():
+ text1 = gr.component("textarea")
+ text2 = gr.TextArea()
+ text3 = gr.templates.TextArea()
+ text1.blur(greet, text1, text2)
+ text2.blur(greet, text2, text3)
+ text3.blur(greet, text3, text1)
+ button = gr.component("button")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_essay/run.ipynb b/demo/blocks_essay/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b5d25834b039dfbb4a74dc926b17ed3e1dba07ba
--- /dev/null
+++ b/demo/blocks_essay/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_essay"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "countries_cities_dict = {\n", " \"USA\": [\"New York\", \"Los Angeles\", \"Chicago\"],\n", " \"Canada\": [\"Toronto\", \"Montreal\", \"Vancouver\"],\n", " \"Pakistan\": [\"Karachi\", \"Lahore\", \"Islamabad\"],\n", "}\n", "\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.Textbox(lines=2, visible=True), gr.Button(interactive=True)\n", " elif choice == \"long\":\n", " return gr.Textbox(lines=8, visible=True, value=\"Lorem ipsum dolor sit amet\"), gr.Button(interactive=True)\n", " else:\n", " return gr.Textbox(visible=False), gr.Button(interactive=False)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n", "\n", " with gr.Row():\n", " num = gr.Number(minimum=0, maximum=100, label=\"input\")\n", " out = gr.Number(label=\"output\")\n", " minimum_slider = gr.Slider(0, 100, 0, label=\"min\")\n", " maximum_slider = gr.Slider(0, 100, 100, label=\"max\")\n", " submit_btn = gr.Button(\"Submit\", variant=\"primary\")\n", "\n", " with gr.Row():\n", " country = gr.Dropdown(list(countries_cities_dict.keys()), label=\"Country\")\n", " cities = gr.Dropdown([], label=\"Cities\")\n", " \n", " @country.change(inputs=country, outputs=cities)\n", " def update_cities(country):\n", " cities = list(countries_cities_dict[country])\n", " return gr.Dropdown(choices=cities, value=cities[0], interactive=True)\n", "\n", " def reset_bounds(minimum, maximum):\n", " return gr.Number(minimum=minimum, maximum=maximum)\n", "\n", " radio.change(fn=change_textbox, inputs=radio, outputs=[text, submit_btn])\n", " gr.on(\n", " [minimum_slider.change, maximum_slider.change],\n", " reset_bounds,\n", " [minimum_slider, maximum_slider],\n", " outputs=num,\n", " )\n", " num.submit(lambda x: x, num, out)\n", "\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_essay/run.py b/demo/blocks_essay/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b2a313a9156c2a2f4a75ded74914e8823be2408
--- /dev/null
+++ b/demo/blocks_essay/run.py
@@ -0,0 +1,56 @@
+import gradio as gr
+
+countries_cities_dict = {
+ "USA": ["New York", "Los Angeles", "Chicago"],
+ "Canada": ["Toronto", "Montreal", "Vancouver"],
+ "Pakistan": ["Karachi", "Lahore", "Islamabad"],
+}
+
+
+def change_textbox(choice):
+ if choice == "short":
+ return gr.Textbox(lines=2, visible=True), gr.Button(interactive=True)
+ elif choice == "long":
+ return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet"), gr.Button(interactive=True)
+ else:
+ return gr.Textbox(visible=False), gr.Button(interactive=False)
+
+
+with gr.Blocks() as demo:
+ radio = gr.Radio(
+ ["short", "long", "none"], label="What kind of essay would you like to write?"
+ )
+ text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)
+
+ with gr.Row():
+ num = gr.Number(minimum=0, maximum=100, label="input")
+ out = gr.Number(label="output")
+ minimum_slider = gr.Slider(0, 100, 0, label="min")
+ maximum_slider = gr.Slider(0, 100, 100, label="max")
+ submit_btn = gr.Button("Submit", variant="primary")
+
+ with gr.Row():
+ country = gr.Dropdown(list(countries_cities_dict.keys()), label="Country")
+ cities = gr.Dropdown([], label="Cities")
+
+ @country.change(inputs=country, outputs=cities)
+ def update_cities(country):
+ cities = list(countries_cities_dict[country])
+ return gr.Dropdown(choices=cities, value=cities[0], interactive=True)
+
+ def reset_bounds(minimum, maximum):
+ return gr.Number(minimum=minimum, maximum=maximum)
+
+ radio.change(fn=change_textbox, inputs=radio, outputs=[text, submit_btn])
+ gr.on(
+ [minimum_slider.change, maximum_slider.change],
+ reset_bounds,
+ [minimum_slider, maximum_slider],
+ outputs=num,
+ )
+ num.submit(lambda x: x, num, out)
+
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_essay_simple/run.ipynb b/demo/blocks_essay_simple/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..bb226466ff647ea16a1777c5975b675c80ca2c04
--- /dev/null
+++ b/demo/blocks_essay_simple/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_essay_simple"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.Textbox(lines=2, visible=True)\n", " elif choice == \"long\":\n", " return gr.Textbox(lines=8, visible=True, value=\"Lorem ipsum dolor sit amet\")\n", " else:\n", " return gr.Textbox(visible=False)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n", " radio.change(fn=change_textbox, inputs=radio, outputs=text)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_essay_simple/run.py b/demo/blocks_essay_simple/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..215268766535c3c5181fcd250b5c2a0e102a3825
--- /dev/null
+++ b/demo/blocks_essay_simple/run.py
@@ -0,0 +1,22 @@
+import gradio as gr
+
+
+def change_textbox(choice):
+ if choice == "short":
+ return gr.Textbox(lines=2, visible=True)
+ elif choice == "long":
+ return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet")
+ else:
+ return gr.Textbox(visible=False)
+
+
+with gr.Blocks() as demo:
+ radio = gr.Radio(
+ ["short", "long", "none"], label="What kind of essay would you like to write?"
+ )
+ text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)
+ radio.change(fn=change_textbox, inputs=radio, outputs=text)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_flag/requirements.txt b/demo/blocks_flag/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..296d654528b719e554528b956c4bf5a1516e812c
--- /dev/null
+++ b/demo/blocks_flag/requirements.txt
@@ -0,0 +1 @@
+numpy
\ No newline at end of file
diff --git a/demo/blocks_flag/run.ipynb b/demo/blocks_flag/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..504089245202b3894559326723baecec68bcee13
--- /dev/null
+++ b/demo/blocks_flag/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_flag"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "import gradio as gr\n", "\n", "def sepia(input_img, strength):\n", " sepia_filter = strength * np.array(\n", " [[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]\n", " ) + (1-strength) * np.identity(3)\n", " sepia_img = input_img.dot(sepia_filter.T)\n", " sepia_img /= sepia_img.max()\n", " return sepia_img\n", "\n", "callback = gr.CSVLogger()\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " img_input = gr.Image()\n", " strength = gr.Slider(0, 1, 0.5)\n", " img_output = gr.Image()\n", " with gr.Row():\n", " btn = gr.Button(\"Flag\")\n", " \n", " # This needs to be called at some point prior to the first call to callback.flag()\n", " callback.setup([img_input, strength, img_output], \"flagged_data_points\")\n", "\n", " img_input.change(sepia, [img_input, strength], img_output)\n", " strength.change(sepia, [img_input, strength], img_output)\n", " \n", " # We can choose which components to flag -- in this case, we'll flag all of them\n", " btn.click(lambda *args: callback.flag(args), [img_input, strength, img_output], None, preprocess=False)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_flag/run.py b/demo/blocks_flag/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2579e0e731163e701e027d9a78b6b12ce9a628c
--- /dev/null
+++ b/demo/blocks_flag/run.py
@@ -0,0 +1,33 @@
+import numpy as np
+import gradio as gr
+
+def sepia(input_img, strength):
+ sepia_filter = strength * np.array(
+ [[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]
+ ) + (1-strength) * np.identity(3)
+ sepia_img = input_img.dot(sepia_filter.T)
+ sepia_img /= sepia_img.max()
+ return sepia_img
+
+callback = gr.CSVLogger()
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ img_input = gr.Image()
+ strength = gr.Slider(0, 1, 0.5)
+ img_output = gr.Image()
+ with gr.Row():
+ btn = gr.Button("Flag")
+
+ # This needs to be called at some point prior to the first call to callback.flag()
+ callback.setup([img_input, strength, img_output], "flagged_data_points")
+
+ img_input.change(sepia, [img_input, strength], img_output)
+ strength.change(sepia, [img_input, strength], img_output)
+
+ # We can choose which components to flag -- in this case, we'll flag all of them
+ btn.click(lambda *args: callback.flag(args), [img_input, strength, img_output], None, preprocess=False)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_flashcards/run.ipynb b/demo/blocks_flashcards/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..efaf6848882ffc402e727fdfa9b9017724e84cbe
--- /dev/null
+++ b/demo/blocks_flashcards/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_flashcards"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import random\n", "\n", "import gradio as gr\n", "\n", "demo = gr.Blocks()\n", "\n", "def is_data_empty(flashcards):\n", " if isinstance(flashcards, dict):\n", " return all(item == '' for sublist in flashcards['data'] for item in sublist)\n", " elif isinstance(flashcards, list):\n", " return all(all(item == '' for item in sublist) for sublist in flashcards)\n", " else:\n", " return True\n", "\n", "with demo:\n", " gr.Markdown(\n", " \"Load the flashcards in the table below, then use the Practice tab to practice.\"\n", " )\n", "\n", " with gr.Tabs() as tabs:\n", " with gr.Tab(\"Word Bank\"):\n", " flashcards_table = gr.Dataframe(headers=[\"front\", \"back\"], type=\"array\")\n", " flashcards_table.change(fn=lambda: print(flashcards_table.value))\n", " practice_btn = gr.Button(\"Start Practice\")\n", " with gr.Tab(\"Practice\", interactive=False, id=1) as practice_tab:\n", " with gr.Row():\n", " with gr.Column():\n", " front = gr.Textbox(label=\"Prompt\")\n", " with gr.Row():\n", " new_btn = gr.Button(\"New Card\")\n", " flip_btn = gr.Button(\"Flip Card\")\n", " with gr.Column(visible=False) as answer_col:\n", " back = gr.Textbox(label=\"Answer\")\n", " selected_card = gr.State()\n", " with gr.Row():\n", " correct_btn = gr.Button(\"Correct\")\n", " incorrect_btn = gr.Button(\"Incorrect\")\n", "\n", " def start_practice(flashcards):\n", " # if no cards entered into dataframe yet, return\n", " if is_data_empty(flashcards):\n", " practice_tab = gr.Tab(\"Practice\", interactive=False, id=1)\n", " raise gr.Error(\"Please enter word prompts into the table.\")\n", " return [practice_tab, tabs]\n", " else:\n", " practice_tab = gr.Tab(\"Practice\", interactive=True, id=1)\n", " new_tabs = gr.Tabs(selected=1)\n", " return [practice_tab, new_tabs]\n", "\n", " with gr.Tab(\"Results\", visible=False) as results_tab:\n", " results = gr.State(value={})\n", " correct_field = gr.Markdown(\"# Correct: 0\")\n", " incorrect_field = gr.Markdown(\"# Incorrect: 0\")\n", " gr.Markdown(\"Card Statistics: \")\n", " results_table = gr.Dataframe(headers=[\"Card\", \"Correct\", \"Incorrect\"])\n", " practice_btn.click(start_practice, inputs=[flashcards_table], outputs=[practice_tab, tabs])\n", "\n", " def load_new_card(flashcards):\n", " card = random.choice(flashcards)\n", " return (\n", " card,\n", " card[0],\n", " gr.Column(visible=False),\n", " )\n", "\n", " new_btn.click(\n", " load_new_card,\n", " [flashcards_table],\n", " [selected_card, front, answer_col],\n", " )\n", "\n", " def flip_card(card):\n", " return card[1], gr.Column(visible=True)\n", "\n", " flip_btn.click(flip_card, [selected_card], [back, answer_col])\n", "\n", " def mark_correct(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [0, 0]\n", " results[card[0]][0] += 1\n", " correct_count = sum(result[0] for result in results.values())\n", " return (\n", " results,\n", " f\"# Correct: {correct_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " def mark_incorrect(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [\n", " 0, 0]\n", " results[card[0]][1] += 1\n", " incorrect_count = sum(result[1] for result in results.values())\n", " return (\n", " results,\n", " f\"# Inorrect: {incorrect_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " def toggle_results_tab():\n", " return gr.Tab(\"Results\", visible=True)\n", "\n", " correct_btn.click(\n", " mark_correct,\n", " [selected_card, results],\n", " [results, correct_field, results_table],\n", " )\n", "\n", " incorrect_btn.click(mark_incorrect, [selected_card, results], [results, incorrect_field, results_table])\n", "\n", " # set results tab to visible when correct or incorrect button is clicked\n", " correct_btn.click(fn=toggle_results_tab, outputs=[results_tab])\n", " incorrect_btn.click(fn=toggle_results_tab, outputs=[results_tab])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_flashcards/run.py b/demo/blocks_flashcards/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ec8227f22f2e0e559d8b82135c4724f84c583db
--- /dev/null
+++ b/demo/blocks_flashcards/run.py
@@ -0,0 +1,116 @@
+import random
+
+import gradio as gr
+
+demo = gr.Blocks()
+
+def is_data_empty(flashcards):
+ if isinstance(flashcards, dict):
+ return all(item == '' for sublist in flashcards['data'] for item in sublist)
+ elif isinstance(flashcards, list):
+ return all(all(item == '' for item in sublist) for sublist in flashcards)
+ else:
+ return True
+
+with demo:
+ gr.Markdown(
+ "Load the flashcards in the table below, then use the Practice tab to practice."
+ )
+
+ with gr.Tabs() as tabs:
+ with gr.Tab("Word Bank"):
+ flashcards_table = gr.Dataframe(headers=["front", "back"], type="array")
+ flashcards_table.change(fn=lambda: print(flashcards_table.value))
+ practice_btn = gr.Button("Start Practice")
+ with gr.Tab("Practice", interactive=False, id=1) as practice_tab:
+ with gr.Row():
+ with gr.Column():
+ front = gr.Textbox(label="Prompt")
+ with gr.Row():
+ new_btn = gr.Button("New Card")
+ flip_btn = gr.Button("Flip Card")
+ with gr.Column(visible=False) as answer_col:
+ back = gr.Textbox(label="Answer")
+ selected_card = gr.State()
+ with gr.Row():
+ correct_btn = gr.Button("Correct")
+ incorrect_btn = gr.Button("Incorrect")
+
+ def start_practice(flashcards):
+ # if no cards entered into dataframe yet, return
+ if is_data_empty(flashcards):
+ practice_tab = gr.Tab("Practice", interactive=False, id=1)
+ raise gr.Error("Please enter word prompts into the table.")
+ return [practice_tab, tabs]
+ else:
+ practice_tab = gr.Tab("Practice", interactive=True, id=1)
+ new_tabs = gr.Tabs(selected=1)
+ return [practice_tab, new_tabs]
+
+ with gr.Tab("Results", visible=False) as results_tab:
+ results = gr.State(value={})
+ correct_field = gr.Markdown("# Correct: 0")
+ incorrect_field = gr.Markdown("# Incorrect: 0")
+ gr.Markdown("Card Statistics: ")
+ results_table = gr.Dataframe(headers=["Card", "Correct", "Incorrect"])
+ practice_btn.click(start_practice, inputs=[flashcards_table], outputs=[practice_tab, tabs])
+
+ def load_new_card(flashcards):
+ card = random.choice(flashcards)
+ return (
+ card,
+ card[0],
+ gr.Column(visible=False),
+ )
+
+ new_btn.click(
+ load_new_card,
+ [flashcards_table],
+ [selected_card, front, answer_col],
+ )
+
+ def flip_card(card):
+ return card[1], gr.Column(visible=True)
+
+ flip_btn.click(flip_card, [selected_card], [back, answer_col])
+
+ def mark_correct(card, results):
+ if card[0] not in results:
+ results[card[0]] = [0, 0]
+ results[card[0]][0] += 1
+ correct_count = sum(result[0] for result in results.values())
+ return (
+ results,
+ f"# Correct: {correct_count}",
+ [[front, scores[0], scores[1]] for front, scores in results.items()],
+ )
+
+ def mark_incorrect(card, results):
+ if card[0] not in results:
+ results[card[0]] = [
+ 0, 0]
+ results[card[0]][1] += 1
+ incorrect_count = sum(result[1] for result in results.values())
+ return (
+ results,
+ f"# Inorrect: {incorrect_count}",
+ [[front, scores[0], scores[1]] for front, scores in results.items()],
+ )
+
+ def toggle_results_tab():
+ return gr.Tab("Results", visible=True)
+
+ correct_btn.click(
+ mark_correct,
+ [selected_card, results],
+ [results, correct_field, results_table],
+ )
+
+ incorrect_btn.click(mark_incorrect, [selected_card, results], [results, incorrect_field, results_table])
+
+ # set results tab to visible when correct or incorrect button is clicked
+ correct_btn.click(fn=toggle_results_tab, outputs=[results_tab])
+ incorrect_btn.click(fn=toggle_results_tab, outputs=[results_tab])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_flipper/run.ipynb b/demo/blocks_flipper/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8fc016f28250afcf9057cdbda247ae65d32d258f
--- /dev/null
+++ b/demo/blocks_flipper/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_flipper"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "import gradio as gr\n", "\n", "\n", "def flip_text(x):\n", " return x[::-1]\n", "\n", "\n", "def flip_image(x):\n", " return np.fliplr(x)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Flip text or image files using this demo.\")\n", " with gr.Tab(\"Flip Text\"):\n", " text_input = gr.Textbox()\n", " text_output = gr.Textbox()\n", " text_button = gr.Button(\"Flip\")\n", " with gr.Tab(\"Flip Image\"):\n", " with gr.Row():\n", " image_input = gr.Image()\n", " image_output = gr.Image()\n", " image_button = gr.Button(\"Flip\")\n", "\n", " with gr.Accordion(\"Open for More!\"):\n", " gr.Markdown(\"Look at me...\")\n", "\n", " text_button.click(flip_text, inputs=text_input, outputs=text_output)\n", " image_button.click(flip_image, inputs=image_input, outputs=image_output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_flipper/run.py b/demo/blocks_flipper/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..29753508d941d26ccd5bc3951e9a3bf126878842
--- /dev/null
+++ b/demo/blocks_flipper/run.py
@@ -0,0 +1,32 @@
+import numpy as np
+import gradio as gr
+
+
+def flip_text(x):
+ return x[::-1]
+
+
+def flip_image(x):
+ return np.fliplr(x)
+
+
+with gr.Blocks() as demo:
+ gr.Markdown("Flip text or image files using this demo.")
+ with gr.Tab("Flip Text"):
+ text_input = gr.Textbox()
+ text_output = gr.Textbox()
+ text_button = gr.Button("Flip")
+ with gr.Tab("Flip Image"):
+ with gr.Row():
+ image_input = gr.Image()
+ image_output = gr.Image()
+ image_button = gr.Button("Flip")
+
+ with gr.Accordion("Open for More!"):
+ gr.Markdown("Look at me...")
+
+ text_button.click(flip_text, inputs=text_input, outputs=text_output)
+ image_button.click(flip_image, inputs=image_input, outputs=image_output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_flipper/screenshot.gif b/demo/blocks_flipper/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..84562331deddcbec95680423b5eb1c1129d482e3
--- /dev/null
+++ b/demo/blocks_flipper/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:21b814857d694e576b3e6db4cabe069f56e7386f7a1fabc6be81431c7176d700
+size 1108151
diff --git a/demo/blocks_form/run.ipynb b/demo/blocks_form/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5980197cc147031e6d90a44a959fbaefdb5f2ce5
--- /dev/null
+++ b/demo/blocks_form/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_form"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " error_box = gr.Textbox(label=\"Error\", visible=False)\n", "\n", " name_box = gr.Textbox(label=\"Name\")\n", " age_box = gr.Number(label=\"Age\", minimum=0, maximum=100)\n", " symptoms_box = gr.CheckboxGroup([\"Cough\", \"Fever\", \"Runny Nose\"])\n", " submit_btn = gr.Button(\"Submit\")\n", "\n", " with gr.Column(visible=False) as output_col:\n", " diagnosis_box = gr.Textbox(label=\"Diagnosis\")\n", " patient_summary_box = gr.Textbox(label=\"Patient Summary\")\n", "\n", " def submit(name, age, symptoms):\n", " if len(name) == 0:\n", " return {error_box: gr.Textbox(value=\"Enter name\", visible=True)}\n", " return {\n", " output_col: gr.Column(visible=True),\n", " diagnosis_box: \"covid\" if \"Cough\" in symptoms else \"flu\",\n", " patient_summary_box: f\"{name}, {age} y/o\",\n", " }\n", "\n", " submit_btn.click(\n", " submit,\n", " [name_box, age_box, symptoms_box],\n", " [error_box, diagnosis_box, patient_summary_box, output_col],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_form/run.py b/demo/blocks_form/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..956083cb0840909d890807f126ee643b05da6099
--- /dev/null
+++ b/demo/blocks_form/run.py
@@ -0,0 +1,31 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ error_box = gr.Textbox(label="Error", visible=False)
+
+ name_box = gr.Textbox(label="Name")
+ age_box = gr.Number(label="Age", minimum=0, maximum=100)
+ symptoms_box = gr.CheckboxGroup(["Cough", "Fever", "Runny Nose"])
+ submit_btn = gr.Button("Submit")
+
+ with gr.Column(visible=False) as output_col:
+ diagnosis_box = gr.Textbox(label="Diagnosis")
+ patient_summary_box = gr.Textbox(label="Patient Summary")
+
+ def submit(name, age, symptoms):
+ if len(name) == 0:
+ return {error_box: gr.Textbox(value="Enter name", visible=True)}
+ return {
+ output_col: gr.Column(visible=True),
+ diagnosis_box: "covid" if "Cough" in symptoms else "flu",
+ patient_summary_box: f"{name}, {age} y/o",
+ }
+
+ submit_btn.click(
+ submit,
+ [name_box, age_box, symptoms_box],
+ [error_box, diagnosis_box, patient_summary_box, output_col],
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_gpt/run.ipynb b/demo/blocks_gpt/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..93002058703506c52303d4e7daf3205a47c16497
--- /dev/null
+++ b/demo/blocks_gpt/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_gpt"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "api = gr.load(\"huggingface/gpt2-xl\")\n", "\n", "def complete_with_gpt(text):\n", " # Use the last 50 characters of the text as context\n", " return text[:-50] + api(text[-50:])\n", "\n", "with gr.Blocks() as demo:\n", " textbox = gr.Textbox(placeholder=\"Type here and press enter...\", lines=4)\n", " btn = gr.Button(\"Generate\")\n", " \n", " btn.click(complete_with_gpt, textbox, textbox)\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_gpt/run.py b/demo/blocks_gpt/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb1e4e476befd084d61589faf9da0f5d34ae60b5
--- /dev/null
+++ b/demo/blocks_gpt/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+api = gr.load("huggingface/gpt2-xl")
+
+def complete_with_gpt(text):
+ # Use the last 50 characters of the text as context
+ return text[:-50] + api(text[-50:])
+
+with gr.Blocks() as demo:
+ textbox = gr.Textbox(placeholder="Type here and press enter...", lines=4)
+ btn = gr.Button("Generate")
+
+ btn.click(complete_with_gpt, textbox, textbox)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_group/run.ipynb b/demo/blocks_group/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..15b658417cbf526d5be9a42d01b63c200c4b16a9
--- /dev/null
+++ b/demo/blocks_group/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_group"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name):\n", " return \"Hello \" + name + \"!\"\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"### This is a couple of elements without any gr.Group. Form elements naturally group together anyway.\")\n", " gr.Textbox(\"A\")\n", " gr.Number(3)\n", " gr.Button()\n", " gr.Image()\n", " gr.Slider()\n", "\n", " gr.Markdown(\"### This is the same set put in a gr.Group.\")\n", " with gr.Group():\n", " gr.Textbox(\"A\")\n", " gr.Number(3)\n", " gr.Button()\n", " gr.Image()\n", " gr.Slider()\n", "\n", " gr.Markdown(\"### Now in a Row, no group.\")\n", " with gr.Row():\n", " gr.Textbox(\"A\")\n", " gr.Number(3)\n", " gr.Button()\n", " gr.Image()\n", " gr.Slider()\n", "\n", " gr.Markdown(\"### Now in a Row in a group.\")\n", " with gr.Group():\n", " with gr.Row():\n", " gr.Textbox(\"A\")\n", " gr.Number(3)\n", " gr.Button()\n", " gr.Image()\n", " gr.Slider()\n", "\n", " gr.Markdown(\"### Several rows grouped together.\")\n", " with gr.Group():\n", " with gr.Row():\n", " gr.Textbox(\"A\")\n", " gr.Number(3)\n", " gr.Button()\n", " with gr.Row():\n", " gr.Image()\n", " gr.Audio()\n", "\n", " gr.Markdown(\"### Several columns grouped together. If columns are uneven, there is a gray group background.\")\n", " with gr.Group():\n", " with gr.Row():\n", " with gr.Column():\n", " name = gr.Textbox(label=\"Name\")\n", " btn = gr.Button(\"Hello\")\n", " gr.Dropdown([\"a\", \"b\", \"c\"], interactive=True)\n", " gr.Number()\n", " gr.Textbox()\n", " with gr.Column():\n", " gr.Image()\n", " gr.Dropdown([\"a\", \"b\", \"c\"], interactive=True)\n", " with gr.Row():\n", " gr.Number(scale=2)\n", " gr.Textbox()\n", "\n", " gr.Markdown(\"### container=False removes label, padding, and block border, placing elements 'directly' on background.\")\n", " gr.Radio([1,2,3], container=False)\n", " gr.Textbox(container=False)\n", " gr.Image(\"https://picsum.photos/id/237/200/300\", container=False, height=200)\n", "\n", " gr.Markdown(\"### Textbox, Dropdown, and Number input boxes takes up full space when within a group without a container.\")\n", "\n", "\n", " with gr.Group():\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(show_label=False, container=False)\n", " greet_btn = gr.Button(\"Greet\")\n", " with gr.Row():\n", " gr.Dropdown([\"a\", \"b\", \"c\"], interactive=True, container=False)\n", " gr.Textbox(container=False)\n", " gr.Number(container=False)\n", " gr.Image(height=100)\n", " greet_btn.click(fn=greet, inputs=name, outputs=output, api_name=\"greet\")\n", "\n", "\n", " gr.Markdown(\"### More examples\")\n", "\n", " with gr.Group():\n", " gr.Chatbot()\n", " with gr.Row():\n", " name = gr.Textbox(label=\"Prompot\", container=False)\n", " go = gr.Button(\"go\", scale=0)\n", "\n", " with gr.Column():\n", " gr.Radio([1,2,3], container=False)\n", " gr.Slider(0, 20, container=False)\n", "\n", " with gr.Group():\n", " with gr.Row():\n", " gr.Dropdown([\"a\", \"b\", \"c\"], interactive=True, container=False, elem_id=\"here2\")\n", " gr.Number(container=False)\n", " gr.Textbox(container=False)\n", "\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Dropdown([\"a\", \"b\", \"c\"], interactive=True, container=False, elem_id=\"here2\")\n", " with gr.Column():\n", " gr.Number(container=False)\n", " with gr.Column():\n", " gr.Textbox(container=False)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_group/run.py b/demo/blocks_group/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a5c5485891417c55d20c64f27ca751a170c93e5f
--- /dev/null
+++ b/demo/blocks_group/run.py
@@ -0,0 +1,113 @@
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+with gr.Blocks() as demo:
+ gr.Markdown("### This is a couple of elements without any gr.Group. Form elements naturally group together anyway.")
+ gr.Textbox("A")
+ gr.Number(3)
+ gr.Button()
+ gr.Image()
+ gr.Slider()
+
+ gr.Markdown("### This is the same set put in a gr.Group.")
+ with gr.Group():
+ gr.Textbox("A")
+ gr.Number(3)
+ gr.Button()
+ gr.Image()
+ gr.Slider()
+
+ gr.Markdown("### Now in a Row, no group.")
+ with gr.Row():
+ gr.Textbox("A")
+ gr.Number(3)
+ gr.Button()
+ gr.Image()
+ gr.Slider()
+
+ gr.Markdown("### Now in a Row in a group.")
+ with gr.Group():
+ with gr.Row():
+ gr.Textbox("A")
+ gr.Number(3)
+ gr.Button()
+ gr.Image()
+ gr.Slider()
+
+ gr.Markdown("### Several rows grouped together.")
+ with gr.Group():
+ with gr.Row():
+ gr.Textbox("A")
+ gr.Number(3)
+ gr.Button()
+ with gr.Row():
+ gr.Image()
+ gr.Audio()
+
+ gr.Markdown("### Several columns grouped together. If columns are uneven, there is a gray group background.")
+ with gr.Group():
+ with gr.Row():
+ with gr.Column():
+ name = gr.Textbox(label="Name")
+ btn = gr.Button("Hello")
+ gr.Dropdown(["a", "b", "c"], interactive=True)
+ gr.Number()
+ gr.Textbox()
+ with gr.Column():
+ gr.Image()
+ gr.Dropdown(["a", "b", "c"], interactive=True)
+ with gr.Row():
+ gr.Number(scale=2)
+ gr.Textbox()
+
+ gr.Markdown("### container=False removes label, padding, and block border, placing elements 'directly' on background.")
+ gr.Radio([1,2,3], container=False)
+ gr.Textbox(container=False)
+ gr.Image("https://picsum.photos/id/237/200/300", container=False, height=200)
+
+ gr.Markdown("### Textbox, Dropdown, and Number input boxes takes up full space when within a group without a container.")
+
+
+ with gr.Group():
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(show_label=False, container=False)
+ greet_btn = gr.Button("Greet")
+ with gr.Row():
+ gr.Dropdown(["a", "b", "c"], interactive=True, container=False)
+ gr.Textbox(container=False)
+ gr.Number(container=False)
+ gr.Image(height=100)
+ greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
+
+
+ gr.Markdown("### More examples")
+
+ with gr.Group():
+ gr.Chatbot()
+ with gr.Row():
+ name = gr.Textbox(label="Prompot", container=False)
+ go = gr.Button("go", scale=0)
+
+ with gr.Column():
+ gr.Radio([1,2,3], container=False)
+ gr.Slider(0, 20, container=False)
+
+ with gr.Group():
+ with gr.Row():
+ gr.Dropdown(["a", "b", "c"], interactive=True, container=False, elem_id="here2")
+ gr.Number(container=False)
+ gr.Textbox(container=False)
+
+ with gr.Row():
+ with gr.Column():
+ gr.Dropdown(["a", "b", "c"], interactive=True, container=False, elem_id="here2")
+ with gr.Column():
+ gr.Number(container=False)
+ with gr.Column():
+ gr.Textbox(container=False)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_hello/run.ipynb b/demo/blocks_hello/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e7ac92072f123b68d517a4007502b0ab65d05a6e
--- /dev/null
+++ b/demo/blocks_hello/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_hello"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def welcome(name):\n", " return f\"Welcome to Gradio, {name}!\"\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Hello World!\n", " Start typing below to see the output.\n", " \"\"\")\n", " inp = gr.Textbox(placeholder=\"What is your name?\")\n", " out = gr.Textbox()\n", " inp.change(welcome, inp, out)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_hello/run.py b/demo/blocks_hello/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d416ee4ee0594fbd7c2ab1035fe2a1dc399d903
--- /dev/null
+++ b/demo/blocks_hello/run.py
@@ -0,0 +1,17 @@
+import gradio as gr
+
+def welcome(name):
+ return f"Welcome to Gradio, {name}!"
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+ # Hello World!
+ Start typing below to see the output.
+ """)
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+ inp.change(welcome, inp, out)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_inputs/lion.jpg b/demo/blocks_inputs/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/blocks_inputs/lion.jpg differ
diff --git a/demo/blocks_inputs/run.ipynb b/demo/blocks_inputs/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..93b3d9d876954c5e6099c3ff37414d9d8dae9296
--- /dev/null
+++ b/demo/blocks_inputs/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_inputs"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_inputs/lion.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def combine(a, b):\n", " return a + \" \" + b\n", "\n", "\n", "def mirror(x):\n", " return x\n", "\n", "\n", "with gr.Blocks() as demo:\n", "\n", " txt = gr.Textbox(label=\"Input\", lines=2)\n", " txt_2 = gr.Textbox(label=\"Input 2\")\n", " txt_3 = gr.Textbox(value=\"\", label=\"Output\")\n", " btn = gr.Button(value=\"Submit\")\n", " btn.click(combine, inputs=[txt, txt_2], outputs=[txt_3])\n", "\n", " with gr.Row():\n", " im = gr.Image()\n", " im_2 = gr.Image()\n", "\n", " btn = gr.Button(value=\"Mirror Image\")\n", " btn.click(mirror, inputs=[im], outputs=[im_2])\n", "\n", " gr.Markdown(\"## Text Examples\")\n", " gr.Examples(\n", " [[\"hi\", \"Adam\"], [\"hello\", \"Eve\"]],\n", " [txt, txt_2],\n", " txt_3,\n", " combine,\n", " cache_examples=True,\n", " )\n", " gr.Markdown(\"## Image Examples\")\n", " gr.Examples(\n", " examples=[os.path.join(os.path.abspath(''), \"lion.jpg\")],\n", " inputs=im,\n", " outputs=im_2,\n", " fn=mirror,\n", " cache_examples=True,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_inputs/run.py b/demo/blocks_inputs/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b259312d8ecab627ab77007ddb964da528438921
--- /dev/null
+++ b/demo/blocks_inputs/run.py
@@ -0,0 +1,46 @@
+import gradio as gr
+import os
+
+
+def combine(a, b):
+ return a + " " + b
+
+
+def mirror(x):
+ return x
+
+
+with gr.Blocks() as demo:
+
+ txt = gr.Textbox(label="Input", lines=2)
+ txt_2 = gr.Textbox(label="Input 2")
+ txt_3 = gr.Textbox(value="", label="Output")
+ btn = gr.Button(value="Submit")
+ btn.click(combine, inputs=[txt, txt_2], outputs=[txt_3])
+
+ with gr.Row():
+ im = gr.Image()
+ im_2 = gr.Image()
+
+ btn = gr.Button(value="Mirror Image")
+ btn.click(mirror, inputs=[im], outputs=[im_2])
+
+ gr.Markdown("## Text Examples")
+ gr.Examples(
+ [["hi", "Adam"], ["hello", "Eve"]],
+ [txt, txt_2],
+ txt_3,
+ combine,
+ cache_examples=True,
+ )
+ gr.Markdown("## Image Examples")
+ gr.Examples(
+ examples=[os.path.join(os.path.dirname(__file__), "lion.jpg")],
+ inputs=im,
+ outputs=im_2,
+ fn=mirror,
+ cache_examples=True,
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_joined/files/cheetah1.jpg b/demo/blocks_joined/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/blocks_joined/files/cheetah1.jpg differ
diff --git a/demo/blocks_joined/run.ipynb b/demo/blocks_joined/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9158608ec53b612729bc25149659a6145864eb69
--- /dev/null
+++ b/demo/blocks_joined/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_joined"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/blocks_joined/files/cheetah1.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["from time import sleep\n", "import gradio as gr\n", "import os\n", "\n", "cheetah = os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\")\n", "\n", "\n", "def img(text):\n", " sleep(3)\n", " return [\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " cheetah,\n", " ]\n", "\n", "\n", "with gr.Blocks(css=\".container { max-width: 800px; margin: auto; }\") as demo:\n", " gr.Markdown(\"DALL\u00b7E mini \")\n", " gr.Markdown(\n", " \"DALL\u00b7E mini is an AI model that generates images from any prompt you give!\"\n", " )\n", " with gr.Group():\n", " with gr.Row(equal_height=True):\n", " text = gr.Textbox(\n", " label=\"Enter your prompt\",\n", " max_lines=1,\n", " container=False,\n", " )\n", " btn = gr.Button(\"Run\", scale=0)\n", " gallery = gr.Gallery(\n", " label=\"Generated images\",\n", " show_label=False,\n", " columns=(1, 3),\n", " height=\"auto\",\n", " )\n", " btn.click(img, inputs=text, outputs=gallery)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", "\n", "\n", "# margin = (TOP, RIGHT, BOTTOM, LEFT)\n", "# rounded = (TOPLEFT, TOPRIGHT, BOTTOMRIGHT, BOTTOMLEFT)\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_joined/run.py b/demo/blocks_joined/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba2d71e24fa9bf4a2484cc5b0a86153492744d92
--- /dev/null
+++ b/demo/blocks_joined/run.py
@@ -0,0 +1,50 @@
+from time import sleep
+import gradio as gr
+import os
+
+cheetah = os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg")
+
+
+def img(text):
+ sleep(3)
+ return [
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ cheetah,
+ ]
+
+
+with gr.Blocks(css=".container { max-width: 800px; margin: auto; }") as demo:
+ gr.Markdown("DALL·E mini ")
+ gr.Markdown(
+ "DALL·E mini is an AI model that generates images from any prompt you give!"
+ )
+ with gr.Group():
+ with gr.Row(equal_height=True):
+ text = gr.Textbox(
+ label="Enter your prompt",
+ max_lines=1,
+ container=False,
+ )
+ btn = gr.Button("Run", scale=0)
+ gallery = gr.Gallery(
+ label="Generated images",
+ show_label=False,
+ columns=(1, 3),
+ height="auto",
+ )
+ btn.click(img, inputs=text, outputs=gallery)
+
+
+if __name__ == "__main__":
+ demo.launch()
+
+
+# margin = (TOP, RIGHT, BOTTOM, LEFT)
+# rounded = (TOPLEFT, TOPRIGHT, BOTTOMRIGHT, BOTTOMLEFT)
diff --git a/demo/blocks_js_load/run.ipynb b/demo/blocks_js_load/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c4ec6babf6d29be9610988b7bb5683a1d4ff8bd1
--- /dev/null
+++ b/demo/blocks_js_load/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_js_load"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def welcome(name):\n", " return f\"Welcome to Gradio, {name}!\"\n", "\n", "js = \"\"\"\n", "function createGradioAnimation() {\n", " var container = document.createElement('div');\n", " container.id = 'gradio-animation';\n", " container.style.fontSize = '2em';\n", " container.style.fontWeight = 'bold';\n", " container.style.textAlign = 'center';\n", " container.style.marginBottom = '20px';\n", "\n", " var text = 'Welcome to Gradio!';\n", " for (var i = 0; i < text.length; i++) {\n", " (function(i){\n", " setTimeout(function(){\n", " var letter = document.createElement('span');\n", " letter.style.opacity = '0';\n", " letter.style.transition = 'opacity 0.5s';\n", " letter.innerText = text[i];\n", "\n", " container.appendChild(letter);\n", "\n", " setTimeout(function() {\n", " letter.style.opacity = '1';\n", " }, 50);\n", " }, i * 250);\n", " })(i);\n", " }\n", "\n", " var gradioContainer = document.querySelector('.gradio-container');\n", " gradioContainer.insertBefore(container, gradioContainer.firstChild);\n", "\n", " return 'Animation created';\n", "}\n", "\"\"\"\n", "with gr.Blocks(js=js) as demo:\n", " inp = gr.Textbox(placeholder=\"What is your name?\")\n", " out = gr.Textbox()\n", " inp.change(welcome, inp, out)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_js_load/run.py b/demo/blocks_js_load/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1c0335e9b20e15548c3dc6c23c8d2f5bdee4c8c
--- /dev/null
+++ b/demo/blocks_js_load/run.py
@@ -0,0 +1,45 @@
+import gradio as gr
+
+def welcome(name):
+ return f"Welcome to Gradio, {name}!"
+
+js = """
+function createGradioAnimation() {
+ var container = document.createElement('div');
+ container.id = 'gradio-animation';
+ container.style.fontSize = '2em';
+ container.style.fontWeight = 'bold';
+ container.style.textAlign = 'center';
+ container.style.marginBottom = '20px';
+
+ var text = 'Welcome to Gradio!';
+ for (var i = 0; i < text.length; i++) {
+ (function(i){
+ setTimeout(function(){
+ var letter = document.createElement('span');
+ letter.style.opacity = '0';
+ letter.style.transition = 'opacity 0.5s';
+ letter.innerText = text[i];
+
+ container.appendChild(letter);
+
+ setTimeout(function() {
+ letter.style.opacity = '1';
+ }, 50);
+ }, i * 250);
+ })(i);
+ }
+
+ var gradioContainer = document.querySelector('.gradio-container');
+ gradioContainer.insertBefore(container, gradioContainer.firstChild);
+
+ return 'Animation created';
+}
+"""
+with gr.Blocks(js=js) as demo:
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+ inp.change(welcome, inp, out)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_js_methods/run.ipynb b/demo/blocks_js_methods/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1a5195c09b6de1ce5d3510e0a47eb1d1aa1e1d65
--- /dev/null
+++ b/demo/blocks_js_methods/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_js_methods"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "blocks = gr.Blocks()\n", "\n", "with blocks as demo:\n", " subject = gr.Textbox(placeholder=\"subject\")\n", " verb = gr.Radio([\"ate\", \"loved\", \"hated\"])\n", " object = gr.Textbox(placeholder=\"object\")\n", "\n", " with gr.Row():\n", " btn = gr.Button(\"Create sentence.\")\n", " reverse_btn = gr.Button(\"Reverse sentence.\")\n", " foo_bar_btn = gr.Button(\"Append foo\")\n", " reverse_then_to_the_server_btn = gr.Button(\n", " \"Reverse sentence and send to server.\"\n", " )\n", "\n", " def sentence_maker(w1, w2, w3):\n", " return f\"{w1} {w2} {w3}\"\n", "\n", " output1 = gr.Textbox(label=\"output 1\")\n", " output2 = gr.Textbox(label=\"verb\")\n", " output3 = gr.Textbox(label=\"verb reversed\")\n", " output4 = gr.Textbox(label=\"front end process and then send to backend\")\n", "\n", " btn.click(sentence_maker, [subject, verb, object], output1)\n", " reverse_btn.click(\n", " None, [subject, verb, object], output2, js=\"(s, v, o) => o + ' ' + v + ' ' + s\"\n", " )\n", " verb.change(lambda x: x, verb, output3, js=\"(x) => [...x].reverse().join('')\")\n", " foo_bar_btn.click(None, [], subject, js=\"(x) => x + ' foo'\")\n", "\n", " reverse_then_to_the_server_btn.click(\n", " sentence_maker,\n", " [subject, verb, object],\n", " output4,\n", " js=\"(s, v, o) => [s, v, o].map(x => [...x].reverse().join(''))\",\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_js_methods/run.py b/demo/blocks_js_methods/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2abb2d9d3bca4114009da9ae61ef1ebfc347da81
--- /dev/null
+++ b/demo/blocks_js_methods/run.py
@@ -0,0 +1,41 @@
+import gradio as gr
+
+blocks = gr.Blocks()
+
+with blocks as demo:
+ subject = gr.Textbox(placeholder="subject")
+ verb = gr.Radio(["ate", "loved", "hated"])
+ object = gr.Textbox(placeholder="object")
+
+ with gr.Row():
+ btn = gr.Button("Create sentence.")
+ reverse_btn = gr.Button("Reverse sentence.")
+ foo_bar_btn = gr.Button("Append foo")
+ reverse_then_to_the_server_btn = gr.Button(
+ "Reverse sentence and send to server."
+ )
+
+ def sentence_maker(w1, w2, w3):
+ return f"{w1} {w2} {w3}"
+
+ output1 = gr.Textbox(label="output 1")
+ output2 = gr.Textbox(label="verb")
+ output3 = gr.Textbox(label="verb reversed")
+ output4 = gr.Textbox(label="front end process and then send to backend")
+
+ btn.click(sentence_maker, [subject, verb, object], output1)
+ reverse_btn.click(
+ None, [subject, verb, object], output2, js="(s, v, o) => o + ' ' + v + ' ' + s"
+ )
+ verb.change(lambda x: x, verb, output3, js="(x) => [...x].reverse().join('')")
+ foo_bar_btn.click(None, [], subject, js="(x) => x + ' foo'")
+
+ reverse_then_to_the_server_btn.click(
+ sentence_maker,
+ [subject, verb, object],
+ output4,
+ js="(s, v, o) => [s, v, o].map(x => [...x].reverse().join(''))",
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_kinematics/run.ipynb b/demo/blocks_kinematics/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dfc050ca61ce4dce7751edda7e0272658f450a9e
--- /dev/null
+++ b/demo/blocks_kinematics/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_kinematics"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import pandas as pd\n", "import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def plot(v, a):\n", " g = 9.81\n", " theta = a / 180 * 3.14\n", " tmax = ((2 * v) * np.sin(theta)) / g\n", " timemat = tmax * np.linspace(0, 1, 40)\n", "\n", " x = (v * timemat) * np.cos(theta)\n", " y = ((v * timemat) * np.sin(theta)) - ((0.5 * g) * (timemat**2))\n", " df = pd.DataFrame({\"x\": x, \"y\": y})\n", " return df\n", "\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " gr.Markdown(\n", " r\"Let's do some kinematics! Choose the speed and angle to see the trajectory. Remember that the range $R = v_0^2 \\cdot \\frac{\\sin(2\\theta)}{g}$\"\n", " )\n", "\n", " with gr.Row():\n", " speed = gr.Slider(1, 30, 25, label=\"Speed\")\n", " angle = gr.Slider(0, 90, 45, label=\"Angle\")\n", " output = gr.LinePlot(\n", " x=\"x\",\n", " y=\"y\",\n", " overlay_point=True,\n", " tooltip=[\"x\", \"y\"],\n", " x_lim=[0, 100],\n", " y_lim=[0, 60],\n", " width=350,\n", " height=300,\n", " )\n", " btn = gr.Button(value=\"Run\")\n", " btn.click(plot, [speed, angle], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_kinematics/run.py b/demo/blocks_kinematics/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..513eb4d5ed161be9c036fcd71f2eb217da01249c
--- /dev/null
+++ b/demo/blocks_kinematics/run.py
@@ -0,0 +1,43 @@
+import pandas as pd
+import numpy as np
+
+import gradio as gr
+
+
+def plot(v, a):
+ g = 9.81
+ theta = a / 180 * 3.14
+ tmax = ((2 * v) * np.sin(theta)) / g
+ timemat = tmax * np.linspace(0, 1, 40)
+
+ x = (v * timemat) * np.cos(theta)
+ y = ((v * timemat) * np.sin(theta)) - ((0.5 * g) * (timemat**2))
+ df = pd.DataFrame({"x": x, "y": y})
+ return df
+
+
+demo = gr.Blocks()
+
+with demo:
+ gr.Markdown(
+ r"Let's do some kinematics! Choose the speed and angle to see the trajectory. Remember that the range $R = v_0^2 \cdot \frac{\sin(2\theta)}{g}$"
+ )
+
+ with gr.Row():
+ speed = gr.Slider(1, 30, 25, label="Speed")
+ angle = gr.Slider(0, 90, 45, label="Angle")
+ output = gr.LinePlot(
+ x="x",
+ y="y",
+ overlay_point=True,
+ tooltip=["x", "y"],
+ x_lim=[0, 100],
+ y_lim=[0, 60],
+ width=350,
+ height=300,
+ )
+ btn = gr.Button(value="Run")
+ btn.click(plot, [speed, angle], output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_kitchen_sink/run.ipynb b/demo/blocks_kitchen_sink/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..19ebc14aaa1f184b9909625ebc83ed70e4d0d130
--- /dev/null
+++ b/demo/blocks_kitchen_sink/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_kitchen_sink"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "from os.path import abspath, join, pardir\n", "\n", "KS_FILES = abspath(join(__file__, pardir, pardir, \"kitchen_sink\", \"files\"))\n", "\n", "base_theme = gr.themes.Base()\n", "default_theme = gr.themes.Default()\n", "monochrome_theme = gr.themes.Monochrome()\n", "soft_theme = gr.themes.Soft()\n", "glass_theme = gr.themes.Glass()\n", "\n", "with gr.Blocks(theme=base_theme) as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Blocks Kitchen Sink\n", " This is a demo of most Gradio features. Test all themes and toggle dark mode\n", " ## Elements\n", " - Use of Rows, Columns, Tabs, and Accordion\n", " - Use of Form elements: Textbox, Dropdown, Checkbox, Radio, Slider\n", " ## Other\n", " Other stuff\n", " - Buttons of variants: \"primary\", \"secondary\", \"stop\"\n", " - Embedded interface\n", " - Custom progress bar\n", " \"\"\"\n", " )\n", " toggle_dark = gr.Button(\"Toggle Dark\", scale=0)\n", " toggle_dark.click(\n", " None,\n", " js=\"\"\"\n", " () => { \n", " document.body.classList.toggle('dark');\n", " }\n", " \"\"\",\n", " )\n", " theme_selector = gr.Radio(\n", " [\"Base\", \"Default\", \"Monochrome\", \"Soft\", \"Glass\"],\n", " value=\"Base\",\n", " label=\"Theme\",\n", " )\n", " theme_selector.change(\n", " None,\n", " theme_selector,\n", " None,\n", " js=f\"\"\"\n", " (theme) => {{\n", " if (!document.querySelector('.theme-css')) {{\n", " var theme_elem = document.createElement('style');\n", " theme_elem.classList.add('theme-css');\n", " document.head.appendChild(theme_elem);\n", "\n", " var link_elem = document.createElement('link');\n", " link_elem.classList.add('link-css');\n", " link_elem.rel = 'stylesheet';\n", " document.head.appendChild(link_elem);\n", " }} else {{\n", " var theme_elem = document.querySelector('.theme-css');\n", " var link_elem = document.querySelector('.link-css');\n", " }}\n", " if (theme == \"Base\") {{\n", " var theme_css = `{base_theme._get_theme_css()}`;\n", " var link_css = `{base_theme._stylesheets[0]}`;\n", " }} else if (theme == \"Default\") {{\n", " var theme_css = `{default_theme._get_theme_css()}`;\n", " var link_css = `{default_theme._stylesheets[0]}`;\n", " }} else if (theme == \"Monochrome\") {{\n", " var theme_css = `{monochrome_theme._get_theme_css()}`;\n", " var link_css = `{monochrome_theme._stylesheets[0]}`;\n", " }} else if (theme == \"Soft\") {{\n", " var theme_css = `{soft_theme._get_theme_css()}`;\n", " var link_css = `{soft_theme._stylesheets[0]}`;\n", " }} else if (theme == \"Glass\") {{\n", " var theme_css = `{glass_theme._get_theme_css()}`;\n", " var link_css = `{glass_theme._stylesheets[0]}`;\n", " }}\n", " theme_elem.innerHTML = theme_css;\n", " link_elem.href = link_css;\n", " }}\n", " \"\"\",\n", " )\n", "\n", " name = gr.Textbox(\n", " label=\"Name (select)\",\n", " info=\"Full name, including middle name. No special characters.\",\n", " placeholder=\"John Doe\",\n", " value=\"John Doe\",\n", " interactive=True,\n", " )\n", "\n", " with gr.Row():\n", " slider1 = gr.Slider(label=\"Slider 1\")\n", " slider2 = gr.Slider(label=\"Slider 2\")\n", " checkboxes = gr.CheckboxGroup([\"A\", \"B\", \"C\"], label=\"Checkbox Group (select)\")\n", "\n", " with gr.Row():\n", " with gr.Column(variant=\"panel\", scale=1):\n", " gr.Markdown(\"## Panel 1\")\n", " radio = gr.Radio(\n", " [\"A\", \"B\", \"C\"],\n", " label=\"Radio (select)\",\n", " info=\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\",\n", " )\n", " drop = gr.Dropdown([\"Option 1\", \"Option 2\", \"Option 3\"], show_label=False)\n", " drop_2 = gr.Dropdown(\n", " [\"Option A\", \"Option B\", \"Option C\"],\n", " multiselect=True,\n", " value=[\"Option A\"],\n", " label=\"Dropdown (select)\",\n", " interactive=True,\n", " )\n", " check = gr.Checkbox(label=\"Go\")\n", " with gr.Column(variant=\"panel\", scale=2):\n", " img = gr.Image(\n", " \"https://picsum.photos/536/354\",\n", " label=\"Image\",\n", " height=320,\n", " )\n", " with gr.Row():\n", " go_btn = gr.Button(\"Go\", label=\"Primary Button\", variant=\"primary\")\n", " clear_btn = gr.Button(\n", " \"Clear\", label=\"Secondary Button\", variant=\"secondary\"\n", " )\n", "\n", " def go(*args):\n", " time.sleep(3)\n", " return \"https://i.ibb.co/6BgKdSj/groot.jpg\"\n", "\n", " go_btn.click(go, [radio, drop, drop_2, check, name], img, api_name=\"go\")\n", "\n", " def clear():\n", " time.sleep(0.2)\n", " return None\n", "\n", " clear_btn.click(clear, None, img)\n", "\n", " with gr.Row():\n", " btn1 = gr.Button(\"Button 1\", size=\"sm\")\n", " btn2 = gr.UploadButton(size=\"sm\")\n", " stop_btn = gr.Button(\n", " \"Stop\", label=\"Stop Button\", variant=\"stop\", size=\"sm\"\n", " )\n", "\n", " gr.Examples(\n", " examples=[join(KS_FILES, \"lion.jpg\"), join(KS_FILES, \"tower.jpg\")],\n", " inputs=img,\n", " )\n", "\n", " gr.Examples(\n", " examples=[\n", " [\"A\", \"Option 1\", [\"Option B\"], True, join(KS_FILES, \"lion.jpg\")],\n", " [\n", " \"B\",\n", " \"Option 2\",\n", " [\"Option B\", \"Option C\"],\n", " False,\n", " join(KS_FILES, \"tower.jpg\"),\n", " ],\n", " ],\n", " inputs=[radio, drop, drop_2, check, img],\n", " label=\"Examples (select)\",\n", " )\n", "\n", " gr.Markdown(\"## Media Files\")\n", "\n", " with gr.Tabs() as tabs:\n", " with gr.Tab(\"Audio\"):\n", " with gr.Row():\n", " gr.Audio()\n", " gr.Audio(sources=[\"microphone\"])\n", " gr.Audio(join(KS_FILES, \"cantina.wav\"))\n", " with gr.Tab(\"Other\"):\n", " # gr.Image(source=\"webcam\")\n", " gr.HTML(\n", " \"
\"\n", " )\n", " with gr.Row():\n", " dataframe = gr.Dataframe(\n", " value=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], label=\"Dataframe (select)\"\n", " )\n", " gr.JSON(\n", " value={\"a\": 1, \"b\": 2, \"c\": {\"test\": \"a\", \"test2\": [1, 2, 3]}}, label=\"JSON\"\n", " )\n", " label = gr.Label(\n", " value={\"cat\": 0.7, \"dog\": 0.2, \"fish\": 0.1}, label=\"Label (select)\"\n", " )\n", " file = gr.File(label=\"File (select)\")\n", " with gr.Row():\n", " gr.ColorPicker()\n", " gr.Video(join(KS_FILES, \"world.mp4\"))\n", " gallery = gr.Gallery(\n", " [\n", " (join(KS_FILES, \"lion.jpg\"), \"lion\"),\n", " (join(KS_FILES, \"logo.png\"), \"logo\"),\n", " (join(KS_FILES, \"tower.jpg\"), \"tower\"),\n", " ],\n", " label=\"Gallery (select)\",\n", " )\n", "\n", " with gr.Row():\n", " with gr.Column(scale=2):\n", " highlight = gr.HighlightedText(\n", " [[\"The\", \"art\"], [\"dog\", \"noun\"], [\"is\", None], [\"fat\", \"adj\"]],\n", " label=\"Highlighted Text (select)\",\n", " )\n", " chatbot = gr.Chatbot([[\"Hello\", \"Hi\"]], label=\"Chatbot (select)\")\n", " chat_btn = gr.Button(\"Add messages\")\n", "\n", " def chat(history):\n", " time.sleep(2)\n", " yield [[\"How are you?\", \"I am good.\"]]\n", " time\n", "\n", " chat_btn.click(\n", " lambda history: history\n", " + [[\"How are you?\", \"I am good.\"]]\n", " + (time.sleep(2) or []),\n", " chatbot,\n", " chatbot,\n", " )\n", " with gr.Column(scale=1):\n", " with gr.Accordion(\"Select Info\"):\n", " gr.Markdown(\n", " \"Click on any part of any component with '(select)' in the label and see the SelectData data here.\"\n", " )\n", " select_index = gr.Textbox(label=\"Index\")\n", " select_value = gr.Textbox(label=\"Value\")\n", " select_selected = gr.Textbox(label=\"Selected\")\n", "\n", " selectables = [\n", " name,\n", " checkboxes,\n", " radio,\n", " drop_2,\n", " dataframe,\n", " label,\n", " file,\n", " highlight,\n", " chatbot,\n", " gallery,\n", " tabs,\n", " ]\n", "\n", " def select_data(evt: gr.SelectData):\n", " return [\n", " evt.index,\n", " evt.value,\n", " evt.selected,\n", " ]\n", "\n", " for selectable in selectables:\n", " selectable.select(\n", " select_data,\n", " None,\n", " [select_index, select_value, select_selected],\n", " )\n", "\n", " gr.Markdown(\"## Dataset Examples\")\n", "\n", " component_example_set = [\n", " (gr.Audio(render=False), join(KS_FILES, \"cantina.wav\")),\n", " (gr.Checkbox(render=False), True),\n", " (gr.CheckboxGroup(render=False, choices=[\"A\", \"B\"]), [\"A\", \"B\"]),\n", " (gr.ColorPicker(render=False), \"#FF0000\"),\n", " (gr.Dataframe(render=False), [[1, 2, 3], [4, 5, 6]]),\n", " (gr.Dropdown(render=False), \"A\"),\n", " (gr.File(render=False), join(KS_FILES, \"lion.jpg\")),\n", " (gr.HTML(render=False), \"Test
\"),\n", " (gr.Image(render=False), join(KS_FILES, \"lion.jpg\")),\n", " (gr.Markdown(render=False), \"# Test\"),\n", " (gr.Number(render=False), 1),\n", " (gr.Radio(render=False), \"A\"),\n", " (gr.Slider(render=False), 1),\n", " (gr.Textbox(render=False), \"A\"),\n", " (gr.Video(render=False), join(KS_FILES, \"world.mp4\")),\n", " ]\n", " gr.Dataset(\n", " components=[c for c, _ in component_example_set],\n", " samples=[[e for _, e in component_example_set]],\n", " )\n", "\n", " with gr.Tabs():\n", " for c, e in component_example_set:\n", " with gr.Tab(c.__class__.__name__):\n", " gr.Dataset(components=[c], samples=[[e]] * 3)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch(allowed_paths=[KS_FILES])\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_kitchen_sink/run.py b/demo/blocks_kitchen_sink/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea264cf15a5c9bbffd054cfe0da56c185a08443f
--- /dev/null
+++ b/demo/blocks_kitchen_sink/run.py
@@ -0,0 +1,289 @@
+import gradio as gr
+import time
+from os.path import abspath, join, pardir
+
+KS_FILES = abspath(join(__file__, pardir, pardir, "kitchen_sink", "files"))
+
+base_theme = gr.themes.Base()
+default_theme = gr.themes.Default()
+monochrome_theme = gr.themes.Monochrome()
+soft_theme = gr.themes.Soft()
+glass_theme = gr.themes.Glass()
+
+with gr.Blocks(theme=base_theme) as demo:
+ gr.Markdown(
+ """
+ # Blocks Kitchen Sink
+ This is a demo of most Gradio features. Test all themes and toggle dark mode
+ ## Elements
+ - Use of Rows, Columns, Tabs, and Accordion
+ - Use of Form elements: Textbox, Dropdown, Checkbox, Radio, Slider
+ ## Other
+ Other stuff
+ - Buttons of variants: "primary", "secondary", "stop"
+ - Embedded interface
+ - Custom progress bar
+ """
+ )
+ toggle_dark = gr.Button("Toggle Dark", scale=0)
+ toggle_dark.click(
+ None,
+ js="""
+ () => {
+ document.body.classList.toggle('dark');
+ }
+ """,
+ )
+ theme_selector = gr.Radio(
+ ["Base", "Default", "Monochrome", "Soft", "Glass"],
+ value="Base",
+ label="Theme",
+ )
+ theme_selector.change(
+ None,
+ theme_selector,
+ None,
+ js=f"""
+ (theme) => {{
+ if (!document.querySelector('.theme-css')) {{
+ var theme_elem = document.createElement('style');
+ theme_elem.classList.add('theme-css');
+ document.head.appendChild(theme_elem);
+
+ var link_elem = document.createElement('link');
+ link_elem.classList.add('link-css');
+ link_elem.rel = 'stylesheet';
+ document.head.appendChild(link_elem);
+ }} else {{
+ var theme_elem = document.querySelector('.theme-css');
+ var link_elem = document.querySelector('.link-css');
+ }}
+ if (theme == "Base") {{
+ var theme_css = `{base_theme._get_theme_css()}`;
+ var link_css = `{base_theme._stylesheets[0]}`;
+ }} else if (theme == "Default") {{
+ var theme_css = `{default_theme._get_theme_css()}`;
+ var link_css = `{default_theme._stylesheets[0]}`;
+ }} else if (theme == "Monochrome") {{
+ var theme_css = `{monochrome_theme._get_theme_css()}`;
+ var link_css = `{monochrome_theme._stylesheets[0]}`;
+ }} else if (theme == "Soft") {{
+ var theme_css = `{soft_theme._get_theme_css()}`;
+ var link_css = `{soft_theme._stylesheets[0]}`;
+ }} else if (theme == "Glass") {{
+ var theme_css = `{glass_theme._get_theme_css()}`;
+ var link_css = `{glass_theme._stylesheets[0]}`;
+ }}
+ theme_elem.innerHTML = theme_css;
+ link_elem.href = link_css;
+ }}
+ """,
+ )
+
+ name = gr.Textbox(
+ label="Name (select)",
+ info="Full name, including middle name. No special characters.",
+ placeholder="John Doe",
+ value="John Doe",
+ interactive=True,
+ )
+
+ with gr.Row():
+ slider1 = gr.Slider(label="Slider 1")
+ slider2 = gr.Slider(label="Slider 2")
+ checkboxes = gr.CheckboxGroup(["A", "B", "C"], label="Checkbox Group (select)")
+
+ with gr.Row():
+ with gr.Column(variant="panel", scale=1):
+ gr.Markdown("## Panel 1")
+ radio = gr.Radio(
+ ["A", "B", "C"],
+ label="Radio (select)",
+ info="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
+ )
+ drop = gr.Dropdown(["Option 1", "Option 2", "Option 3"], show_label=False)
+ drop_2 = gr.Dropdown(
+ ["Option A", "Option B", "Option C"],
+ multiselect=True,
+ value=["Option A"],
+ label="Dropdown (select)",
+ interactive=True,
+ )
+ check = gr.Checkbox(label="Go")
+ with gr.Column(variant="panel", scale=2):
+ img = gr.Image(
+ "https://picsum.photos/536/354",
+ label="Image",
+ height=320,
+ )
+ with gr.Row():
+ go_btn = gr.Button("Go", label="Primary Button", variant="primary")
+ clear_btn = gr.Button(
+ "Clear", label="Secondary Button", variant="secondary"
+ )
+
+ def go(*args):
+ time.sleep(3)
+ return "https://i.ibb.co/6BgKdSj/groot.jpg"
+
+ go_btn.click(go, [radio, drop, drop_2, check, name], img, api_name="go")
+
+ def clear():
+ time.sleep(0.2)
+ return None
+
+ clear_btn.click(clear, None, img)
+
+ with gr.Row():
+ btn1 = gr.Button("Button 1", size="sm")
+ btn2 = gr.UploadButton(size="sm")
+ stop_btn = gr.Button(
+ "Stop", label="Stop Button", variant="stop", size="sm"
+ )
+
+ gr.Examples(
+ examples=[join(KS_FILES, "lion.jpg"), join(KS_FILES, "tower.jpg")],
+ inputs=img,
+ )
+
+ gr.Examples(
+ examples=[
+ ["A", "Option 1", ["Option B"], True, join(KS_FILES, "lion.jpg")],
+ [
+ "B",
+ "Option 2",
+ ["Option B", "Option C"],
+ False,
+ join(KS_FILES, "tower.jpg"),
+ ],
+ ],
+ inputs=[radio, drop, drop_2, check, img],
+ label="Examples (select)",
+ )
+
+ gr.Markdown("## Media Files")
+
+ with gr.Tabs() as tabs:
+ with gr.Tab("Audio"):
+ with gr.Row():
+ gr.Audio()
+ gr.Audio(sources=["microphone"])
+ gr.Audio(join(KS_FILES, "cantina.wav"))
+ with gr.Tab("Other"):
+ # gr.Image(source="webcam")
+ gr.HTML(
+ "
"
+ )
+ with gr.Row():
+ dataframe = gr.Dataframe(
+ value=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], label="Dataframe (select)"
+ )
+ gr.JSON(
+ value={"a": 1, "b": 2, "c": {"test": "a", "test2": [1, 2, 3]}}, label="JSON"
+ )
+ label = gr.Label(
+ value={"cat": 0.7, "dog": 0.2, "fish": 0.1}, label="Label (select)"
+ )
+ file = gr.File(label="File (select)")
+ with gr.Row():
+ gr.ColorPicker()
+ gr.Video(join(KS_FILES, "world.mp4"))
+ gallery = gr.Gallery(
+ [
+ (join(KS_FILES, "lion.jpg"), "lion"),
+ (join(KS_FILES, "logo.png"), "logo"),
+ (join(KS_FILES, "tower.jpg"), "tower"),
+ ],
+ label="Gallery (select)",
+ )
+
+ with gr.Row():
+ with gr.Column(scale=2):
+ highlight = gr.HighlightedText(
+ [["The", "art"], ["dog", "noun"], ["is", None], ["fat", "adj"]],
+ label="Highlighted Text (select)",
+ )
+ chatbot = gr.Chatbot([["Hello", "Hi"]], label="Chatbot (select)")
+ chat_btn = gr.Button("Add messages")
+
+ def chat(history):
+ time.sleep(2)
+ yield [["How are you?", "I am good."]]
+ time
+
+ chat_btn.click(
+ lambda history: history
+ + [["How are you?", "I am good."]]
+ + (time.sleep(2) or []),
+ chatbot,
+ chatbot,
+ )
+ with gr.Column(scale=1):
+ with gr.Accordion("Select Info"):
+ gr.Markdown(
+ "Click on any part of any component with '(select)' in the label and see the SelectData data here."
+ )
+ select_index = gr.Textbox(label="Index")
+ select_value = gr.Textbox(label="Value")
+ select_selected = gr.Textbox(label="Selected")
+
+ selectables = [
+ name,
+ checkboxes,
+ radio,
+ drop_2,
+ dataframe,
+ label,
+ file,
+ highlight,
+ chatbot,
+ gallery,
+ tabs,
+ ]
+
+ def select_data(evt: gr.SelectData):
+ return [
+ evt.index,
+ evt.value,
+ evt.selected,
+ ]
+
+ for selectable in selectables:
+ selectable.select(
+ select_data,
+ None,
+ [select_index, select_value, select_selected],
+ )
+
+ gr.Markdown("## Dataset Examples")
+
+ component_example_set = [
+ (gr.Audio(render=False), join(KS_FILES, "cantina.wav")),
+ (gr.Checkbox(render=False), True),
+ (gr.CheckboxGroup(render=False, choices=["A", "B"]), ["A", "B"]),
+ (gr.ColorPicker(render=False), "#FF0000"),
+ (gr.Dataframe(render=False), [[1, 2, 3], [4, 5, 6]]),
+ (gr.Dropdown(render=False), "A"),
+ (gr.File(render=False), join(KS_FILES, "lion.jpg")),
+ (gr.HTML(render=False), "Test
"),
+ (gr.Image(render=False), join(KS_FILES, "lion.jpg")),
+ (gr.Markdown(render=False), "# Test"),
+ (gr.Number(render=False), 1),
+ (gr.Radio(render=False), "A"),
+ (gr.Slider(render=False), 1),
+ (gr.Textbox(render=False), "A"),
+ (gr.Video(render=False), join(KS_FILES, "world.mp4")),
+ ]
+ gr.Dataset(
+ components=[c for c, _ in component_example_set],
+ samples=[[e for _, e in component_example_set]],
+ )
+
+ with gr.Tabs():
+ for c, e in component_example_set:
+ with gr.Tab(c.__class__.__name__):
+ gr.Dataset(components=[c], samples=[[e]] * 3)
+
+
+if __name__ == "__main__":
+ demo.launch(allowed_paths=[KS_FILES])
diff --git a/demo/blocks_layout/run.ipynb b/demo/blocks_layout/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..deef224dfb4132575a2a5fe9c18e7978cb742132
--- /dev/null
+++ b/demo/blocks_layout/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_layout"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " with gr.Row():\n", " gr.Image(interactive=True, scale=2)\n", " gr.Image()\n", " with gr.Row():\n", " gr.Textbox(label=\"Text\")\n", " gr.Number(label=\"Count\", scale=2)\n", " gr.Radio(choices=[\"One\", \"Two\"])\n", " with gr.Row():\n", " gr.Button(\"500\", scale=0, min_width=500)\n", " gr.Button(\"A\", scale=0)\n", " gr.Button(\"grow\")\n", " with gr.Row():\n", " gr.Textbox()\n", " gr.Textbox()\n", " gr.Button() \n", " with gr.Row():\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Textbox(label=\"Text\")\n", " gr.Number(label=\"Count\")\n", " gr.Radio(choices=[\"One\", \"Two\"])\n", " gr.Image()\n", " with gr.Column():\n", " gr.Image(interactive=True)\n", " gr.Image()\n", " gr.Image()\n", " gr.Textbox(label=\"Text\")\n", " gr.Number(label=\"Count\")\n", " gr.Radio(choices=[\"One\", \"Two\"])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_layout/run.py b/demo/blocks_layout/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a7f3660ffce75035d191274fecf3063f28b647d
--- /dev/null
+++ b/demo/blocks_layout/run.py
@@ -0,0 +1,39 @@
+import gradio as gr
+
+
+demo = gr.Blocks()
+
+with demo:
+ with gr.Row():
+ gr.Image(interactive=True, scale=2)
+ gr.Image()
+ with gr.Row():
+ gr.Textbox(label="Text")
+ gr.Number(label="Count", scale=2)
+ gr.Radio(choices=["One", "Two"])
+ with gr.Row():
+ gr.Button("500", scale=0, min_width=500)
+ gr.Button("A", scale=0)
+ gr.Button("grow")
+ with gr.Row():
+ gr.Textbox()
+ gr.Textbox()
+ gr.Button()
+ with gr.Row():
+ with gr.Row():
+ with gr.Column():
+ gr.Textbox(label="Text")
+ gr.Number(label="Count")
+ gr.Radio(choices=["One", "Two"])
+ gr.Image()
+ with gr.Column():
+ gr.Image(interactive=True)
+ gr.Image()
+ gr.Image()
+ gr.Textbox(label="Text")
+ gr.Number(label="Count")
+ gr.Radio(choices=["One", "Two"])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_multiple_event_triggers/requirements.txt b/demo/blocks_multiple_event_triggers/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5cb63bcc8c366f4abc569ed8ef379a90d4759ff4
--- /dev/null
+++ b/demo/blocks_multiple_event_triggers/requirements.txt
@@ -0,0 +1,2 @@
+plotly
+pypistats
\ No newline at end of file
diff --git a/demo/blocks_multiple_event_triggers/run.ipynb b/demo/blocks_multiple_event_triggers/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1ada4f02c5276bfb454f57e163052181e5af9d93
--- /dev/null
+++ b/demo/blocks_multiple_event_triggers/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_multiple_event_triggers"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly pypistats"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pypistats\n", "from datetime import date\n", "from dateutil.relativedelta import relativedelta\n", "import pandas as pd\n", "\n", "def get_plot(lib, time):\n", " data = pypistats.overall(lib, total=True, format=\"pandas\")\n", " data = data.groupby(\"category\").get_group(\"with_mirrors\").sort_values(\"date\")\n", " start_date = date.today() - relativedelta(months=int(time.split(\" \")[0]))\n", " data = data[(data['date'] > str(start_date))]\n", " data.date = pd.to_datetime(pd.to_datetime(data.date))\n", " return gr.LinePlot(value=data, x=\"date\", y=\"downloads\",\n", " tooltip=['date', 'downloads'],\n", " title=f\"Pypi downloads of {lib} over last {time}\",\n", " overlay_point=True,\n", " height=400,\n", " width=900)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " ## Pypi Download Stats \ud83d\udcc8\n", " See live download stats for all of Hugging Face's open-source libraries \ud83e\udd17\n", " \"\"\")\n", " with gr.Row():\n", " lib = gr.Dropdown([\"transformers\", \"datasets\", \"huggingface-hub\", \"gradio\", \"accelerate\"],\n", " value=\"gradio\", label=\"Library\")\n", " time = gr.Dropdown([\"3 months\", \"6 months\", \"9 months\", \"12 months\"],\n", " value=\"3 months\", label=\"Downloads over the last...\")\n", "\n", " plt = gr.LinePlot()\n", " # You can add multiple event triggers in 2 lines like this\n", " for event in [lib.change, time.change, demo.load]:\n", " event(get_plot, [lib, time], [plt])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_multiple_event_triggers/run.py b/demo/blocks_multiple_event_triggers/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a8340d8f760e90b0ce571c751cc2c98813e1dbca
--- /dev/null
+++ b/demo/blocks_multiple_event_triggers/run.py
@@ -0,0 +1,39 @@
+import gradio as gr
+import pypistats
+from datetime import date
+from dateutil.relativedelta import relativedelta
+import pandas as pd
+
+def get_plot(lib, time):
+ data = pypistats.overall(lib, total=True, format="pandas")
+ data = data.groupby("category").get_group("with_mirrors").sort_values("date")
+ start_date = date.today() - relativedelta(months=int(time.split(" ")[0]))
+ data = data[(data['date'] > str(start_date))]
+ data.date = pd.to_datetime(pd.to_datetime(data.date))
+ return gr.LinePlot(value=data, x="date", y="downloads",
+ tooltip=['date', 'downloads'],
+ title=f"Pypi downloads of {lib} over last {time}",
+ overlay_point=True,
+ height=400,
+ width=900)
+
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+ ## Pypi Download Stats 📈
+ See live download stats for all of Hugging Face's open-source libraries 🤗
+ """)
+ with gr.Row():
+ lib = gr.Dropdown(["transformers", "datasets", "huggingface-hub", "gradio", "accelerate"],
+ value="gradio", label="Library")
+ time = gr.Dropdown(["3 months", "6 months", "9 months", "12 months"],
+ value="3 months", label="Downloads over the last...")
+
+ plt = gr.LinePlot()
+ # You can add multiple event triggers in 2 lines like this
+ for event in [lib.change, time.change, demo.load]:
+ event(get_plot, [lib, time], [plt])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_neural_instrument_coding/flute.wav b/demo/blocks_neural_instrument_coding/flute.wav
new file mode 100644
index 0000000000000000000000000000000000000000..17430f96670bd23a15072c33563fb86ccd7488a7
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/flute.wav differ
diff --git a/demo/blocks_neural_instrument_coding/new-sax-1.mp3 b/demo/blocks_neural_instrument_coding/new-sax-1.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..a323caeee337eb3845622ff0681031cb5ad89be6
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/new-sax-1.mp3 differ
diff --git a/demo/blocks_neural_instrument_coding/new-sax-1.wav b/demo/blocks_neural_instrument_coding/new-sax-1.wav
new file mode 100644
index 0000000000000000000000000000000000000000..1c92620db215576bff779d63d690b346e6369942
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/new-sax-1.wav differ
diff --git a/demo/blocks_neural_instrument_coding/new-sax.wav b/demo/blocks_neural_instrument_coding/new-sax.wav
new file mode 100644
index 0000000000000000000000000000000000000000..ec61ad246339c6ab0e3900464f98a2b413eccaaf
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/new-sax.wav differ
diff --git a/demo/blocks_neural_instrument_coding/run.ipynb b/demo/blocks_neural_instrument_coding/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..55e6aab3890df97212882c2ecaa5b6762988b67d
--- /dev/null
+++ b/demo/blocks_neural_instrument_coding/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_neural_instrument_coding"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/flute.wav\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/new-sax-1.mp3\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/new-sax-1.wav\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/new-sax.wav\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/sax.wav\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/sax2.wav\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/blocks_neural_instrument_coding/trombone.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["# A Blocks implementation of https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6\n", "\n", "import datetime\n", "import os\n", "import random\n", "\n", "import gradio as gr\n", "from gradio.components import Markdown as m\n", "\n", "\n", "def get_time():\n", " now = datetime.datetime.now()\n", " return now.strftime(\"%m/%d/%Y, %H:%M:%S\")\n", "\n", "\n", "def generate_recording():\n", " return random.choice([\"new-sax-1.mp3\", \"new-sax-1.wav\"])\n", "\n", "\n", "def reconstruct(audio):\n", " return random.choice([\"new-sax-1.mp3\", \"new-sax-1.wav\"])\n", "\n", "\n", "io1 = gr.Interface(\n", " lambda x, y, z: os.path.join(os.path.abspath(''),\"sax.wav\"),\n", " [\n", " gr.Slider(label=\"pitch\"),\n", " gr.Slider(label=\"loudness\"),\n", " gr.Audio(label=\"base audio file (optional)\"),\n", " ],\n", " gr.Audio(),\n", ")\n", "\n", "io2 = gr.Interface(\n", " lambda x, y, z: os.path.join(os.path.abspath(''),\"flute.wav\"),\n", " [\n", " gr.Slider(label=\"pitch\"),\n", " gr.Slider(label=\"loudness\"),\n", " gr.Audio(label=\"base audio file (optional)\"),\n", " ],\n", " gr.Audio(),\n", ")\n", "\n", "io3 = gr.Interface(\n", " lambda x, y, z: os.path.join(os.path.abspath(''),\"trombone.wav\"),\n", " [\n", " gr.Slider(label=\"pitch\"),\n", " gr.Slider(label=\"loudness\"),\n", " gr.Audio(label=\"base audio file (optional)\"),\n", " ],\n", " gr.Audio(),\n", ")\n", "\n", "io4 = gr.Interface(\n", " lambda x, y, z: os.path.join(os.path.abspath(''),\"sax2.wav\"),\n", " [\n", " gr.Slider(label=\"pitch\"),\n", " gr.Slider(label=\"loudness\"),\n", " gr.Audio(label=\"base audio file (optional)\"),\n", " ],\n", " gr.Audio(),\n", ")\n", "\n", "demo = gr.Blocks(title=\"Neural Instrument Cloning\")\n", "\n", "with demo.clear():\n", " m(\n", " \"\"\"\n", " ## Neural Instrument Cloning from Very Few Samples\n", " \"\"\"\n", " )\n", " m(\n", " \"\"\"\n", " This Blocks implementation is an adaptation [a report written](https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6) by Nicolas Jonason and Bob L.T. Sturm.\n", " \n", " I've implemented it in Blocks to show off some cool features, such as embedding live ML demos. More on that ahead...\n", " \n", " ### What does this machine learning model do?\n", " It combines techniques from neural voice cloning with musical instrument synthesis. This makes it possible to produce neural instrument synthesisers from just seconds of target instrument audio.\n", " \n", " ### Audio Examples\n", " Here are some **real** 16 second saxophone recordings:\n", " \"\"\"\n", " )\n", " gr.Audio(os.path.join(os.path.abspath(''),\"sax.wav\"), label=\"Here is a real 16 second saxophone recording:\")\n", " gr.Audio(os.path.join(os.path.abspath(''),\"sax.wav\"))\n", "\n", " m(\n", " \"\"\"\\n\n", " Here is a **generated** saxophone recordings:\"\"\"\n", " )\n", " a = gr.Audio(os.path.join(os.path.abspath(''),\"new-sax.wav\"))\n", "\n", " gr.Button(\"Generate a new saxophone recording\")\n", "\n", " m(\n", " \"\"\"\n", " ### Inputs to the model\n", " The inputs to the model are:\n", " * pitch\n", " * loudness\n", " * base audio file\n", " \"\"\"\n", " )\n", "\n", " m(\n", " \"\"\"\n", " Try the model live!\n", " \"\"\"\n", " )\n", "\n", " gr.TabbedInterface(\n", " [io1, io2, io3, io4], [\"Saxophone\", \"Flute\", \"Trombone\", \"Another Saxophone\"]\n", " )\n", "\n", " m(\n", " \"\"\"\n", " ### Using the model for cloning\n", " You can also use this model a different way, to simply clone the audio file and reconstruct it \n", " using machine learning. Here, we'll show a demo of that below:\n", " \"\"\"\n", " )\n", "\n", " a2 = gr.Audio()\n", " a2.change(reconstruct, a2, a2)\n", "\n", " m(\n", " \"\"\"\n", " Thanks for reading this! As you may have realized, all of the \"models\" in this demo are fake. They are just designed to show you what is possible using Blocks \ud83e\udd17.\n", " \n", " For details of the model, read the [original report here](https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6).\n", " \n", " *Details for nerds*: this report was \"launched\" on:\n", " \"\"\"\n", " )\n", "\n", " t = gr.Textbox(label=\"timestamp\")\n", "\n", " demo.load(get_time, [], t)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_neural_instrument_coding/run.py b/demo/blocks_neural_instrument_coding/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d387de781ee72df120c52a8a2bdbf2dd218ee4b
--- /dev/null
+++ b/demo/blocks_neural_instrument_coding/run.py
@@ -0,0 +1,143 @@
+# A Blocks implementation of https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6
+
+import datetime
+import os
+import random
+
+import gradio as gr
+from gradio.components import Markdown as m
+
+
+def get_time():
+ now = datetime.datetime.now()
+ return now.strftime("%m/%d/%Y, %H:%M:%S")
+
+
+def generate_recording():
+ return random.choice(["new-sax-1.mp3", "new-sax-1.wav"])
+
+
+def reconstruct(audio):
+ return random.choice(["new-sax-1.mp3", "new-sax-1.wav"])
+
+
+io1 = gr.Interface(
+ lambda x, y, z: os.path.join(os.path.dirname(__file__),"sax.wav"),
+ [
+ gr.Slider(label="pitch"),
+ gr.Slider(label="loudness"),
+ gr.Audio(label="base audio file (optional)"),
+ ],
+ gr.Audio(),
+)
+
+io2 = gr.Interface(
+ lambda x, y, z: os.path.join(os.path.dirname(__file__),"flute.wav"),
+ [
+ gr.Slider(label="pitch"),
+ gr.Slider(label="loudness"),
+ gr.Audio(label="base audio file (optional)"),
+ ],
+ gr.Audio(),
+)
+
+io3 = gr.Interface(
+ lambda x, y, z: os.path.join(os.path.dirname(__file__),"trombone.wav"),
+ [
+ gr.Slider(label="pitch"),
+ gr.Slider(label="loudness"),
+ gr.Audio(label="base audio file (optional)"),
+ ],
+ gr.Audio(),
+)
+
+io4 = gr.Interface(
+ lambda x, y, z: os.path.join(os.path.dirname(__file__),"sax2.wav"),
+ [
+ gr.Slider(label="pitch"),
+ gr.Slider(label="loudness"),
+ gr.Audio(label="base audio file (optional)"),
+ ],
+ gr.Audio(),
+)
+
+demo = gr.Blocks(title="Neural Instrument Cloning")
+
+with demo.clear():
+ m(
+ """
+ ## Neural Instrument Cloning from Very Few Samples
+ """
+ )
+ m(
+ """
+ This Blocks implementation is an adaptation [a report written](https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6) by Nicolas Jonason and Bob L.T. Sturm.
+
+ I've implemented it in Blocks to show off some cool features, such as embedding live ML demos. More on that ahead...
+
+ ### What does this machine learning model do?
+ It combines techniques from neural voice cloning with musical instrument synthesis. This makes it possible to produce neural instrument synthesisers from just seconds of target instrument audio.
+
+ ### Audio Examples
+ Here are some **real** 16 second saxophone recordings:
+ """
+ )
+ gr.Audio(os.path.join(os.path.dirname(__file__),"sax.wav"), label="Here is a real 16 second saxophone recording:")
+ gr.Audio(os.path.join(os.path.dirname(__file__),"sax.wav"))
+
+ m(
+ """\n
+ Here is a **generated** saxophone recordings:"""
+ )
+ a = gr.Audio(os.path.join(os.path.dirname(__file__),"new-sax.wav"))
+
+ gr.Button("Generate a new saxophone recording")
+
+ m(
+ """
+ ### Inputs to the model
+ The inputs to the model are:
+ * pitch
+ * loudness
+ * base audio file
+ """
+ )
+
+ m(
+ """
+ Try the model live!
+ """
+ )
+
+ gr.TabbedInterface(
+ [io1, io2, io3, io4], ["Saxophone", "Flute", "Trombone", "Another Saxophone"]
+ )
+
+ m(
+ """
+ ### Using the model for cloning
+ You can also use this model a different way, to simply clone the audio file and reconstruct it
+ using machine learning. Here, we'll show a demo of that below:
+ """
+ )
+
+ a2 = gr.Audio()
+ a2.change(reconstruct, a2, a2)
+
+ m(
+ """
+ Thanks for reading this! As you may have realized, all of the "models" in this demo are fake. They are just designed to show you what is possible using Blocks 🤗.
+
+ For details of the model, read the [original report here](https://erlj.notion.site/Neural-Instrument-Cloning-from-very-few-samples-2cf41d8b630842ee8c7eb55036a1bfd6).
+
+ *Details for nerds*: this report was "launched" on:
+ """
+ )
+
+ t = gr.Textbox(label="timestamp")
+
+ demo.load(get_time, [], t)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_neural_instrument_coding/sax.wav b/demo/blocks_neural_instrument_coding/sax.wav
new file mode 100644
index 0000000000000000000000000000000000000000..ed727c5408ced9c0b81ccf940b89425d6291dc65
--- /dev/null
+++ b/demo/blocks_neural_instrument_coding/sax.wav
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12ee32c66257e1c98ed0f2f7b708a1eab638ec09f4c69dda3ec1d78047a7be4d
+size 1536044
diff --git a/demo/blocks_neural_instrument_coding/sax2.wav b/demo/blocks_neural_instrument_coding/sax2.wav
new file mode 100644
index 0000000000000000000000000000000000000000..73963a554f01b6d60a6abc509511cc513dfdbf73
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/sax2.wav differ
diff --git a/demo/blocks_neural_instrument_coding/trombone.wav b/demo/blocks_neural_instrument_coding/trombone.wav
new file mode 100644
index 0000000000000000000000000000000000000000..55d17d879e4977edeafd9a9fef56798ec7b8e007
Binary files /dev/null and b/demo/blocks_neural_instrument_coding/trombone.wav differ
diff --git a/demo/blocks_outputs/run.ipynb b/demo/blocks_outputs/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..894e59dc1981ef756231a9379f8a853a4a51f7ee
--- /dev/null
+++ b/demo/blocks_outputs/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_outputs"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def make_markdown():\n", " return [\n", " [\n", " \"# hello again\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " [\n", " \"## hello again again\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " [\n", " \"### hello thrice\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " ]\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Column():\n", " txt = gr.Textbox(label=\"Small Textbox\", lines=1, show_label=False)\n", " txt = gr.Textbox(label=\"Large Textbox\", lines=5, show_label=False)\n", " num = gr.Number(label=\"Number\", show_label=False)\n", " check = gr.Checkbox(label=\"Checkbox\", show_label=False)\n", " check_g = gr.CheckboxGroup(\n", " label=\"Checkbox Group\", choices=[\"One\", \"Two\", \"Three\"], show_label=False\n", " )\n", " radio = gr.Radio(\n", " label=\"Radio\", choices=[\"One\", \"Two\", \"Three\"], show_label=False\n", " )\n", " drop = gr.Dropdown(\n", " label=\"Dropdown\", choices=[\"One\", \"Two\", \"Three\"], show_label=False\n", " )\n", " slider = gr.Slider(label=\"Slider\", show_label=False)\n", " audio = gr.Audio(show_label=False)\n", " file = gr.File(show_label=False)\n", " video = gr.Video(show_label=False)\n", " image = gr.Image(show_label=False)\n", " df = gr.Dataframe(show_label=False)\n", " html = gr.HTML(show_label=False)\n", " json = gr.JSON(show_label=False)\n", " md = gr.Markdown(show_label=False)\n", " label = gr.Label(show_label=False)\n", " highlight = gr.HighlightedText(show_label=False)\n", " gr.Dataframe(interactive=True, col_count=(3, \"fixed\"), label=\"Dataframe\")\n", " gr.Dataframe(interactive=True, col_count=4, label=\"Dataframe\")\n", " gr.Dataframe(\n", " interactive=True, headers=[\"One\", \"Two\", \"Three\", \"Four\"], label=\"Dataframe\"\n", " )\n", " gr.Dataframe(\n", " interactive=True,\n", " headers=[\"One\", \"Two\", \"Three\", \"Four\"],\n", " col_count=(4, \"fixed\"),\n", " row_count=(7, \"fixed\"),\n", " value=[[0, 0, 0, 0]],\n", " label=\"Dataframe\",\n", " )\n", " gr.Dataframe(\n", " interactive=True, headers=[\"One\", \"Two\", \"Three\", \"Four\"], col_count=4\n", " )\n", " df = gr.DataFrame(\n", " [\n", " [\n", " \"# hello\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " [\n", " \"## hello\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " [\n", " \"### hello\",\n", " \"Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.\",\n", " ' ',\n", " ],\n", " ],\n", " headers=[\"One\", \"Two\", \"Three\"],\n", " wrap=True,\n", " datatype=[\"markdown\", \"markdown\", \"html\"],\n", " interactive=True,\n", " )\n", " btn = gr.Button(\"Run\")\n", " btn.click(fn=make_markdown, inputs=None, outputs=df)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_outputs/run.py b/demo/blocks_outputs/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd0b4d25a23ff17d855d00253c9a2ed58d878566
--- /dev/null
+++ b/demo/blocks_outputs/run.py
@@ -0,0 +1,94 @@
+import gradio as gr
+
+
+def make_markdown():
+ return [
+ [
+ "# hello again",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ [
+ "## hello again again",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ [
+ "### hello thrice",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ ]
+
+
+with gr.Blocks() as demo:
+ with gr.Column():
+ txt = gr.Textbox(label="Small Textbox", lines=1, show_label=False)
+ txt = gr.Textbox(label="Large Textbox", lines=5, show_label=False)
+ num = gr.Number(label="Number", show_label=False)
+ check = gr.Checkbox(label="Checkbox", show_label=False)
+ check_g = gr.CheckboxGroup(
+ label="Checkbox Group", choices=["One", "Two", "Three"], show_label=False
+ )
+ radio = gr.Radio(
+ label="Radio", choices=["One", "Two", "Three"], show_label=False
+ )
+ drop = gr.Dropdown(
+ label="Dropdown", choices=["One", "Two", "Three"], show_label=False
+ )
+ slider = gr.Slider(label="Slider", show_label=False)
+ audio = gr.Audio(show_label=False)
+ file = gr.File(show_label=False)
+ video = gr.Video(show_label=False)
+ image = gr.Image(show_label=False)
+ df = gr.Dataframe(show_label=False)
+ html = gr.HTML(show_label=False)
+ json = gr.JSON(show_label=False)
+ md = gr.Markdown(show_label=False)
+ label = gr.Label(show_label=False)
+ highlight = gr.HighlightedText(show_label=False)
+ gr.Dataframe(interactive=True, col_count=(3, "fixed"), label="Dataframe")
+ gr.Dataframe(interactive=True, col_count=4, label="Dataframe")
+ gr.Dataframe(
+ interactive=True, headers=["One", "Two", "Three", "Four"], label="Dataframe"
+ )
+ gr.Dataframe(
+ interactive=True,
+ headers=["One", "Two", "Three", "Four"],
+ col_count=(4, "fixed"),
+ row_count=(7, "fixed"),
+ value=[[0, 0, 0, 0]],
+ label="Dataframe",
+ )
+ gr.Dataframe(
+ interactive=True, headers=["One", "Two", "Three", "Four"], col_count=4
+ )
+ df = gr.DataFrame(
+ [
+ [
+ "# hello",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ [
+ "## hello",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ [
+ "### hello",
+ "Hello my name is frank, I am liking the small turtle you have there. It would be a shame if it went missing.",
+ ' ',
+ ],
+ ],
+ headers=["One", "Two", "Three"],
+ wrap=True,
+ datatype=["markdown", "markdown", "html"],
+ interactive=True,
+ )
+ btn = gr.Button("Run")
+ btn.click(fn=make_markdown, inputs=None, outputs=df)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_page_load/run.ipynb b/demo/blocks_page_load/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dfd1ad0ed795efbb43941bc77ccdb9f8418ae4f8
--- /dev/null
+++ b/demo/blocks_page_load/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_page_load"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def print_message(n):\n", " return \"Welcome! This page has loaded for \" + n\n", "\n", "\n", "with gr.Blocks() as demo:\n", " t = gr.Textbox(\"Frank\", label=\"Name\")\n", " t2 = gr.Textbox(label=\"Output\")\n", " demo.load(print_message, t, t2)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_page_load/run.py b/demo/blocks_page_load/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5022a41023f15f69513bb1734f30aa621cab8e72
--- /dev/null
+++ b/demo/blocks_page_load/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+
+def print_message(n):
+ return "Welcome! This page has loaded for " + n
+
+
+with gr.Blocks() as demo:
+ t = gr.Textbox("Frank", label="Name")
+ t2 = gr.Textbox(label="Output")
+ demo.load(print_message, t, t2)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_plug/run.ipynb b/demo/blocks_plug/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8a037f584a6a5c29a5c73d068f5638fa24037b3c
--- /dev/null
+++ b/demo/blocks_plug/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_plug"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_tab():\n", " return gr.Tabs(selected=2)\n", "\n", "\n", "identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()\n", "\n", "with identity_demo:\n", " gr.Interface(lambda x: x, \"text\", \"text\")\n", "\n", "with input_demo:\n", " t = gr.Textbox(label=\"Enter your text here\")\n", " with gr.Row():\n", " btn = gr.Button(\"Submit\")\n", " clr = gr.ClearButton(t)\n", "\n", "with output_demo:\n", " gr.Textbox(\"This is a static output\")\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Three demos in one!\")\n", " with gr.Tabs(selected=1) as tabs:\n", " with gr.TabItem(\"Text Identity\", id=0) as tab0:\n", " tab0.select(lambda: gr.Tabs(selected=0), None, tabs)\n", " identity_demo.render()\n", " with gr.TabItem(\"Text Input\", id=1) as tab1:\n", " tab1.select(lambda: gr.Tabs(selected=1), None, tabs)\n", " input_demo.render()\n", " with gr.TabItem(\"Text Static\", id=2) as tab2:\n", " tab2.select(lambda: gr.Tabs(selected=2), None, tabs)\n", " output_demo.render()\n", " btn = gr.Button(\"Change tab\")\n", " btn.click(inputs=None, outputs=tabs, fn=change_tab)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_plug/run.py b/demo/blocks_plug/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c2b49423298d388051a14ebc6b016457ee8e34c8
--- /dev/null
+++ b/demo/blocks_plug/run.py
@@ -0,0 +1,38 @@
+import gradio as gr
+
+
+def change_tab():
+ return gr.Tabs(selected=2)
+
+
+identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()
+
+with identity_demo:
+ gr.Interface(lambda x: x, "text", "text")
+
+with input_demo:
+ t = gr.Textbox(label="Enter your text here")
+ with gr.Row():
+ btn = gr.Button("Submit")
+ clr = gr.ClearButton(t)
+
+with output_demo:
+ gr.Textbox("This is a static output")
+
+with gr.Blocks() as demo:
+ gr.Markdown("Three demos in one!")
+ with gr.Tabs(selected=1) as tabs:
+ with gr.TabItem("Text Identity", id=0) as tab0:
+ tab0.select(lambda: gr.Tabs(selected=0), None, tabs)
+ identity_demo.render()
+ with gr.TabItem("Text Input", id=1) as tab1:
+ tab1.select(lambda: gr.Tabs(selected=1), None, tabs)
+ input_demo.render()
+ with gr.TabItem("Text Static", id=2) as tab2:
+ tab2.select(lambda: gr.Tabs(selected=2), None, tabs)
+ output_demo.render()
+ btn = gr.Button("Change tab")
+ btn.click(inputs=None, outputs=tabs, fn=change_tab)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_random_slider/run.ipynb b/demo/blocks_random_slider/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..52b32cb819a67b68d3d3e0e723dc7ed4419224e6
--- /dev/null
+++ b/demo/blocks_random_slider/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_random_slider"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["\n", "import gradio as gr\n", "\n", "\n", "def func(slider_1, slider_2):\n", " return slider_1 * 5 + slider_2\n", "\n", "\n", "with gr.Blocks() as demo:\n", " slider = gr.Slider(minimum=-10.2, maximum=15, label=\"Random Slider (Static)\", randomize=True)\n", " slider_1 = gr.Slider(minimum=100, maximum=200, label=\"Random Slider (Input 1)\", randomize=True)\n", " slider_2 = gr.Slider(minimum=10, maximum=23.2, label=\"Random Slider (Input 2)\", randomize=True)\n", " slider_3 = gr.Slider(value=3, label=\"Non random slider\")\n", " btn = gr.Button(\"Run\")\n", " btn.click(func, inputs=[slider_1, slider_2], outputs=gr.Number())\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_random_slider/run.py b/demo/blocks_random_slider/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..105ddcb0e4f8e77d7da977400d25e95210add2fc
--- /dev/null
+++ b/demo/blocks_random_slider/run.py
@@ -0,0 +1,18 @@
+
+import gradio as gr
+
+
+def func(slider_1, slider_2):
+ return slider_1 * 5 + slider_2
+
+
+with gr.Blocks() as demo:
+ slider = gr.Slider(minimum=-10.2, maximum=15, label="Random Slider (Static)", randomize=True)
+ slider_1 = gr.Slider(minimum=100, maximum=200, label="Random Slider (Input 1)", randomize=True)
+ slider_2 = gr.Slider(minimum=10, maximum=23.2, label="Random Slider (Input 2)", randomize=True)
+ slider_3 = gr.Slider(value=3, label="Non random slider")
+ btn = gr.Button("Run")
+ btn.click(func, inputs=[slider_1, slider_2], outputs=gr.Number())
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_scroll/run.ipynb b/demo/blocks_scroll/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..075ff8c94333457cdb6499a00432b7c364fc1976
--- /dev/null
+++ b/demo/blocks_scroll/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_scroll"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " inp = gr.Textbox(placeholder=\"Enter text.\")\n", " scroll_btn = gr.Button(\"Scroll\")\n", " no_scroll_btn = gr.Button(\"No Scroll\")\n", " big_block = gr.HTML(\"\"\"\n", "
\n", " \"\"\")\n", " out = gr.Textbox()\n", " \n", " scroll_btn.click(lambda x: x, \n", " inputs=inp, \n", " outputs=out,\n", " scroll_to_output=True)\n", " no_scroll_btn.click(lambda x: x, \n", " inputs=inp, \n", " outputs=out)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_scroll/run.py b/demo/blocks_scroll/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b2194dfb8050fc2a50b9491f2e57f672289ffe7
--- /dev/null
+++ b/demo/blocks_scroll/run.py
@@ -0,0 +1,24 @@
+import gradio as gr
+
+
+demo = gr.Blocks()
+
+with demo:
+ inp = gr.Textbox(placeholder="Enter text.")
+ scroll_btn = gr.Button("Scroll")
+ no_scroll_btn = gr.Button("No Scroll")
+ big_block = gr.HTML("""
+
+ """)
+ out = gr.Textbox()
+
+ scroll_btn.click(lambda x: x,
+ inputs=inp,
+ outputs=out,
+ scroll_to_output=True)
+ no_scroll_btn.click(lambda x: x,
+ inputs=inp,
+ outputs=out)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_simple_squares/run.ipynb b/demo/blocks_simple_squares/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0d4b6d5f41732d565f5f7ba62586c85a6fb0d049
--- /dev/null
+++ b/demo/blocks_simple_squares/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_simple_squares"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "demo = gr.Blocks(css=\"\"\"#btn {color: red} .abc {font-family: \"Comic Sans MS\", \"Comic Sans\", cursive !important}\"\"\")\n", "\n", "with demo:\n", " default_json = {\"a\": \"a\"}\n", "\n", " num = gr.State(value=0)\n", " squared = gr.Number(value=0)\n", " btn = gr.Button(\"Next Square\", elem_id=\"btn\", elem_classes=[\"abc\", \"def\"])\n", "\n", " stats = gr.State(value=default_json)\n", " table = gr.JSON()\n", "\n", " def increase(var, stats_history):\n", " var += 1\n", " stats_history[str(var)] = var**2\n", " return var, var**2, stats_history, stats_history\n", "\n", " btn.click(increase, [num, stats], [num, squared, stats, table])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_simple_squares/run.py b/demo/blocks_simple_squares/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..631d398e6e2809ce958d72b8b93104910f60d3af
--- /dev/null
+++ b/demo/blocks_simple_squares/run.py
@@ -0,0 +1,23 @@
+import gradio as gr
+
+demo = gr.Blocks(css="""#btn {color: red} .abc {font-family: "Comic Sans MS", "Comic Sans", cursive !important}""")
+
+with demo:
+ default_json = {"a": "a"}
+
+ num = gr.State(value=0)
+ squared = gr.Number(value=0)
+ btn = gr.Button("Next Square", elem_id="btn", elem_classes=["abc", "def"])
+
+ stats = gr.State(value=default_json)
+ table = gr.JSON()
+
+ def increase(var, stats_history):
+ var += 1
+ stats_history[str(var)] = var**2
+ return var, var**2, stats_history, stats_history
+
+ btn.click(increase, [num, stats], [num, squared, stats, table])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_speech_text_sentiment/requirements.txt b/demo/blocks_speech_text_sentiment/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39dab0fdd98d55da5ce06ddf1dacbdbda14b1372
--- /dev/null
+++ b/demo/blocks_speech_text_sentiment/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
\ No newline at end of file
diff --git a/demo/blocks_speech_text_sentiment/run.ipynb b/demo/blocks_speech_text_sentiment/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c864e6fe661905c26ad7e01d98e3577fd345bf4e
--- /dev/null
+++ b/demo/blocks_speech_text_sentiment/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_speech_text_sentiment"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from transformers import pipeline\n", "\n", "import gradio as gr\n", "\n", "asr = pipeline(\"automatic-speech-recognition\", \"facebook/wav2vec2-base-960h\")\n", "classifier = pipeline(\"text-classification\")\n", "\n", "\n", "def speech_to_text(speech):\n", " text = asr(speech)[\"text\"]\n", " return text\n", "\n", "\n", "def text_to_sentiment(text):\n", " return classifier(text)[0][\"label\"]\n", "\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " audio_file = gr.Audio(type=\"filepath\")\n", " text = gr.Textbox()\n", " label = gr.Label()\n", "\n", " b1 = gr.Button(\"Recognize Speech\")\n", " b2 = gr.Button(\"Classify Sentiment\")\n", "\n", " b1.click(speech_to_text, inputs=audio_file, outputs=text)\n", " b2.click(text_to_sentiment, inputs=text, outputs=label)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_speech_text_sentiment/run.py b/demo/blocks_speech_text_sentiment/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c9343fd1233859ec226129c890fc43939f352a1
--- /dev/null
+++ b/demo/blocks_speech_text_sentiment/run.py
@@ -0,0 +1,32 @@
+from transformers import pipeline
+
+import gradio as gr
+
+asr = pipeline("automatic-speech-recognition", "facebook/wav2vec2-base-960h")
+classifier = pipeline("text-classification")
+
+
+def speech_to_text(speech):
+ text = asr(speech)["text"]
+ return text
+
+
+def text_to_sentiment(text):
+ return classifier(text)[0]["label"]
+
+
+demo = gr.Blocks()
+
+with demo:
+ audio_file = gr.Audio(type="filepath")
+ text = gr.Textbox()
+ label = gr.Label()
+
+ b1 = gr.Button("Recognize Speech")
+ b2 = gr.Button("Classify Sentiment")
+
+ b1.click(speech_to_text, inputs=audio_file, outputs=text)
+ b2.click(text_to_sentiment, inputs=text, outputs=label)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_static/run.ipynb b/demo/blocks_static/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2010f8432016dd420a87505a4263f330e5b90573
--- /dev/null
+++ b/demo/blocks_static/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_static"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " gr.Image(\n", " \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\"\n", " )\n", " gr.Textbox(\"hi\")\n", " gr.Number(3)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_static/run.py b/demo/blocks_static/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..79aba06c19ce7dd7cec3f4409483377c31768f66
--- /dev/null
+++ b/demo/blocks_static/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+demo = gr.Blocks()
+
+with demo:
+ gr.Image(
+ "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80"
+ )
+ gr.Textbox("hi")
+ gr.Number(3)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_style/run.ipynb b/demo/blocks_style/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..81550ce642c911fef4d21e071bdae78349af5f4f
--- /dev/null
+++ b/demo/blocks_style/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_style"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks(title=\"Styling Examples\") as demo:\n", " with gr.Column(variant=\"box\"):\n", " txt = gr.Textbox(label=\"Small Textbox\", lines=1)\n", " num = gr.Number(label=\"Number\", show_label=False)\n", " slider = gr.Slider(label=\"Slider\", show_label=False)\n", " check = gr.Checkbox(label=\"Checkbox\", show_label=False)\n", " check_g = gr.CheckboxGroup(\n", " label=\"Checkbox Group\",\n", " choices=[\"One\", \"Two\", \"Three\"],\n", " show_label=False,\n", " )\n", " radio = gr.Radio(\n", " label=\"Radio\",\n", " choices=[\"One\", \"Two\", \"Three\"],\n", " show_label=False,\n", " )\n", " drop = gr.Dropdown(\n", " label=\"Dropdown\", choices=[\"One\", \"Two\", \"Three\"], show_label=False\n", " )\n", " image = gr.Image(show_label=False)\n", " video = gr.Video(show_label=False)\n", " audio = gr.Audio(show_label=False)\n", " file = gr.File(show_label=False)\n", " df = gr.Dataframe(show_label=False)\n", " label = gr.Label(container=False)\n", " highlight = gr.HighlightedText(\n", " [(\"hello\", None), (\"goodbye\", \"-\")],\n", " color_map={\"+\": \"green\", \"-\": \"red\"},\n", " container=False,\n", " )\n", " json = gr.JSON(container=False)\n", " html = gr.HTML(show_label=False)\n", " gallery = gr.Gallery(\n", " columns=(3, 3, 1),\n", " height=\"auto\",\n", " container=False,\n", " )\n", " chat = gr.Chatbot([(\"hi\", \"good bye\")])\n", "\n", " model = gr.Model3D()\n", "\n", " md = gr.Markdown(show_label=False)\n", "\n", " highlight = gr.HighlightedText()\n", "\n", " btn = gr.Button(\"Run\")\n", "\n", " gr.Dataset(components=[txt, num])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_style/run.py b/demo/blocks_style/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4feb0e0b34fb7ded12ef97f6542eff8738bb5e8
--- /dev/null
+++ b/demo/blocks_style/run.py
@@ -0,0 +1,54 @@
+import gradio as gr
+
+with gr.Blocks(title="Styling Examples") as demo:
+ with gr.Column(variant="box"):
+ txt = gr.Textbox(label="Small Textbox", lines=1)
+ num = gr.Number(label="Number", show_label=False)
+ slider = gr.Slider(label="Slider", show_label=False)
+ check = gr.Checkbox(label="Checkbox", show_label=False)
+ check_g = gr.CheckboxGroup(
+ label="Checkbox Group",
+ choices=["One", "Two", "Three"],
+ show_label=False,
+ )
+ radio = gr.Radio(
+ label="Radio",
+ choices=["One", "Two", "Three"],
+ show_label=False,
+ )
+ drop = gr.Dropdown(
+ label="Dropdown", choices=["One", "Two", "Three"], show_label=False
+ )
+ image = gr.Image(show_label=False)
+ video = gr.Video(show_label=False)
+ audio = gr.Audio(show_label=False)
+ file = gr.File(show_label=False)
+ df = gr.Dataframe(show_label=False)
+ label = gr.Label(container=False)
+ highlight = gr.HighlightedText(
+ [("hello", None), ("goodbye", "-")],
+ color_map={"+": "green", "-": "red"},
+ container=False,
+ )
+ json = gr.JSON(container=False)
+ html = gr.HTML(show_label=False)
+ gallery = gr.Gallery(
+ columns=(3, 3, 1),
+ height="auto",
+ container=False,
+ )
+ chat = gr.Chatbot([("hi", "good bye")])
+
+ model = gr.Model3D()
+
+ md = gr.Markdown(show_label=False)
+
+ highlight = gr.HighlightedText()
+
+ btn = gr.Button("Run")
+
+ gr.Dataset(components=[txt, num])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_textbox_max_lines/run.ipynb b/demo/blocks_textbox_max_lines/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..00c909378f062e7127f028dd9f9969b646e8edbf
--- /dev/null
+++ b/demo/blocks_textbox_max_lines/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_textbox_max_lines"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def greet(name: str, repeat: float):\n", " return \"Hello \" + name * int(repeat) + \"!!\"\n", "\n", "\n", "demo = gr.Interface(\n", " fn=greet, inputs=[gr.Textbox(lines=2, max_lines=4), gr.Number()], outputs=\"textarea\"\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_textbox_max_lines/run.py b/demo/blocks_textbox_max_lines/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a50ec1a7f7e2f6f31a555a9c3a2117546f175e67
--- /dev/null
+++ b/demo/blocks_textbox_max_lines/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+
+def greet(name: str, repeat: float):
+ return "Hello " + name * int(repeat) + "!!"
+
+
+demo = gr.Interface(
+ fn=greet, inputs=[gr.Textbox(lines=2, max_lines=4), gr.Number()], outputs="textarea"
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_update/run.ipynb b/demo/blocks_update/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..31eb77c2f3c4d6997da61c5f71e58c8643da98f8
--- /dev/null
+++ b/demo/blocks_update/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_update"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Animal Generator\n", " Once you select a species, the detail panel should be visible.\n", " \"\"\"\n", " )\n", "\n", " species = gr.Radio(label=\"Animal Class\", choices=[\"Mammal\", \"Fish\", \"Bird\"])\n", " animal = gr.Dropdown(label=\"Animal\", choices=[])\n", "\n", " with gr.Column(visible=False) as details_col:\n", " weight = gr.Slider(0, 20)\n", " details = gr.Textbox(label=\"Extra Details\")\n", " generate_btn = gr.Button(\"Generate\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " species_map = {\n", " \"Mammal\": [\"Elephant\", \"Giraffe\", \"Hamster\"],\n", " \"Fish\": [\"Shark\", \"Salmon\", \"Tuna\"],\n", " \"Bird\": [\"Chicken\", \"Eagle\", \"Hawk\"],\n", " }\n", "\n", " def filter_species(species):\n", " return gr.Dropdown(\n", " choices=species_map[species], value=species_map[species][1]\n", " ), gr.Column(visible=True)\n", "\n", " species.change(filter_species, species, [animal, details_col])\n", "\n", " def filter_weight(animal):\n", " if animal in (\"Elephant\", \"Shark\", \"Giraffe\"):\n", " return gr.Slider(maximum=100)\n", " else:\n", " return gr.Slider(maximum=20)\n", "\n", " animal.change(filter_weight, animal, weight)\n", " weight.change(lambda w: gr.Textbox(lines=int(w / 10) + 1), weight, details)\n", "\n", " generate_btn.click(lambda x: x, details, output)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_update/run.py b/demo/blocks_update/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..423a8d3dce27590f84d1a37ec9f31f2df0bde631
--- /dev/null
+++ b/demo/blocks_update/run.py
@@ -0,0 +1,46 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+ # Animal Generator
+ Once you select a species, the detail panel should be visible.
+ """
+ )
+
+ species = gr.Radio(label="Animal Class", choices=["Mammal", "Fish", "Bird"])
+ animal = gr.Dropdown(label="Animal", choices=[])
+
+ with gr.Column(visible=False) as details_col:
+ weight = gr.Slider(0, 20)
+ details = gr.Textbox(label="Extra Details")
+ generate_btn = gr.Button("Generate")
+ output = gr.Textbox(label="Output")
+
+ species_map = {
+ "Mammal": ["Elephant", "Giraffe", "Hamster"],
+ "Fish": ["Shark", "Salmon", "Tuna"],
+ "Bird": ["Chicken", "Eagle", "Hawk"],
+ }
+
+ def filter_species(species):
+ return gr.Dropdown(
+ choices=species_map[species], value=species_map[species][1]
+ ), gr.Column(visible=True)
+
+ species.change(filter_species, species, [animal, details_col])
+
+ def filter_weight(animal):
+ if animal in ("Elephant", "Shark", "Giraffe"):
+ return gr.Slider(maximum=100)
+ else:
+ return gr.Slider(maximum=20)
+
+ animal.change(filter_weight, animal, weight)
+ weight.change(lambda w: gr.Textbox(lines=int(w / 10) + 1), weight, details)
+
+ generate_btn.click(lambda x: x, details, output)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/blocks_webcam/run.ipynb b/demo/blocks_webcam/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..bf4b993fdb531169ee584069e78a00aefbc3bfa5
--- /dev/null
+++ b/demo/blocks_webcam/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_webcam"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def snap(image):\n", " return np.flipud(image)\n", "\n", "\n", "demo = gr.Interface(snap, gr.Image(sources=[\"webcam\"]), \"image\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_webcam/run.py b/demo/blocks_webcam/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..1076d0b1afd1ba6893275fb499f3500641f9735b
--- /dev/null
+++ b/demo/blocks_webcam/run.py
@@ -0,0 +1,13 @@
+import numpy as np
+
+import gradio as gr
+
+
+def snap(image):
+ return np.flipud(image)
+
+
+demo = gr.Interface(snap, gr.Image(sources=["webcam"]), "image")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/blocks_xray/run.ipynb b/demo/blocks_xray/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..6754b73faff91fb1dc04e46d8ab3adf83da1134a
--- /dev/null
+++ b/demo/blocks_xray/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_xray"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "disease_values = [0.25, 0.5, 0.75]\n", "\n", "def xray_model(diseases, img):\n", " return [{disease: disease_values[idx] for idx,disease in enumerate(diseases)}]\n", "\n", "\n", "def ct_model(diseases, img):\n", " return [{disease: 0.1 for disease in diseases}]\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", "# Detect Disease From Scan\n", "With this model you can lorem ipsum\n", "- ipsum 1\n", "- ipsum 2\n", "\"\"\"\n", " )\n", " gr.DuplicateButton()\n", " disease = gr.CheckboxGroup(\n", " info=\"Select the diseases you want to scan for.\",\n", " choices=[\"Covid\", \"Malaria\", \"Lung Cancer\"], label=\"Disease to Scan For\"\n", " )\n", " slider = gr.Slider(0, 100)\n", "\n", " with gr.Tab(\"X-ray\") as x_tab:\n", " with gr.Row():\n", " xray_scan = gr.Image()\n", " xray_results = gr.JSON()\n", " xray_run = gr.Button(\"Run\")\n", " xray_run.click(\n", " xray_model,\n", " inputs=[disease, xray_scan],\n", " outputs=xray_results,\n", " api_name=\"xray_model\"\n", " )\n", "\n", " with gr.Tab(\"CT Scan\"):\n", " with gr.Row():\n", " ct_scan = gr.Image()\n", " ct_results = gr.JSON()\n", " ct_run = gr.Button(\"Run\")\n", " ct_run.click(\n", " ct_model,\n", " inputs=[disease, ct_scan],\n", " outputs=ct_results,\n", " api_name=\"ct_model\"\n", " )\n", "\n", " upload_btn = gr.Button(\"Upload Results\", variant=\"primary\")\n", " upload_btn.click(\n", " lambda ct, xr: None,\n", " inputs=[ct_results, xray_results],\n", " outputs=[],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/blocks_xray/run.py b/demo/blocks_xray/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8e8e8167f1d6adc3b5a49fc52111542b4192c90
--- /dev/null
+++ b/demo/blocks_xray/run.py
@@ -0,0 +1,61 @@
+import gradio as gr
+import time
+
+disease_values = [0.25, 0.5, 0.75]
+
+def xray_model(diseases, img):
+ return [{disease: disease_values[idx] for idx,disease in enumerate(diseases)}]
+
+
+def ct_model(diseases, img):
+ return [{disease: 0.1 for disease in diseases}]
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+# Detect Disease From Scan
+With this model you can lorem ipsum
+- ipsum 1
+- ipsum 2
+"""
+ )
+ gr.DuplicateButton()
+ disease = gr.CheckboxGroup(
+ info="Select the diseases you want to scan for.",
+ choices=["Covid", "Malaria", "Lung Cancer"], label="Disease to Scan For"
+ )
+ slider = gr.Slider(0, 100)
+
+ with gr.Tab("X-ray") as x_tab:
+ with gr.Row():
+ xray_scan = gr.Image()
+ xray_results = gr.JSON()
+ xray_run = gr.Button("Run")
+ xray_run.click(
+ xray_model,
+ inputs=[disease, xray_scan],
+ outputs=xray_results,
+ api_name="xray_model"
+ )
+
+ with gr.Tab("CT Scan"):
+ with gr.Row():
+ ct_scan = gr.Image()
+ ct_results = gr.JSON()
+ ct_run = gr.Button("Run")
+ ct_run.click(
+ ct_model,
+ inputs=[disease, ct_scan],
+ outputs=ct_results,
+ api_name="ct_model"
+ )
+
+ upload_btn = gr.Button("Upload Results", variant="primary")
+ upload_btn.click(
+ lambda ct, xr: None,
+ inputs=[ct_results, xray_results],
+ outputs=[],
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/bokeh_plot/requirements.txt b/demo/bokeh_plot/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8d941b8ebb982d2ece938624f3eff495ba89f03d
--- /dev/null
+++ b/demo/bokeh_plot/requirements.txt
@@ -0,0 +1,2 @@
+bokeh>=3.0
+xyzservices
\ No newline at end of file
diff --git a/demo/bokeh_plot/run.ipynb b/demo/bokeh_plot/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f37fb0c8fab1669dba5d3ccbfece7cd2f576ddeb
--- /dev/null
+++ b/demo/bokeh_plot/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: bokeh_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio bokeh>=3.0 xyzservices"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import xyzservices.providers as xyz\n", "from bokeh.models import ColumnDataSource, Whisker\n", "from bokeh.plotting import figure\n", "from bokeh.sampledata.autompg2 import autompg2 as df\n", "from bokeh.sampledata.penguins import data\n", "from bokeh.transform import factor_cmap, jitter, factor_mark\n", "\n", "\n", "def get_plot(plot_type):\n", " if plot_type == \"map\":\n", " plot = figure(\n", " x_range=(-2000000, 6000000),\n", " y_range=(-1000000, 7000000),\n", " x_axis_type=\"mercator\",\n", " y_axis_type=\"mercator\",\n", " )\n", " plot.add_tile(xyz.OpenStreetMap.Mapnik)\n", " return plot\n", " elif plot_type == \"whisker\":\n", " classes = list(sorted(df[\"class\"].unique()))\n", "\n", " p = figure(\n", " height=400,\n", " x_range=classes,\n", " background_fill_color=\"#efefef\",\n", " title=\"Car class vs HWY mpg with quintile ranges\",\n", " )\n", " p.xgrid.grid_line_color = None\n", "\n", " g = df.groupby(\"class\")\n", " upper = g.hwy.quantile(0.80)\n", " lower = g.hwy.quantile(0.20)\n", " source = ColumnDataSource(data=dict(base=classes, upper=upper, lower=lower))\n", "\n", " error = Whisker(\n", " base=\"base\",\n", " upper=\"upper\",\n", " lower=\"lower\",\n", " source=source,\n", " level=\"annotation\",\n", " line_width=2,\n", " )\n", " error.upper_head.size = 20\n", " error.lower_head.size = 20\n", " p.add_layout(error)\n", "\n", " p.circle(\n", " jitter(\"class\", 0.3, range=p.x_range),\n", " \"hwy\",\n", " source=df,\n", " alpha=0.5,\n", " size=13,\n", " line_color=\"white\",\n", " color=factor_cmap(\"class\", \"Light6\", classes),\n", " )\n", " return p\n", " elif plot_type == \"scatter\":\n", "\n", " SPECIES = sorted(data.species.unique())\n", " MARKERS = [\"hex\", \"circle_x\", \"triangle\"]\n", "\n", " p = figure(title=\"Penguin size\", background_fill_color=\"#fafafa\")\n", " p.xaxis.axis_label = \"Flipper Length (mm)\"\n", " p.yaxis.axis_label = \"Body Mass (g)\"\n", "\n", " p.scatter(\n", " \"flipper_length_mm\",\n", " \"body_mass_g\",\n", " source=data,\n", " legend_group=\"species\",\n", " fill_alpha=0.4,\n", " size=12,\n", " marker=factor_mark(\"species\", MARKERS, SPECIES),\n", " color=factor_cmap(\"species\", \"Category10_3\", SPECIES),\n", " )\n", "\n", " p.legend.location = \"top_left\"\n", " p.legend.title = \"Species\"\n", " return p\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " plot_type = gr.Radio(value=\"scatter\", choices=[\"scatter\", \"whisker\", \"map\"])\n", " plot = gr.Plot()\n", " plot_type.change(get_plot, inputs=[plot_type], outputs=[plot])\n", " demo.load(get_plot, inputs=[plot_type], outputs=[plot])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/bokeh_plot/run.py b/demo/bokeh_plot/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..896a1839a36949a8cd0efbc99c967d951bc85056
--- /dev/null
+++ b/demo/bokeh_plot/run.py
@@ -0,0 +1,91 @@
+import gradio as gr
+import xyzservices.providers as xyz
+from bokeh.models import ColumnDataSource, Whisker
+from bokeh.plotting import figure
+from bokeh.sampledata.autompg2 import autompg2 as df
+from bokeh.sampledata.penguins import data
+from bokeh.transform import factor_cmap, jitter, factor_mark
+
+
+def get_plot(plot_type):
+ if plot_type == "map":
+ plot = figure(
+ x_range=(-2000000, 6000000),
+ y_range=(-1000000, 7000000),
+ x_axis_type="mercator",
+ y_axis_type="mercator",
+ )
+ plot.add_tile(xyz.OpenStreetMap.Mapnik)
+ return plot
+ elif plot_type == "whisker":
+ classes = list(sorted(df["class"].unique()))
+
+ p = figure(
+ height=400,
+ x_range=classes,
+ background_fill_color="#efefef",
+ title="Car class vs HWY mpg with quintile ranges",
+ )
+ p.xgrid.grid_line_color = None
+
+ g = df.groupby("class")
+ upper = g.hwy.quantile(0.80)
+ lower = g.hwy.quantile(0.20)
+ source = ColumnDataSource(data=dict(base=classes, upper=upper, lower=lower))
+
+ error = Whisker(
+ base="base",
+ upper="upper",
+ lower="lower",
+ source=source,
+ level="annotation",
+ line_width=2,
+ )
+ error.upper_head.size = 20
+ error.lower_head.size = 20
+ p.add_layout(error)
+
+ p.circle(
+ jitter("class", 0.3, range=p.x_range),
+ "hwy",
+ source=df,
+ alpha=0.5,
+ size=13,
+ line_color="white",
+ color=factor_cmap("class", "Light6", classes),
+ )
+ return p
+ elif plot_type == "scatter":
+
+ SPECIES = sorted(data.species.unique())
+ MARKERS = ["hex", "circle_x", "triangle"]
+
+ p = figure(title="Penguin size", background_fill_color="#fafafa")
+ p.xaxis.axis_label = "Flipper Length (mm)"
+ p.yaxis.axis_label = "Body Mass (g)"
+
+ p.scatter(
+ "flipper_length_mm",
+ "body_mass_g",
+ source=data,
+ legend_group="species",
+ fill_alpha=0.4,
+ size=12,
+ marker=factor_mark("species", MARKERS, SPECIES),
+ color=factor_cmap("species", "Category10_3", SPECIES),
+ )
+
+ p.legend.location = "top_left"
+ p.legend.title = "Species"
+ return p
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ plot_type = gr.Radio(value="scatter", choices=["scatter", "whisker", "map"])
+ plot = gr.Plot()
+ plot_type.change(get_plot, inputs=[plot_type], outputs=[plot])
+ demo.load(get_plot, inputs=[plot_type], outputs=[plot])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/button_component/run.ipynb b/demo/button_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..641a17bf891ccd0613f16721bf1208f750040eff
--- /dev/null
+++ b/demo/button_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: button_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Button()\n", " \n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/button_component/run.py b/demo/button_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..660d3ecc271f32b5313aa3ed1528425658c10e20
--- /dev/null
+++ b/demo/button_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Button()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/calculator/examples/log.csv b/demo/calculator/examples/log.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/calculator/run.ipynb b/demo/calculator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f43bbf4ce843d1b75f8b84cba738fcd9c7ba0ace
--- /dev/null
+++ b/demo/calculator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: calculator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('examples')\n", "!wget -q -O examples/log.csv https://github.com/gradio-app/gradio/raw/main/demo/calculator/examples/log.csv"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "#from foo import BAR\n", "#\n", "def calculator(num1, operation, num2):\n", " if operation == \"add\":\n", " return num1 + num2\n", " elif operation == \"subtract\":\n", " return num1 - num2\n", " elif operation == \"multiply\":\n", " return num1 * num2\n", " elif operation == \"divide\":\n", " if num2 == 0:\n", " raise gr.Error(\"Cannot divide by zero!\")\n", " return num1 / num2\n", "\n", "demo = gr.Interface(\n", " calculator,\n", " [\n", " \"number\", \n", " gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n", " \"number\"\n", " ],\n", " \"number\",\n", " examples=[\n", " [45, \"add\", 3],\n", " [3.14, \"divide\", 2],\n", " [144, \"multiply\", 2.5],\n", " [0, \"subtract\", 1.2],\n", " ],\n", " title=\"Toy Calculator\",\n", " description=\"Here's a sample toy calculator. Allows you to calculate things like $2+2=4$\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/calculator/run.py b/demo/calculator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ee04812fac61aa54de6f73d6cb1baff35110149
--- /dev/null
+++ b/demo/calculator/run.py
@@ -0,0 +1,35 @@
+import gradio as gr
+#from foo import BAR
+#
+def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ if num2 == 0:
+ raise gr.Error("Cannot divide by zero!")
+ return num1 / num2
+
+demo = gr.Interface(
+ calculator,
+ [
+ "number",
+ gr.Radio(["add", "subtract", "multiply", "divide"]),
+ "number"
+ ],
+ "number",
+ examples=[
+ [45, "add", 3],
+ [3.14, "divide", 2],
+ [144, "multiply", 2.5],
+ [0, "subtract", 1.2],
+ ],
+ title="Toy Calculator",
+ description="Here's a sample toy calculator. Allows you to calculate things like $2+2=4$",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/calculator/screenshot.gif b/demo/calculator/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8ae0d0494adf069b4e23cf30956b43262258021c
--- /dev/null
+++ b/demo/calculator/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3698fb03b6507ff954de47559f6830dfff88aa66487d2029a9bcf1c2f3762e08
+size 5718090
diff --git a/demo/calculator_blocks/run.ipynb b/demo/calculator_blocks/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..85f90aa55baba269431a5252adf692c0eb58dafa
--- /dev/null
+++ b/demo/calculator_blocks/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: calculator_blocks"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def calculator(num1, operation, num2):\n", " if operation == \"add\":\n", " return num1 + num2\n", " elif operation == \"subtract\":\n", " return num1 - num2\n", " elif operation == \"multiply\":\n", " return num1 * num2\n", " elif operation == \"divide\":\n", " return num1 / num2\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " num_1 = gr.Number(value=4)\n", " operation = gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"])\n", " num_2 = gr.Number(value=0)\n", " submit_btn = gr.Button(value=\"Calculate\")\n", " with gr.Column():\n", " result = gr.Number()\n", "\n", " submit_btn.click(calculator, inputs=[num_1, operation, num_2], outputs=[result], api_name=False)\n", " examples = gr.Examples(examples=[[5, \"add\", 3],\n", " [4, \"divide\", 2],\n", " [-4, \"multiply\", 2.5],\n", " [0, \"subtract\", 1.2]],\n", " inputs=[num_1, operation, num_2])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch(show_api=False)"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/calculator_blocks/run.py b/demo/calculator_blocks/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..21b47b94bd1a9b318cdc3a4efbc80fa9a96bdb9a
--- /dev/null
+++ b/demo/calculator_blocks/run.py
@@ -0,0 +1,33 @@
+import gradio as gr
+
+
+def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ return num1 / num2
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ num_1 = gr.Number(value=4)
+ operation = gr.Radio(["add", "subtract", "multiply", "divide"])
+ num_2 = gr.Number(value=0)
+ submit_btn = gr.Button(value="Calculate")
+ with gr.Column():
+ result = gr.Number()
+
+ submit_btn.click(calculator, inputs=[num_1, operation, num_2], outputs=[result], api_name=False)
+ examples = gr.Examples(examples=[[5, "add", 3],
+ [4, "divide", 2],
+ [-4, "multiply", 2.5],
+ [0, "subtract", 1.2]],
+ inputs=[num_1, operation, num_2])
+
+if __name__ == "__main__":
+ demo.launch(show_api=False)
\ No newline at end of file
diff --git a/demo/calculator_blocks_cached/run.ipynb b/demo/calculator_blocks_cached/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5ca1b4d3af8f5265f05c839bc575277c7abdb8d8
--- /dev/null
+++ b/demo/calculator_blocks_cached/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: calculator_blocks_cached"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def calculator(num1, operation, num2):\n", " if operation == \"add\":\n", " return num1 + num2\n", " elif operation == \"subtract\":\n", " return num1 - num2\n", " elif operation == \"multiply\":\n", " return num1 * num2\n", " elif operation == \"divide\":\n", " return num1 / num2\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " num_1 = gr.Number()\n", " operation = gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"])\n", " num_2 = gr.Number()\n", " submit_btn = gr.Button(value=\"Calculate\")\n", " with gr.Column():\n", " result = gr.Number()\n", "\n", " submit_btn.click(calculator, inputs=[num_1, operation, num_2], outputs=[result])\n", " examples = gr.Examples(examples=[[5, \"add\", 3],\n", " [4, \"divide\", 2],\n", " [-4, \"multiply\", 2.5],\n", " [0, \"subtract\", 1.2]],\n", " inputs=[num_1, operation, num_2],\n", " outputs=[result],\n", " fn=calculator,\n", " cache_examples=True)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/calculator_blocks_cached/run.py b/demo/calculator_blocks_cached/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..084884b1d99eccb8021095d729b99683a2c33436
--- /dev/null
+++ b/demo/calculator_blocks_cached/run.py
@@ -0,0 +1,36 @@
+import gradio as gr
+
+
+def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ return num1 / num2
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ num_1 = gr.Number()
+ operation = gr.Radio(["add", "subtract", "multiply", "divide"])
+ num_2 = gr.Number()
+ submit_btn = gr.Button(value="Calculate")
+ with gr.Column():
+ result = gr.Number()
+
+ submit_btn.click(calculator, inputs=[num_1, operation, num_2], outputs=[result])
+ examples = gr.Examples(examples=[[5, "add", 3],
+ [4, "divide", 2],
+ [-4, "multiply", 2.5],
+ [0, "subtract", 1.2]],
+ inputs=[num_1, operation, num_2],
+ outputs=[result],
+ fn=calculator,
+ cache_examples=True)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/calculator_list_and_dict/run.ipynb b/demo/calculator_list_and_dict/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c967498f3f82cf367301ab7f0a583112363792ed
--- /dev/null
+++ b/demo/calculator_list_and_dict/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: calculator_list_and_dict"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " a = gr.Number(label=\"a\")\n", " b = gr.Number(label=\"b\")\n", " with gr.Row():\n", " add_btn = gr.Button(\"Add\")\n", " sub_btn = gr.Button(\"Subtract\")\n", " c = gr.Number(label=\"sum\")\n", "\n", " def add(num1, num2):\n", " return num1 + num2\n", " add_btn.click(add, inputs=[a, b], outputs=c)\n", "\n", " def sub(data):\n", " return data[a] - data[b]\n", " sub_btn.click(sub, inputs={a, b}, outputs=c)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/calculator_list_and_dict/run.py b/demo/calculator_list_and_dict/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..22b4d5b0386c062de8f5731dac27e9009bf0fdb9
--- /dev/null
+++ b/demo/calculator_list_and_dict/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ a = gr.Number(label="a")
+ b = gr.Number(label="b")
+ with gr.Row():
+ add_btn = gr.Button("Add")
+ sub_btn = gr.Button("Subtract")
+ c = gr.Number(label="sum")
+
+ def add(num1, num2):
+ return num1 + num2
+ add_btn.click(add, inputs=[a, b], outputs=c)
+
+ def sub(data):
+ return data[a] - data[b]
+ sub_btn.click(sub, inputs={a, b}, outputs=c)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/calculator_live/run.ipynb b/demo/calculator_live/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a5c2131ad1b4be04bbe93570785874ed70ee772a
--- /dev/null
+++ b/demo/calculator_live/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: calculator_live"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def calculator(num1, operation, num2):\n", " if operation == \"add\":\n", " return num1 + num2\n", " elif operation == \"subtract\":\n", " return num1 - num2\n", " elif operation == \"multiply\":\n", " return num1 * num2\n", " elif operation == \"divide\":\n", " return num1 / num2\n", "\n", "demo = gr.Interface(\n", " calculator,\n", " [\n", " \"number\",\n", " gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n", " \"number\"\n", " ],\n", " \"number\",\n", " live=True,\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/calculator_live/run.py b/demo/calculator_live/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..09856c099eb6ffa080b355d09bc3ecebe3ea714c
--- /dev/null
+++ b/demo/calculator_live/run.py
@@ -0,0 +1,24 @@
+import gradio as gr
+
+def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ return num1 / num2
+
+demo = gr.Interface(
+ calculator,
+ [
+ "number",
+ gr.Radio(["add", "subtract", "multiply", "divide"]),
+ "number"
+ ],
+ "number",
+ live=True,
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/calculator_live/screenshot.gif b/demo/calculator_live/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b6df1ce765fa746285afdf995958687ab9a8d6a0
Binary files /dev/null and b/demo/calculator_live/screenshot.gif differ
diff --git a/demo/cancel_events/run.ipynb b/demo/cancel_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d821e0034d66a16c4d7bfcb40cc2d5287ef92ab1
--- /dev/null
+++ b/demo/cancel_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: cancel_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import time\n", "import gradio as gr\n", "\n", "\n", "def fake_diffusion(steps):\n", " for i in range(steps):\n", " print(f\"Current step: {i}\")\n", " time.sleep(0.5)\n", " yield str(i)\n", "\n", "\n", "def long_prediction(*args, **kwargs):\n", " time.sleep(10)\n", " return 42\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " n = gr.Slider(1, 10, value=9, step=1, label=\"Number Steps\")\n", " run = gr.Button(value=\"Start Iterating\")\n", " output = gr.Textbox(label=\"Iterative Output\")\n", " stop = gr.Button(value=\"Stop Iterating\")\n", " with gr.Column():\n", " textbox = gr.Textbox(label=\"Prompt\")\n", " prediction = gr.Number(label=\"Expensive Calculation\")\n", " run_pred = gr.Button(value=\"Run Expensive Calculation\")\n", " with gr.Column():\n", " cancel_on_change = gr.Textbox(label=\"Cancel Iteration and Expensive Calculation on Change\")\n", " cancel_on_submit = gr.Textbox(label=\"Cancel Iteration and Expensive Calculation on Submit\")\n", " echo = gr.Textbox(label=\"Echo\")\n", " with gr.Row():\n", " with gr.Column():\n", " image = gr.Image(sources=[\"webcam\"], label=\"Cancel on clear\", interactive=True)\n", " with gr.Column():\n", " video = gr.Video(sources=[\"webcam\"], label=\"Cancel on start recording\", interactive=True)\n", "\n", " click_event = run.click(fake_diffusion, n, output)\n", " stop.click(fn=None, inputs=None, outputs=None, cancels=[click_event])\n", " pred_event = run_pred.click(fn=long_prediction, inputs=[textbox], outputs=prediction)\n", "\n", " cancel_on_change.change(None, None, None, cancels=[click_event, pred_event])\n", " cancel_on_submit.submit(lambda s: s, cancel_on_submit, echo, cancels=[click_event, pred_event])\n", " image.clear(None, None, None, cancels=[click_event, pred_event])\n", " video.start_recording(None, None, None, cancels=[click_event, pred_event])\n", "\n", " demo.queue(max_size=20)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/cancel_events/run.py b/demo/cancel_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..cbc43e36cf3f52e93200c9b6ce5c8e32b9e00ed7
--- /dev/null
+++ b/demo/cancel_events/run.py
@@ -0,0 +1,50 @@
+import time
+import gradio as gr
+
+
+def fake_diffusion(steps):
+ for i in range(steps):
+ print(f"Current step: {i}")
+ time.sleep(0.5)
+ yield str(i)
+
+
+def long_prediction(*args, **kwargs):
+ time.sleep(10)
+ return 42
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ n = gr.Slider(1, 10, value=9, step=1, label="Number Steps")
+ run = gr.Button(value="Start Iterating")
+ output = gr.Textbox(label="Iterative Output")
+ stop = gr.Button(value="Stop Iterating")
+ with gr.Column():
+ textbox = gr.Textbox(label="Prompt")
+ prediction = gr.Number(label="Expensive Calculation")
+ run_pred = gr.Button(value="Run Expensive Calculation")
+ with gr.Column():
+ cancel_on_change = gr.Textbox(label="Cancel Iteration and Expensive Calculation on Change")
+ cancel_on_submit = gr.Textbox(label="Cancel Iteration and Expensive Calculation on Submit")
+ echo = gr.Textbox(label="Echo")
+ with gr.Row():
+ with gr.Column():
+ image = gr.Image(sources=["webcam"], label="Cancel on clear", interactive=True)
+ with gr.Column():
+ video = gr.Video(sources=["webcam"], label="Cancel on start recording", interactive=True)
+
+ click_event = run.click(fake_diffusion, n, output)
+ stop.click(fn=None, inputs=None, outputs=None, cancels=[click_event])
+ pred_event = run_pred.click(fn=long_prediction, inputs=[textbox], outputs=prediction)
+
+ cancel_on_change.change(None, None, None, cancels=[click_event, pred_event])
+ cancel_on_submit.submit(lambda s: s, cancel_on_submit, echo, cancels=[click_event, pred_event])
+ image.clear(None, None, None, cancels=[click_event, pred_event])
+ video.start_recording(None, None, None, cancels=[click_event, pred_event])
+
+ demo.queue(max_size=20)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/change_vs_input/files/cantina.wav b/demo/change_vs_input/files/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/change_vs_input/files/cantina.wav differ
diff --git a/demo/change_vs_input/files/lion.jpg b/demo/change_vs_input/files/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/change_vs_input/files/lion.jpg differ
diff --git a/demo/change_vs_input/files/world.mp4 b/demo/change_vs_input/files/world.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..efdda67248b11de0c703f6809267eb218785ac33
Binary files /dev/null and b/demo/change_vs_input/files/world.mp4 differ
diff --git a/demo/change_vs_input/run.ipynb b/demo/change_vs_input/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..49df4f8a00a17042b9e4105b0e5d04ea71d9295e
--- /dev/null
+++ b/demo/change_vs_input/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: change_vs_input"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/change_vs_input/files/cantina.wav\n", "!wget -q -O files/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/change_vs_input/files/lion.jpg\n", "!wget -q -O files/world.mp4 https://github.com/gradio-app/gradio/raw/main/demo/change_vs_input/files/world.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " set_button = gr.Button(\"Set Values\")\n", " with gr.Row():\n", " with gr.Column(min_width=200):\n", " gr.Markdown(\"# Enter Here\")\n", " text = gr.Textbox()\n", " num = gr.Number()\n", " slider = gr.Slider()\n", " checkbox = gr.Checkbox()\n", " checkbox_group = gr.CheckboxGroup([\"a\", \"b\", \"c\"])\n", " radio = gr.Radio([\"a\", \"b\", \"c\"])\n", " dropdown = gr.Dropdown([\"a\", \"b\", \"c\"])\n", " colorpicker = gr.ColorPicker()\n", " code = gr.Code()\n", " dataframe = gr.Dataframe()\n", " image = gr.Image(elem_id=\"image-original\")\n", " audio = gr.Audio(elem_id=\"audio-original\")\n", " video = gr.Video(elem_id=\"video-original\")\n", "\n", " with gr.Column(min_width=200):\n", " gr.Markdown(\"# ON:INPUT/UPLOAD\")\n", " text_in = gr.Textbox()\n", " num_in = gr.Number()\n", " slider_in = gr.Slider()\n", " checkbox_in = gr.Checkbox()\n", " checkbox_group_in = gr.CheckboxGroup([\"a\", \"b\", \"c\"])\n", " radio_in = gr.Radio([\"a\", \"b\", \"c\"])\n", " dropdown_in = gr.Dropdown([\"a\", \"b\", \"c\"])\n", " colorpicker_in = gr.ColorPicker()\n", " code_in = gr.Code()\n", " dataframe_in = gr.Dataframe()\n", " image_up = gr.Image(elem_id=\"image-upload\")\n", " audio_up = gr.Audio(elem_id=\"audio-upload\")\n", " video_up = gr.Video(elem_id=\"video-upload\")\n", "\n", " with gr.Column(min_width=200):\n", " gr.Markdown(\"# ON:CHANGE\")\n", " text_ch = gr.Textbox()\n", " num_ch = gr.Number()\n", " slider_ch = gr.Slider()\n", " checkbox_ch = gr.Checkbox()\n", " checkbox_group_ch = gr.CheckboxGroup([\"a\", \"b\", \"c\"])\n", " radio_ch = gr.Radio([\"a\", \"b\", \"c\"])\n", " dropdown_ch = gr.Dropdown([\"a\", \"b\", \"c\"])\n", " colorpicker_ch = gr.ColorPicker()\n", " code_ch = gr.Code()\n", " dataframe_ch = gr.Dataframe()\n", " image_ch = gr.Image(elem_id=\"image-change\")\n", " audio_ch = gr.Audio(elem_id=\"audio-change\")\n", " video_ch = gr.Video(elem_id=\"video-change\")\n", "\n", " with gr.Column(min_width=200):\n", " gr.Markdown(\"# ON:CHANGE x2\")\n", " text_ch2 = gr.Textbox()\n", " num_ch2 = gr.Number()\n", " slider_ch2 = gr.Slider()\n", " checkbox_ch2 = gr.Checkbox()\n", " checkbox_group_ch2 = gr.CheckboxGroup([\"a\", \"b\", \"c\"])\n", " radio_ch2 = gr.Radio([\"a\", \"b\", \"c\"])\n", " dropdown_ch2 = gr.Dropdown([\"a\", \"b\", \"c\"])\n", " colorpicker_ch2 = gr.ColorPicker()\n", " code_ch2 = gr.Code()\n", " dataframe_ch2 = gr.Dataframe()\n", " image_ch2 = gr.Image(elem_id=\"image-change-2\")\n", " audio_ch2 = gr.Audio(elem_id=\"audio-change-2\")\n", " video_ch2 = gr.Video(elem_id=\"video-change-2\")\n", "\n", " counter = gr.Number(label=\"Change counter\")\n", "\n", " lion = os.path.join(os.path.abspath(''), \"files/lion.jpg\")\n", " cantina = os.path.join(os.path.abspath(''), \"files/cantina.wav\")\n", " world = os.path.join(os.path.abspath(''), \"files/world.mp4\")\n", "\n", " set_button.click(\n", " lambda: [\"asdf\", 555, 12, True, [\"a\", \"c\"], \"b\", \"b\", \"#FF0000\", \"import gradio as gr\", [[\"a\", \"b\", \"c\", \"d\"], [\"1\", \"2\", \"3\", \"4\"]], lion, cantina, world], \n", " None, \n", " [text, num, slider, checkbox, checkbox_group, radio, dropdown, colorpicker, code, dataframe, image, audio, video])\n", "\n", " text.input(lambda x:x, text, text_in)\n", " num.input(lambda x:x, num, num_in)\n", " slider.input(lambda x:x, slider, slider_in)\n", " checkbox.input(lambda x:x, checkbox, checkbox_in)\n", " checkbox_group.input(lambda x:x, checkbox_group, checkbox_group_in)\n", " radio.input(lambda x:x, radio, radio_in)\n", " dropdown.input(lambda x:x, dropdown, dropdown_in)\n", " colorpicker.input(lambda x:x, colorpicker, colorpicker_in)\n", " code.input(lambda x:x, code, code_in)\n", " dataframe.input(lambda x:x, dataframe, dataframe_in)\n", " image.upload(lambda x:x, image, image_up)\n", " audio.upload(lambda x:x, audio, audio_up)\n", " video.upload(lambda x:x, video, video_up)\n", "\n", " text.change(lambda x,y:(x,y+1), [text, counter], [text_ch, counter])\n", " num.change(lambda x,y:(x, y+1), [num, counter], [num_ch, counter])\n", " slider.change(lambda x,y:(x, y+1), [slider, counter], [slider_ch, counter])\n", " checkbox.change(lambda x,y:(x, y+1), [checkbox, counter], [checkbox_ch, counter])\n", " checkbox_group.change(lambda x,y:(x, y+1), [checkbox_group, counter], [checkbox_group_ch, counter])\n", " radio.change(lambda x,y:(x, y+1), [radio, counter], [radio_ch, counter])\n", " dropdown.change(lambda x,y:(x, y+1), [dropdown, counter], [dropdown_ch, counter])\n", " colorpicker.change(lambda x,y:(x, y+1), [colorpicker, counter], [colorpicker_ch, counter])\n", " code.change(lambda x,y:(x, y+1), [code, counter], [code_ch, counter])\n", " dataframe.change(lambda x,y:(x, y+1), [dataframe, counter], [dataframe_ch, counter])\n", " image.change(lambda x,y:(x, y+1), [image, counter], [image_ch, counter])\n", " audio.change(lambda x,y:(x, y+1), [audio, counter], [audio_ch, counter])\n", " video.change(lambda x,y:(x, y+1), [video, counter], [video_ch, counter])\n", "\n", " text_ch.change(lambda x:x, text_ch, text_ch2)\n", " num_ch.change(lambda x:x, num_ch, num_ch2)\n", " slider_ch.change(lambda x:x, slider_ch, slider_ch2)\n", " checkbox_ch.change(lambda x:x, checkbox_ch, checkbox_ch2)\n", " checkbox_group_ch.change(lambda x:x, checkbox_group_ch, checkbox_group_ch2)\n", " radio_ch.change(lambda x:x, radio_ch, radio_ch2)\n", " dropdown_ch.change(lambda x:x, dropdown_ch, dropdown_ch2)\n", " colorpicker_ch.change(lambda x:x, colorpicker_ch, colorpicker_ch2)\n", " code_ch.change(lambda x:x, code_ch, code_ch2)\n", " dataframe_ch.change(lambda x:x, dataframe_ch, dataframe_ch2)\n", " image_ch.change(lambda x:x, image_ch, image_ch2)\n", " audio_ch.change(lambda x:x, audio_ch, audio_ch2)\n", " video_ch.change(lambda x:x, video_ch, video_ch2)\n", " \n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/change_vs_input/run.py b/demo/change_vs_input/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f16adf029dac78e99f9b1aa5c8c428ae97f5cb2c
--- /dev/null
+++ b/demo/change_vs_input/run.py
@@ -0,0 +1,126 @@
+import os
+import gradio as gr
+
+with gr.Blocks() as demo:
+ set_button = gr.Button("Set Values")
+ with gr.Row():
+ with gr.Column(min_width=200):
+ gr.Markdown("# Enter Here")
+ text = gr.Textbox()
+ num = gr.Number()
+ slider = gr.Slider()
+ checkbox = gr.Checkbox()
+ checkbox_group = gr.CheckboxGroup(["a", "b", "c"])
+ radio = gr.Radio(["a", "b", "c"])
+ dropdown = gr.Dropdown(["a", "b", "c"])
+ colorpicker = gr.ColorPicker()
+ code = gr.Code()
+ dataframe = gr.Dataframe()
+ image = gr.Image(elem_id="image-original")
+ audio = gr.Audio(elem_id="audio-original")
+ video = gr.Video(elem_id="video-original")
+
+ with gr.Column(min_width=200):
+ gr.Markdown("# ON:INPUT/UPLOAD")
+ text_in = gr.Textbox()
+ num_in = gr.Number()
+ slider_in = gr.Slider()
+ checkbox_in = gr.Checkbox()
+ checkbox_group_in = gr.CheckboxGroup(["a", "b", "c"])
+ radio_in = gr.Radio(["a", "b", "c"])
+ dropdown_in = gr.Dropdown(["a", "b", "c"])
+ colorpicker_in = gr.ColorPicker()
+ code_in = gr.Code()
+ dataframe_in = gr.Dataframe()
+ image_up = gr.Image(elem_id="image-upload")
+ audio_up = gr.Audio(elem_id="audio-upload")
+ video_up = gr.Video(elem_id="video-upload")
+
+ with gr.Column(min_width=200):
+ gr.Markdown("# ON:CHANGE")
+ text_ch = gr.Textbox()
+ num_ch = gr.Number()
+ slider_ch = gr.Slider()
+ checkbox_ch = gr.Checkbox()
+ checkbox_group_ch = gr.CheckboxGroup(["a", "b", "c"])
+ radio_ch = gr.Radio(["a", "b", "c"])
+ dropdown_ch = gr.Dropdown(["a", "b", "c"])
+ colorpicker_ch = gr.ColorPicker()
+ code_ch = gr.Code()
+ dataframe_ch = gr.Dataframe()
+ image_ch = gr.Image(elem_id="image-change")
+ audio_ch = gr.Audio(elem_id="audio-change")
+ video_ch = gr.Video(elem_id="video-change")
+
+ with gr.Column(min_width=200):
+ gr.Markdown("# ON:CHANGE x2")
+ text_ch2 = gr.Textbox()
+ num_ch2 = gr.Number()
+ slider_ch2 = gr.Slider()
+ checkbox_ch2 = gr.Checkbox()
+ checkbox_group_ch2 = gr.CheckboxGroup(["a", "b", "c"])
+ radio_ch2 = gr.Radio(["a", "b", "c"])
+ dropdown_ch2 = gr.Dropdown(["a", "b", "c"])
+ colorpicker_ch2 = gr.ColorPicker()
+ code_ch2 = gr.Code()
+ dataframe_ch2 = gr.Dataframe()
+ image_ch2 = gr.Image(elem_id="image-change-2")
+ audio_ch2 = gr.Audio(elem_id="audio-change-2")
+ video_ch2 = gr.Video(elem_id="video-change-2")
+
+ counter = gr.Number(label="Change counter")
+
+ lion = os.path.join(os.path.dirname(__file__), "files/lion.jpg")
+ cantina = os.path.join(os.path.dirname(__file__), "files/cantina.wav")
+ world = os.path.join(os.path.dirname(__file__), "files/world.mp4")
+
+ set_button.click(
+ lambda: ["asdf", 555, 12, True, ["a", "c"], "b", "b", "#FF0000", "import gradio as gr", [["a", "b", "c", "d"], ["1", "2", "3", "4"]], lion, cantina, world],
+ None,
+ [text, num, slider, checkbox, checkbox_group, radio, dropdown, colorpicker, code, dataframe, image, audio, video])
+
+ text.input(lambda x:x, text, text_in)
+ num.input(lambda x:x, num, num_in)
+ slider.input(lambda x:x, slider, slider_in)
+ checkbox.input(lambda x:x, checkbox, checkbox_in)
+ checkbox_group.input(lambda x:x, checkbox_group, checkbox_group_in)
+ radio.input(lambda x:x, radio, radio_in)
+ dropdown.input(lambda x:x, dropdown, dropdown_in)
+ colorpicker.input(lambda x:x, colorpicker, colorpicker_in)
+ code.input(lambda x:x, code, code_in)
+ dataframe.input(lambda x:x, dataframe, dataframe_in)
+ image.upload(lambda x:x, image, image_up)
+ audio.upload(lambda x:x, audio, audio_up)
+ video.upload(lambda x:x, video, video_up)
+
+ text.change(lambda x,y:(x,y+1), [text, counter], [text_ch, counter])
+ num.change(lambda x,y:(x, y+1), [num, counter], [num_ch, counter])
+ slider.change(lambda x,y:(x, y+1), [slider, counter], [slider_ch, counter])
+ checkbox.change(lambda x,y:(x, y+1), [checkbox, counter], [checkbox_ch, counter])
+ checkbox_group.change(lambda x,y:(x, y+1), [checkbox_group, counter], [checkbox_group_ch, counter])
+ radio.change(lambda x,y:(x, y+1), [radio, counter], [radio_ch, counter])
+ dropdown.change(lambda x,y:(x, y+1), [dropdown, counter], [dropdown_ch, counter])
+ colorpicker.change(lambda x,y:(x, y+1), [colorpicker, counter], [colorpicker_ch, counter])
+ code.change(lambda x,y:(x, y+1), [code, counter], [code_ch, counter])
+ dataframe.change(lambda x,y:(x, y+1), [dataframe, counter], [dataframe_ch, counter])
+ image.change(lambda x,y:(x, y+1), [image, counter], [image_ch, counter])
+ audio.change(lambda x,y:(x, y+1), [audio, counter], [audio_ch, counter])
+ video.change(lambda x,y:(x, y+1), [video, counter], [video_ch, counter])
+
+ text_ch.change(lambda x:x, text_ch, text_ch2)
+ num_ch.change(lambda x:x, num_ch, num_ch2)
+ slider_ch.change(lambda x:x, slider_ch, slider_ch2)
+ checkbox_ch.change(lambda x:x, checkbox_ch, checkbox_ch2)
+ checkbox_group_ch.change(lambda x:x, checkbox_group_ch, checkbox_group_ch2)
+ radio_ch.change(lambda x:x, radio_ch, radio_ch2)
+ dropdown_ch.change(lambda x:x, dropdown_ch, dropdown_ch2)
+ colorpicker_ch.change(lambda x:x, colorpicker_ch, colorpicker_ch2)
+ code_ch.change(lambda x:x, code_ch, code_ch2)
+ dataframe_ch.change(lambda x:x, dataframe_ch, dataframe_ch2)
+ image_ch.change(lambda x:x, image_ch, image_ch2)
+ audio_ch.change(lambda x:x, audio_ch, audio_ch2)
+ video_ch.change(lambda x:x, video_ch, video_ch2)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/chatbot_component/run.ipynb b/demo/chatbot_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d95d2c5f4f473f3d26ffa818062137363eb90e8d
--- /dev/null
+++ b/demo/chatbot_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Chatbot(value=[[\"Hello World\",\"Hey Gradio!\"],[\"\u2764\ufe0f\",\"\ud83d\ude0d\"],[\"\ud83d\udd25\",\"\ud83e\udd17\"]])\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_component/run.py b/demo/chatbot_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1b5d098fcc1991293e55b944e868d23739206a1
--- /dev/null
+++ b/demo/chatbot_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Chatbot(value=[["Hello World","Hey Gradio!"],["❤️","😍"],["🔥","🤗"]])
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/chatbot_consecutive/run.ipynb b/demo/chatbot_consecutive/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ff489e011a9a6d5056376f4befe64d6d223ddc08
--- /dev/null
+++ b/demo/chatbot_consecutive/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_consecutive"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def user(user_message, history):\n", " return \"\", history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " time.sleep(2)\n", " history[-1][1] = bot_message\n", " return history\n", "\n", " msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", " \n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_consecutive/run.py b/demo/chatbot_consecutive/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b575621406a1168f15b1005b9f8952a9e8e514ca
--- /dev/null
+++ b/demo/chatbot_consecutive/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+import random
+import time
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ msg = gr.Textbox()
+ clear = gr.Button("Clear")
+
+ def user(user_message, history):
+ return "", history + [[user_message, None]]
+
+ def bot(history):
+ bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
+ time.sleep(2)
+ history[-1][1] = bot_message
+ return history
+
+ msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
+ bot, chatbot, chatbot
+ )
+ clear.click(lambda: None, None, chatbot, queue=False)
+
+demo.queue()
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatbot_dialogpt/requirements.txt b/demo/chatbot_dialogpt/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39dab0fdd98d55da5ce06ddf1dacbdbda14b1372
--- /dev/null
+++ b/demo/chatbot_dialogpt/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
\ No newline at end of file
diff --git a/demo/chatbot_dialogpt/run.ipynb b/demo/chatbot_dialogpt/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..650f7abcb90417107506ddd6225777dc5fb73b36
--- /dev/null
+++ b/demo/chatbot_dialogpt/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_dialogpt"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "import torch\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\"microsoft/DialoGPT-medium\")\n", "model = AutoModelForCausalLM.from_pretrained(\"microsoft/DialoGPT-medium\")\n", "\n", "\n", "def user(message, history):\n", " return \"\", history + [[message, None]]\n", "\n", "\n", "def bot(history):\n", " user_message = history[-1][0]\n", " new_user_input_ids = tokenizer.encode(\n", " user_message + tokenizer.eos_token, return_tensors=\"pt\"\n", " )\n", "\n", " # append the new user input tokens to the chat history\n", " bot_input_ids = torch.cat([torch.LongTensor([]), new_user_input_ids], dim=-1)\n", "\n", " # generate a response\n", " response = model.generate(\n", " bot_input_ids, max_length=1000, pad_token_id=tokenizer.eos_token_id\n", " ).tolist()\n", "\n", " # convert the tokens to text, and then split the responses into lines\n", " response = tokenizer.decode(response[0]).split(\"<|endoftext|>\")\n", " response = [\n", " (response[i], response[i + 1]) for i in range(0, len(response) - 1, 2)\n", " ] # convert to tuples of list\n", " history[-1] = response[0]\n", " return history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_dialogpt/run.py b/demo/chatbot_dialogpt/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..8548880ebfea24db753de6e1d354ca1ec0ae90c7
--- /dev/null
+++ b/demo/chatbot_dialogpt/run.py
@@ -0,0 +1,47 @@
+import gradio as gr
+from transformers import AutoModelForCausalLM, AutoTokenizer
+import torch
+
+tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-medium")
+model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-medium")
+
+
+def user(message, history):
+ return "", history + [[message, None]]
+
+
+def bot(history):
+ user_message = history[-1][0]
+ new_user_input_ids = tokenizer.encode(
+ user_message + tokenizer.eos_token, return_tensors="pt"
+ )
+
+ # append the new user input tokens to the chat history
+ bot_input_ids = torch.cat([torch.LongTensor([]), new_user_input_ids], dim=-1)
+
+ # generate a response
+ response = model.generate(
+ bot_input_ids, max_length=1000, pad_token_id=tokenizer.eos_token_id
+ ).tolist()
+
+ # convert the tokens to text, and then split the responses into lines
+ response = tokenizer.decode(response[0]).split("<|endoftext|>")
+ response = [
+ (response[i], response[i + 1]) for i in range(0, len(response) - 1, 2)
+ ] # convert to tuples of list
+ history[-1] = response[0]
+ return history
+
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ msg = gr.Textbox()
+ clear = gr.Button("Clear")
+
+ msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
+ bot, chatbot, chatbot
+ )
+ clear.click(lambda: None, None, chatbot, queue=False)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatbot_dialogpt/screenshot.gif b/demo/chatbot_dialogpt/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..48961ca8d8351eee471ea3c35fdf9c1240f1ed0b
Binary files /dev/null and b/demo/chatbot_dialogpt/screenshot.gif differ
diff --git a/demo/chatbot_dialogpt/screenshot.png b/demo/chatbot_dialogpt/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7d6618a92e0fbd6769d4dd867f06cb39a6b5904
Binary files /dev/null and b/demo/chatbot_dialogpt/screenshot.png differ
diff --git a/demo/chatbot_multimodal/avatar.png b/demo/chatbot_multimodal/avatar.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f1df7156f0a690a2415903061e19c20e24adac4
Binary files /dev/null and b/demo/chatbot_multimodal/avatar.png differ
diff --git a/demo/chatbot_multimodal/run.ipynb b/demo/chatbot_multimodal/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..88a58d34ef537e1018139317d76bb4d1691f24bb
--- /dev/null
+++ b/demo/chatbot_multimodal/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/chatbot_multimodal/avatar.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import time\n", "\n", "# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n", "\n", "\n", "def print_like_dislike(x: gr.LikeData):\n", " print(x.index, x.value, x.liked)\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.Textbox(value=\"\", interactive=False)\n", "\n", "\n", "def add_file(history, file):\n", " history = history + [((file.name,), None)]\n", " return history\n", "\n", "\n", "def bot(history):\n", " response = \"**That's cool!**\"\n", " history[-1][1] = \"\"\n", " for character in response:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(\n", " [],\n", " elem_id=\"chatbot\",\n", " bubble_full_width=False,\n", " avatar_images=(None, (os.path.join(os.path.abspath(''), \"avatar.png\"))),\n", " )\n", "\n", " with gr.Row():\n", " txt = gr.Textbox(\n", " scale=4,\n", " show_label=False,\n", " placeholder=\"Enter text and press enter, or upload an image\",\n", " container=False,\n", " )\n", " btn = gr.UploadButton(\"\ud83d\udcc1\", file_types=[\"image\", \"video\", \"audio\"])\n", "\n", " txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(\n", " bot, chatbot, chatbot, api_name=\"bot_response\"\n", " )\n", " txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)\n", " file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", "\n", " chatbot.like(print_like_dislike, None, None)\n", "\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_multimodal/run.py b/demo/chatbot_multimodal/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..96bbf34c44e4104a7c0a18cf8c18d45411c524cc
--- /dev/null
+++ b/demo/chatbot_multimodal/run.py
@@ -0,0 +1,61 @@
+import gradio as gr
+import os
+import time
+
+# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.
+
+
+def print_like_dislike(x: gr.LikeData):
+ print(x.index, x.value, x.liked)
+
+
+def add_text(history, text):
+ history = history + [(text, None)]
+ return history, gr.Textbox(value="", interactive=False)
+
+
+def add_file(history, file):
+ history = history + [((file.name,), None)]
+ return history
+
+
+def bot(history):
+ response = "**That's cool!**"
+ history[-1][1] = ""
+ for character in response:
+ history[-1][1] += character
+ time.sleep(0.05)
+ yield history
+
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot(
+ [],
+ elem_id="chatbot",
+ bubble_full_width=False,
+ avatar_images=(None, (os.path.join(os.path.dirname(__file__), "avatar.png"))),
+ )
+
+ with gr.Row():
+ txt = gr.Textbox(
+ scale=4,
+ show_label=False,
+ placeholder="Enter text and press enter, or upload an image",
+ container=False,
+ )
+ btn = gr.UploadButton("📁", file_types=["image", "video", "audio"])
+
+ txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(
+ bot, chatbot, chatbot, api_name="bot_response"
+ )
+ txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)
+ file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(
+ bot, chatbot, chatbot
+ )
+
+ chatbot.like(print_like_dislike, None, None)
+
+
+demo.queue()
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatbot_simple/run.ipynb b/demo/chatbot_simple/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9085788db10047c18ae2910d65a64942c1f5af5c
--- /dev/null
+++ b/demo/chatbot_simple/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_simple"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.ClearButton([msg, chatbot])\n", "\n", " def respond(message, chat_history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " chat_history.append((message, bot_message))\n", " time.sleep(2)\n", " return \"\", chat_history\n", "\n", " msg.submit(respond, [msg, chatbot], [msg, chatbot])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_simple/run.py b/demo/chatbot_simple/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..9344665c7332e12e585d51e77758f0ed41b40797
--- /dev/null
+++ b/demo/chatbot_simple/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+import random
+import time
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ msg = gr.Textbox()
+ clear = gr.ClearButton([msg, chatbot])
+
+ def respond(message, chat_history):
+ bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
+ chat_history.append((message, bot_message))
+ time.sleep(2)
+ return "", chat_history
+
+ msg.submit(respond, [msg, chatbot], [msg, chatbot])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatbot_streaming/run.ipynb b/demo/chatbot_streaming/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f93bf5b3ec32838ea92ae0ec61ee9cc5bac64238
--- /dev/null
+++ b/demo/chatbot_streaming/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_streaming"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def user(user_message, history):\n", " return \"\", history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " history[-1][1] = \"\"\n", " for character in bot_message:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", " msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", " \n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatbot_streaming/run.py b/demo/chatbot_streaming/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c559715121ae724880f9b7c337e9bfd0fa520a6
--- /dev/null
+++ b/demo/chatbot_streaming/run.py
@@ -0,0 +1,28 @@
+import gradio as gr
+import random
+import time
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ msg = gr.Textbox()
+ clear = gr.Button("Clear")
+
+ def user(user_message, history):
+ return "", history + [[user_message, None]]
+
+ def bot(history):
+ bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
+ history[-1][1] = ""
+ for character in bot_message:
+ history[-1][1] += character
+ time.sleep(0.05)
+ yield history
+
+ msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
+ bot, chatbot, chatbot
+ )
+ clear.click(lambda: None, None, chatbot, queue=False)
+
+demo.queue()
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatinterface_random_response/run.ipynb b/demo/chatinterface_random_response/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dd95ecee051e2e6b35780e1a0d553b0af95f5534
--- /dev/null
+++ b/demo/chatinterface_random_response/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatinterface_random_response"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import random\n", "import gradio as gr\n", "\n", "def random_response(message, history):\n", " return random.choice([\"Yes\", \"No\"])\n", "\n", "demo = gr.ChatInterface(random_response)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatinterface_random_response/run.py b/demo/chatinterface_random_response/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b060926e1ca20a5e82faa6484b7758c26452ae2
--- /dev/null
+++ b/demo/chatinterface_random_response/run.py
@@ -0,0 +1,10 @@
+import random
+import gradio as gr
+
+def random_response(message, history):
+ return random.choice(["Yes", "No"])
+
+demo = gr.ChatInterface(random_response)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatinterface_random_response/screenshot.gif b/demo/chatinterface_random_response/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f93c1fb612b7b8157806245fc434b9e9b8212365
Binary files /dev/null and b/demo/chatinterface_random_response/screenshot.gif differ
diff --git a/demo/chatinterface_streaming_echo/run.ipynb b/demo/chatinterface_streaming_echo/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7b56e7526db6f378cc209f8f67f691862886e7b6
--- /dev/null
+++ b/demo/chatinterface_streaming_echo/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatinterface_streaming_echo"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import time\n", "import gradio as gr\n", "\n", "def slow_echo(message, history):\n", " for i in range(len(message)):\n", " time.sleep(0.05)\n", " yield \"You typed: \" + message[: i+1]\n", "\n", "demo = gr.ChatInterface(slow_echo).queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatinterface_streaming_echo/run.py b/demo/chatinterface_streaming_echo/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..690e38bcbe949b4bbf0c9738a88353f2cfa82fb9
--- /dev/null
+++ b/demo/chatinterface_streaming_echo/run.py
@@ -0,0 +1,12 @@
+import time
+import gradio as gr
+
+def slow_echo(message, history):
+ for i in range(len(message)):
+ time.sleep(0.05)
+ yield "You typed: " + message[: i+1]
+
+demo = gr.ChatInterface(slow_echo).queue()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/chatinterface_system_prompt/run.ipynb b/demo/chatinterface_system_prompt/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7ad525d719a5af09a9b7cd6a9aa986ecf23cf4a7
--- /dev/null
+++ b/demo/chatinterface_system_prompt/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatinterface_system_prompt"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "def echo(message, history, system_prompt, tokens):\n", " response = f\"System prompt: {system_prompt}\\n Message: {message}.\"\n", " for i in range(min(len(response), int(tokens))):\n", " time.sleep(0.05)\n", " yield response[: i+1]\n", "\n", "demo = gr.ChatInterface(echo, \n", " additional_inputs=[\n", " gr.Textbox(\"You are helpful AI.\", label=\"System Prompt\"), \n", " gr.Slider(10, 100)\n", " ]\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chatinterface_system_prompt/run.py b/demo/chatinterface_system_prompt/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8b1422c4f7889f9d7b5ef74a3a72d705d02a876
--- /dev/null
+++ b/demo/chatinterface_system_prompt/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+import time
+
+def echo(message, history, system_prompt, tokens):
+ response = f"System prompt: {system_prompt}\n Message: {message}."
+ for i in range(min(len(response), int(tokens))):
+ time.sleep(0.05)
+ yield response[: i+1]
+
+demo = gr.ChatInterface(echo,
+ additional_inputs=[
+ gr.Textbox("You are helpful AI.", label="System Prompt"),
+ gr.Slider(10, 100)
+ ]
+ )
+
+if __name__ == "__main__":
+ demo.queue().launch()
\ No newline at end of file
diff --git a/demo/checkbox_component/run.ipynb b/demo/checkbox_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2fa85f1986b0230ce0360856427671fded516baa
--- /dev/null
+++ b/demo/checkbox_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: checkbox_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Checkbox()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/checkbox_component/run.py b/demo/checkbox_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c588a0fac1a77f8911fc0f2d98276a0af92d704
--- /dev/null
+++ b/demo/checkbox_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Checkbox()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/checkboxgroup_component/run.ipynb b/demo/checkboxgroup_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..bac9ffa2c07a2b10e245b39dd79aebe1a00a1d7c
--- /dev/null
+++ b/demo/checkboxgroup_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: checkboxgroup_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.CheckboxGroup(choices=[\"First Choice\", \"Second Choice\", \"Third Choice\"])\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/checkboxgroup_component/run.py b/demo/checkboxgroup_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..90530fd1f8117006ce305474f472dda56fa50714
--- /dev/null
+++ b/demo/checkboxgroup_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.CheckboxGroup(choices=["First Choice", "Second Choice", "Third Choice"])
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/chicago-bikeshare-dashboard/requirements.txt b/demo/chicago-bikeshare-dashboard/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..aa9de6427ec5840dfefcb90d405eac980d9d33e3
--- /dev/null
+++ b/demo/chicago-bikeshare-dashboard/requirements.txt
@@ -0,0 +1,3 @@
+psycopg2
+matplotlib
+SQLAlchemy
diff --git a/demo/chicago-bikeshare-dashboard/run.ipynb b/demo/chicago-bikeshare-dashboard/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a8023631fa47e64ef549ef4e8e772728a1c32be4
--- /dev/null
+++ b/demo/chicago-bikeshare-dashboard/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chicago-bikeshare-dashboard"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio psycopg2 matplotlib SQLAlchemy "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import os\n", "import gradio as gr\n", "import pandas as pd\n", "\n", "DB_USER = os.getenv(\"DB_USER\")\n", "DB_PASSWORD = os.getenv(\"DB_PASSWORD\")\n", "DB_HOST = os.getenv(\"DB_HOST\")\n", "PORT = 8080\n", "DB_NAME = \"bikeshare\"\n", "\n", "connection_string = (\n", " f\"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}?port={PORT}&dbname={DB_NAME}\"\n", ")\n", "\n", "\n", "def get_count_ride_type():\n", " df = pd.read_sql(\n", " \"\"\"\n", " SELECT COUNT(ride_id) as n, rideable_type\n", " FROM rides\n", " GROUP BY rideable_type\n", " ORDER BY n DESC\n", " \"\"\",\n", " con=connection_string,\n", " )\n", " return df\n", "\n", "\n", "def get_most_popular_stations():\n", "\n", " df = pd.read_sql(\n", " \"\"\"\n", " SELECT COUNT(ride_id) as n, MAX(start_station_name) as station\n", " FROM RIDES\n", " WHERE start_station_name is NOT NULL\n", " GROUP BY start_station_id\n", " ORDER BY n DESC\n", " LIMIT 5\n", " \"\"\",\n", " con=connection_string,\n", " )\n", " return df\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Chicago Bike Share Dashboard\n", " \n", " This demo pulls Chicago bike share data for March 2022 from a postgresql database hosted on AWS.\n", " This demo uses psycopg2 but any postgresql client library (SQLAlchemy)\n", " is compatible with gradio.\n", " \n", " Connection credentials are handled by environment variables\n", " defined as secrets in the Space.\n", "\n", " If data were added to the database, the plots in this demo would update\n", " whenever the webpage is reloaded.\n", " \n", " This demo serves as a starting point for your database-connected apps!\n", " \"\"\"\n", " )\n", " with gr.Row():\n", " bike_type = gr.BarPlot(\n", " x=\"rideable_type\",\n", " y='n',\n", " title=\"Number of rides per bicycle type\",\n", " y_title=\"Number of Rides\",\n", " x_title=\"Bicycle Type\",\n", " vertical=False,\n", " tooltip=['rideable_type', \"n\"],\n", " height=300,\n", " width=300,\n", " )\n", " station = gr.BarPlot(\n", " x='station',\n", " y='n',\n", " title=\"Most Popular Stations\",\n", " y_title=\"Number of Rides\",\n", " x_title=\"Station Name\",\n", " vertical=False,\n", " tooltip=['station', 'n'],\n", " height=300,\n", " width=300\n", " )\n", "\n", " demo.load(get_count_ride_type, inputs=None, outputs=bike_type)\n", " demo.load(get_most_popular_stations, inputs=None, outputs=station)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/chicago-bikeshare-dashboard/run.py b/demo/chicago-bikeshare-dashboard/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..79bc1f9464ce0398488352b91c4654d0fe78522b
--- /dev/null
+++ b/demo/chicago-bikeshare-dashboard/run.py
@@ -0,0 +1,91 @@
+import os
+import gradio as gr
+import pandas as pd
+
+DB_USER = os.getenv("DB_USER")
+DB_PASSWORD = os.getenv("DB_PASSWORD")
+DB_HOST = os.getenv("DB_HOST")
+PORT = 8080
+DB_NAME = "bikeshare"
+
+connection_string = (
+ f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}?port={PORT}&dbname={DB_NAME}"
+)
+
+
+def get_count_ride_type():
+ df = pd.read_sql(
+ """
+ SELECT COUNT(ride_id) as n, rideable_type
+ FROM rides
+ GROUP BY rideable_type
+ ORDER BY n DESC
+ """,
+ con=connection_string,
+ )
+ return df
+
+
+def get_most_popular_stations():
+
+ df = pd.read_sql(
+ """
+ SELECT COUNT(ride_id) as n, MAX(start_station_name) as station
+ FROM RIDES
+ WHERE start_station_name is NOT NULL
+ GROUP BY start_station_id
+ ORDER BY n DESC
+ LIMIT 5
+ """,
+ con=connection_string,
+ )
+ return df
+
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+ # Chicago Bike Share Dashboard
+
+ This demo pulls Chicago bike share data for March 2022 from a postgresql database hosted on AWS.
+ This demo uses psycopg2 but any postgresql client library (SQLAlchemy)
+ is compatible with gradio.
+
+ Connection credentials are handled by environment variables
+ defined as secrets in the Space.
+
+ If data were added to the database, the plots in this demo would update
+ whenever the webpage is reloaded.
+
+ This demo serves as a starting point for your database-connected apps!
+ """
+ )
+ with gr.Row():
+ bike_type = gr.BarPlot(
+ x="rideable_type",
+ y='n',
+ title="Number of rides per bicycle type",
+ y_title="Number of Rides",
+ x_title="Bicycle Type",
+ vertical=False,
+ tooltip=['rideable_type', "n"],
+ height=300,
+ width=300,
+ )
+ station = gr.BarPlot(
+ x='station',
+ y='n',
+ title="Most Popular Stations",
+ y_title="Number of Rides",
+ x_title="Station Name",
+ vertical=False,
+ tooltip=['station', 'n'],
+ height=300,
+ width=300
+ )
+
+ demo.load(get_count_ride_type, inputs=None, outputs=bike_type)
+ demo.load(get_most_popular_stations, inputs=None, outputs=station)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/clear_components/__init__.py b/demo/clear_components/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/clear_components/run.ipynb b/demo/clear_components/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5593dd49a72252fe47bdb5935933140ff26d0e39
--- /dev/null
+++ b/demo/clear_components/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: clear_components"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/clear_components/__init__.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from datetime import datetime\n", "import os\n", "import random\n", "import string\n", "import pandas as pd\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "\n", "def random_plot():\n", " start_year = 2020\n", " x = np.arange(start_year, start_year + 5)\n", " year_count = x.shape[0]\n", " plt_format = \"-\"\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " series = np.arange(0, year_count, dtype=float)\n", " series = series**2\n", " series += np.random.rand(year_count)\n", " ax.plot(x, series, plt_format)\n", " return fig\n", "\n", "\n", "images = [\n", " \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\",\n", " \"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80\",\n", " \"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80\",\n", "]\n", "file_dir = os.path.join(os.path.abspath(''), \"..\", \"kitchen_sink\", \"files\")\n", "model3d_dir = os.path.join(os.path.abspath(''), \"..\", \"model3D\", \"files\")\n", "highlighted_text_output_1 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-MISC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistani\",\n", " \"start\": 22,\n", " \"end\": 31,\n", " },\n", "]\n", "highlighted_text_output_2 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistan\",\n", " \"start\": 22,\n", " \"end\": 30,\n", " },\n", "]\n", "\n", "highlighted_text = \"Does Chicago have any Pakistani restaurants\"\n", "\n", "\n", "def random_model3d():\n", " model_3d = random.choice(\n", " [os.path.join(model3d_dir, model) for model in os.listdir(model3d_dir) if model != \"source.txt\"]\n", " )\n", " return model_3d\n", "\n", "\n", "\n", "components = [\n", " gr.Textbox(value=lambda: datetime.now(), label=\"Current Time\"),\n", " gr.Number(value=lambda: random.random(), label=\"Random Percentage\"),\n", " gr.Slider(minimum=0, maximum=100, randomize=True, label=\"Slider with randomize\"),\n", " gr.Slider(\n", " minimum=0,\n", " maximum=1,\n", " value=lambda: random.random(),\n", " label=\"Slider with value func\",\n", " ),\n", " gr.Checkbox(value=lambda: random.random() > 0.5, label=\"Random Checkbox\"),\n", " gr.CheckboxGroup(\n", " choices=[\"a\", \"b\", \"c\", \"d\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\", \"d\"]),\n", " label=\"Random CheckboxGroup\",\n", " ),\n", " gr.Radio(\n", " choices=list(string.ascii_lowercase),\n", " value=lambda: random.choice(string.ascii_lowercase),\n", " ),\n", " gr.Dropdown(\n", " choices=[\"a\", \"b\", \"c\", \"d\", \"e\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\"]),\n", " ),\n", " gr.Image(\n", " value=lambda: random.choice(images)\n", " ),\n", " gr.Video(value=lambda: os.path.join(file_dir, \"world.mp4\")),\n", " gr.Audio(value=lambda: os.path.join(file_dir, \"cantina.wav\")),\n", " gr.File(\n", " value=lambda: random.choice(\n", " [os.path.join(file_dir, img) for img in os.listdir(file_dir)]\n", " )\n", " ),\n", " gr.Dataframe(\n", " value=lambda: pd.DataFrame({\"random_number_rows\": range(5)}, columns=[\"one\", \"two\", \"three\"])\n", " ),\n", " gr.ColorPicker(value=lambda: random.choice([\"#000000\", \"#ff0000\", \"#0000FF\"])),\n", " gr.Label(value=lambda: random.choice([\"Pedestrian\", \"Car\", \"Cyclist\"])),\n", " gr.HighlightedText(\n", " value=lambda: random.choice(\n", " [\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_1},\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_2},\n", " ]\n", " ),\n", " ),\n", " gr.JSON(value=lambda: random.choice([{\"a\": 1}, {\"b\": 2}])),\n", " gr.HTML(\n", " value=lambda: random.choice(\n", " [\n", " 'I am red
',\n", " 'I am blue
',\n", " ]\n", " )\n", " ),\n", " gr.Gallery(\n", " value=lambda: images\n", " ),\n", " gr.Model3D(value=random_model3d),\n", " gr.Plot(value=random_plot),\n", " gr.Markdown(value=lambda: f\"### {random.choice(['Hello', 'Hi', 'Goodbye!'])}\"),\n", "]\n", "\n", "\n", "def evaluate_values(*args):\n", " are_false = []\n", " for a in args:\n", " if isinstance(a, (pd.DataFrame, np.ndarray)):\n", " are_false.append(not a.any().any())\n", " elif isinstance(a, str) and a.startswith(\"#\"):\n", " are_false.append(a == \"#000000\")\n", " else:\n", " are_false.append(not a)\n", " return all(are_false)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " for i, component in enumerate(components):\n", " component.label = f\"component_{str(i).zfill(2)}\"\n", " component.render()\n", " clear = gr.ClearButton(value=\"Clear\", components=components)\n", " result = gr.Textbox(label=\"Are all cleared?\")\n", " hide = gr.Button(value=\"Hide\")\n", " reveal = gr.Button(value=\"Reveal\")\n", " clear_button_and_components = components + [clear]\n", " hide.click(\n", " lambda: [c.__class__(visible=False) for c in clear_button_and_components],\n", " inputs=[],\n", " outputs=clear_button_and_components\n", " )\n", " reveal.click(\n", " lambda: [c.__class__(visible=True) for c in clear_button_and_components],\n", " inputs=[],\n", " outputs=clear_button_and_components\n", " )\n", " get_value = gr.Button(value=\"Get Values\")\n", " get_value.click(evaluate_values, components, result)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/clear_components/run.py b/demo/clear_components/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3965ac64bca7e7e4ed6d93c67739d9f6a5dc5f8c
--- /dev/null
+++ b/demo/clear_components/run.py
@@ -0,0 +1,183 @@
+import gradio as gr
+from datetime import datetime
+import os
+import random
+import string
+import pandas as pd
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+
+def random_plot():
+ start_year = 2020
+ x = np.arange(start_year, start_year + 5)
+ year_count = x.shape[0]
+ plt_format = "-"
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ series = np.arange(0, year_count, dtype=float)
+ series = series**2
+ series += np.random.rand(year_count)
+ ax.plot(x, series, plt_format)
+ return fig
+
+
+images = [
+ "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
+ "https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80",
+ "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
+]
+file_dir = os.path.join(os.path.dirname(__file__), "..", "kitchen_sink", "files")
+model3d_dir = os.path.join(os.path.dirname(__file__), "..", "model3D", "files")
+highlighted_text_output_1 = [
+ {
+ "entity": "I-LOC",
+ "score": 0.9988978,
+ "index": 2,
+ "word": "Chicago",
+ "start": 5,
+ "end": 12,
+ },
+ {
+ "entity": "I-MISC",
+ "score": 0.9958592,
+ "index": 5,
+ "word": "Pakistani",
+ "start": 22,
+ "end": 31,
+ },
+]
+highlighted_text_output_2 = [
+ {
+ "entity": "I-LOC",
+ "score": 0.9988978,
+ "index": 2,
+ "word": "Chicago",
+ "start": 5,
+ "end": 12,
+ },
+ {
+ "entity": "I-LOC",
+ "score": 0.9958592,
+ "index": 5,
+ "word": "Pakistan",
+ "start": 22,
+ "end": 30,
+ },
+]
+
+highlighted_text = "Does Chicago have any Pakistani restaurants"
+
+
+def random_model3d():
+ model_3d = random.choice(
+ [os.path.join(model3d_dir, model) for model in os.listdir(model3d_dir) if model != "source.txt"]
+ )
+ return model_3d
+
+
+
+components = [
+ gr.Textbox(value=lambda: datetime.now(), label="Current Time"),
+ gr.Number(value=lambda: random.random(), label="Random Percentage"),
+ gr.Slider(minimum=0, maximum=100, randomize=True, label="Slider with randomize"),
+ gr.Slider(
+ minimum=0,
+ maximum=1,
+ value=lambda: random.random(),
+ label="Slider with value func",
+ ),
+ gr.Checkbox(value=lambda: random.random() > 0.5, label="Random Checkbox"),
+ gr.CheckboxGroup(
+ choices=["a", "b", "c", "d"],
+ value=lambda: random.choice(["a", "b", "c", "d"]),
+ label="Random CheckboxGroup",
+ ),
+ gr.Radio(
+ choices=list(string.ascii_lowercase),
+ value=lambda: random.choice(string.ascii_lowercase),
+ ),
+ gr.Dropdown(
+ choices=["a", "b", "c", "d", "e"],
+ value=lambda: random.choice(["a", "b", "c"]),
+ ),
+ gr.Image(
+ value=lambda: random.choice(images)
+ ),
+ gr.Video(value=lambda: os.path.join(file_dir, "world.mp4")),
+ gr.Audio(value=lambda: os.path.join(file_dir, "cantina.wav")),
+ gr.File(
+ value=lambda: random.choice(
+ [os.path.join(file_dir, img) for img in os.listdir(file_dir)]
+ )
+ ),
+ gr.Dataframe(
+ value=lambda: pd.DataFrame({"random_number_rows": range(5)}, columns=["one", "two", "three"])
+ ),
+ gr.ColorPicker(value=lambda: random.choice(["#000000", "#ff0000", "#0000FF"])),
+ gr.Label(value=lambda: random.choice(["Pedestrian", "Car", "Cyclist"])),
+ gr.HighlightedText(
+ value=lambda: random.choice(
+ [
+ {"text": highlighted_text, "entities": highlighted_text_output_1},
+ {"text": highlighted_text, "entities": highlighted_text_output_2},
+ ]
+ ),
+ ),
+ gr.JSON(value=lambda: random.choice([{"a": 1}, {"b": 2}])),
+ gr.HTML(
+ value=lambda: random.choice(
+ [
+ 'I am red
',
+ 'I am blue
',
+ ]
+ )
+ ),
+ gr.Gallery(
+ value=lambda: images
+ ),
+ gr.Model3D(value=random_model3d),
+ gr.Plot(value=random_plot),
+ gr.Markdown(value=lambda: f"### {random.choice(['Hello', 'Hi', 'Goodbye!'])}"),
+]
+
+
+def evaluate_values(*args):
+ are_false = []
+ for a in args:
+ if isinstance(a, (pd.DataFrame, np.ndarray)):
+ are_false.append(not a.any().any())
+ elif isinstance(a, str) and a.startswith("#"):
+ are_false.append(a == "#000000")
+ else:
+ are_false.append(not a)
+ return all(are_false)
+
+
+with gr.Blocks() as demo:
+ for i, component in enumerate(components):
+ component.label = f"component_{str(i).zfill(2)}"
+ component.render()
+ clear = gr.ClearButton(value="Clear", components=components)
+ result = gr.Textbox(label="Are all cleared?")
+ hide = gr.Button(value="Hide")
+ reveal = gr.Button(value="Reveal")
+ clear_button_and_components = components + [clear]
+ hide.click(
+ lambda: [c.__class__(visible=False) for c in clear_button_and_components],
+ inputs=[],
+ outputs=clear_button_and_components
+ )
+ reveal.click(
+ lambda: [c.__class__(visible=True) for c in clear_button_and_components],
+ inputs=[],
+ outputs=clear_button_and_components
+ )
+ get_value = gr.Button(value="Get Values")
+ get_value.click(evaluate_values, components, result)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/clearbutton_component/run.ipynb b/demo/clearbutton_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ddcf635a234ac6956b0e604234cf7efeadab2854
--- /dev/null
+++ b/demo/clearbutton_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: clearbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "with gr.Blocks() as demo:\n", " textbox = gr.Textbox(value=\"This is some text\")\n", " gr.ClearButton(textbox)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/clearbutton_component/run.py b/demo/clearbutton_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca927258730743ca026a50e450aba309c435e2f1
--- /dev/null
+++ b/demo/clearbutton_component/run.py
@@ -0,0 +1,9 @@
+import gradio as gr
+
+
+with gr.Blocks() as demo:
+ textbox = gr.Textbox(value="This is some text")
+ gr.ClearButton(textbox)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/clustering/DESCRIPTION.md b/demo/clustering/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..f57e9f25bd22de0cb4c9625203d4b79b747bfbcb
--- /dev/null
+++ b/demo/clustering/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo built with Blocks generates 9 plots based on the input.
\ No newline at end of file
diff --git a/demo/clustering/requirements.txt b/demo/clustering/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..db7c7e4468305565bc82b28927c821b04c299700
--- /dev/null
+++ b/demo/clustering/requirements.txt
@@ -0,0 +1,2 @@
+matplotlib>=3.5.2
+scikit-learn>=1.0.1
diff --git a/demo/clustering/run.ipynb b/demo/clustering/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..46792c26f7988a8ec5b3d040c11c99d635f0e631
--- /dev/null
+++ b/demo/clustering/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: clustering\n", "### This demo built with Blocks generates 9 plots based on the input.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio matplotlib>=3.5.2 scikit-learn>=1.0.1 "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import math\n", "from functools import partial\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from sklearn.cluster import (\n", " AgglomerativeClustering, Birch, DBSCAN, KMeans, MeanShift, OPTICS, SpectralClustering, estimate_bandwidth\n", ")\n", "from sklearn.datasets import make_blobs, make_circles, make_moons\n", "from sklearn.mixture import GaussianMixture\n", "from sklearn.neighbors import kneighbors_graph\n", "from sklearn.preprocessing import StandardScaler\n", "\n", "plt.style.use('seaborn-v0_8')\n", "SEED = 0\n", "MAX_CLUSTERS = 10\n", "N_SAMPLES = 1000\n", "N_COLS = 3\n", "FIGSIZE = 7, 7 # does not affect size in webpage\n", "COLORS = [\n", " 'blue', 'orange', 'green', 'red', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan'\n", "]\n", "if len(COLORS) <= MAX_CLUSTERS:\n", " raise ValueError(\"Not enough different colors for all clusters\")\n", "np.random.seed(SEED)\n", "\n", "\n", "def normalize(X):\n", " return StandardScaler().fit_transform(X)\n", "\n", "def get_regular(n_clusters):\n", " # spiral pattern\n", " centers = [\n", " [0, 0],\n", " [1, 0],\n", " [1, 1],\n", " [0, 1],\n", " [-1, 1],\n", " [-1, 0],\n", " [-1, -1],\n", " [0, -1],\n", " [1, -1],\n", " [2, -1],\n", " ][:n_clusters]\n", " assert len(centers) == n_clusters\n", " X, labels = make_blobs(n_samples=N_SAMPLES, centers=centers, cluster_std=0.25, random_state=SEED)\n", " return normalize(X), labels\n", "\n", "\n", "def get_circles(n_clusters):\n", " X, labels = make_circles(n_samples=N_SAMPLES, factor=0.5, noise=0.05, random_state=SEED)\n", " return normalize(X), labels\n", "\n", "\n", "def get_moons(n_clusters):\n", " X, labels = make_moons(n_samples=N_SAMPLES, noise=0.05, random_state=SEED)\n", " return normalize(X), labels\n", "\n", "\n", "def get_noise(n_clusters):\n", " np.random.seed(SEED)\n", " X, labels = np.random.rand(N_SAMPLES, 2), np.random.randint(0, n_clusters, size=(N_SAMPLES,))\n", " return normalize(X), labels\n", "\n", "\n", "def get_anisotropic(n_clusters):\n", " X, labels = make_blobs(n_samples=N_SAMPLES, centers=n_clusters, random_state=170)\n", " transformation = [[0.6, -0.6], [-0.4, 0.8]]\n", " X = np.dot(X, transformation)\n", " return X, labels\n", "\n", "\n", "def get_varied(n_clusters):\n", " cluster_std = [1.0, 2.5, 0.5, 1.0, 2.5, 0.5, 1.0, 2.5, 0.5, 1.0][:n_clusters]\n", " assert len(cluster_std) == n_clusters\n", " X, labels = make_blobs(\n", " n_samples=N_SAMPLES, centers=n_clusters, cluster_std=cluster_std, random_state=SEED\n", " )\n", " return normalize(X), labels\n", "\n", "\n", "def get_spiral(n_clusters):\n", " # from https://scikit-learn.org/stable/auto_examples/cluster/plot_agglomerative_clustering.html\n", " np.random.seed(SEED)\n", " t = 1.5 * np.pi * (1 + 3 * np.random.rand(1, N_SAMPLES))\n", " x = t * np.cos(t)\n", " y = t * np.sin(t)\n", " X = np.concatenate((x, y))\n", " X += 0.7 * np.random.randn(2, N_SAMPLES)\n", " X = np.ascontiguousarray(X.T)\n", "\n", " labels = np.zeros(N_SAMPLES, dtype=int)\n", " return normalize(X), labels\n", "\n", "\n", "DATA_MAPPING = {\n", " 'regular': get_regular,\n", " 'circles': get_circles,\n", " 'moons': get_moons,\n", " 'spiral': get_spiral,\n", " 'noise': get_noise,\n", " 'anisotropic': get_anisotropic,\n", " 'varied': get_varied,\n", "}\n", "\n", "\n", "def get_groundtruth_model(X, labels, n_clusters, **kwargs):\n", " # dummy model to show true label distribution\n", " class Dummy:\n", " def __init__(self, y):\n", " self.labels_ = labels\n", "\n", " return Dummy(labels)\n", "\n", "\n", "def get_kmeans(X, labels, n_clusters, **kwargs):\n", " model = KMeans(init=\"k-means++\", n_clusters=n_clusters, n_init=10, random_state=SEED)\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_dbscan(X, labels, n_clusters, **kwargs):\n", " model = DBSCAN(eps=0.3)\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_agglomerative(X, labels, n_clusters, **kwargs):\n", " connectivity = kneighbors_graph(\n", " X, n_neighbors=n_clusters, include_self=False\n", " )\n", " # make connectivity symmetric\n", " connectivity = 0.5 * (connectivity + connectivity.T)\n", " model = AgglomerativeClustering(\n", " n_clusters=n_clusters, linkage=\"ward\", connectivity=connectivity\n", " )\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_meanshift(X, labels, n_clusters, **kwargs):\n", " bandwidth = estimate_bandwidth(X, quantile=0.25)\n", " model = MeanShift(bandwidth=bandwidth, bin_seeding=True)\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_spectral(X, labels, n_clusters, **kwargs):\n", " model = SpectralClustering(\n", " n_clusters=n_clusters,\n", " eigen_solver=\"arpack\",\n", " affinity=\"nearest_neighbors\",\n", " )\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_optics(X, labels, n_clusters, **kwargs):\n", " model = OPTICS(\n", " min_samples=7,\n", " xi=0.05,\n", " min_cluster_size=0.1,\n", " )\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_birch(X, labels, n_clusters, **kwargs):\n", " model = Birch(n_clusters=n_clusters)\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "def get_gaussianmixture(X, labels, n_clusters, **kwargs):\n", " model = GaussianMixture(\n", " n_components=n_clusters, covariance_type=\"full\", random_state=SEED,\n", " )\n", " model.set_params(**kwargs)\n", " return model.fit(X)\n", "\n", "\n", "MODEL_MAPPING = {\n", " 'True labels': get_groundtruth_model,\n", " 'KMeans': get_kmeans,\n", " 'DBSCAN': get_dbscan,\n", " 'MeanShift': get_meanshift,\n", " 'SpectralClustering': get_spectral,\n", " 'OPTICS': get_optics,\n", " 'Birch': get_birch,\n", " 'GaussianMixture': get_gaussianmixture,\n", " 'AgglomerativeClustering': get_agglomerative,\n", "}\n", "\n", "\n", "def plot_clusters(ax, X, labels):\n", " set_clusters = set(labels)\n", " set_clusters.discard(-1) # -1 signifiies outliers, which we plot separately\n", " for label, color in zip(sorted(set_clusters), COLORS):\n", " idx = labels == label\n", " if not sum(idx):\n", " continue\n", " ax.scatter(X[idx, 0], X[idx, 1], color=color)\n", "\n", " # show outliers (if any)\n", " idx = labels == -1\n", " if sum(idx):\n", " ax.scatter(X[idx, 0], X[idx, 1], c='k', marker='x')\n", "\n", " ax.grid(None)\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", " return ax\n", "\n", "\n", "def cluster(dataset: str, n_clusters: int, clustering_algorithm: str):\n", " if isinstance(n_clusters, dict):\n", " n_clusters = n_clusters['value']\n", " else:\n", " n_clusters = int(n_clusters)\n", "\n", " X, labels = DATA_MAPPING[dataset](n_clusters)\n", " model = MODEL_MAPPING[clustering_algorithm](X, labels, n_clusters=n_clusters)\n", " if hasattr(model, \"labels_\"):\n", " y_pred = model.labels_.astype(int)\n", " else:\n", " y_pred = model.predict(X)\n", "\n", " fig, ax = plt.subplots(figsize=FIGSIZE)\n", "\n", " plot_clusters(ax, X, y_pred)\n", " ax.set_title(clustering_algorithm, fontsize=16)\n", "\n", " return fig\n", "\n", "\n", "title = \"Clustering with Scikit-learn\"\n", "description = (\n", " \"This example shows how different clustering algorithms work. Simply pick \"\n", " \"the dataset and the number of clusters to see how the clustering algorithms work. \"\n", " \"Colored circles are (predicted) labels and black x are outliers.\"\n", ")\n", "\n", "\n", "def iter_grid(n_rows, n_cols):\n", " # create a grid using gradio Block\n", " for _ in range(n_rows):\n", " with gr.Row():\n", " for _ in range(n_cols):\n", " with gr.Column():\n", " yield\n", "\n", "with gr.Blocks(title=title) as demo:\n", " gr.HTML(f\"{title} \")\n", " gr.Markdown(description)\n", "\n", " input_models = list(MODEL_MAPPING)\n", " input_data = gr.Radio(\n", " list(DATA_MAPPING),\n", " value=\"regular\",\n", " label=\"dataset\"\n", " )\n", " input_n_clusters = gr.Slider(\n", " minimum=1,\n", " maximum=MAX_CLUSTERS,\n", " value=4,\n", " step=1,\n", " label='Number of clusters'\n", " )\n", " n_rows = int(math.ceil(len(input_models) / N_COLS))\n", " counter = 0\n", " for _ in iter_grid(n_rows, N_COLS):\n", " if counter >= len(input_models):\n", " break\n", "\n", " input_model = input_models[counter]\n", " plot = gr.Plot(label=input_model)\n", " fn = partial(cluster, clustering_algorithm=input_model)\n", " input_data.change(fn=fn, inputs=[input_data, input_n_clusters], outputs=plot)\n", " input_n_clusters.change(fn=fn, inputs=[input_data, input_n_clusters], outputs=plot)\n", " counter += 1\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/clustering/run.py b/demo/clustering/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..66a6f301f3bd488c64c937e6fbd5f75799203fdc
--- /dev/null
+++ b/demo/clustering/run.py
@@ -0,0 +1,282 @@
+import gradio as gr
+import math
+from functools import partial
+import matplotlib.pyplot as plt
+import numpy as np
+from sklearn.cluster import (
+ AgglomerativeClustering, Birch, DBSCAN, KMeans, MeanShift, OPTICS, SpectralClustering, estimate_bandwidth
+)
+from sklearn.datasets import make_blobs, make_circles, make_moons
+from sklearn.mixture import GaussianMixture
+from sklearn.neighbors import kneighbors_graph
+from sklearn.preprocessing import StandardScaler
+
+plt.style.use('seaborn-v0_8')
+SEED = 0
+MAX_CLUSTERS = 10
+N_SAMPLES = 1000
+N_COLS = 3
+FIGSIZE = 7, 7 # does not affect size in webpage
+COLORS = [
+ 'blue', 'orange', 'green', 'red', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan'
+]
+if len(COLORS) <= MAX_CLUSTERS:
+ raise ValueError("Not enough different colors for all clusters")
+np.random.seed(SEED)
+
+
+def normalize(X):
+ return StandardScaler().fit_transform(X)
+
+def get_regular(n_clusters):
+ # spiral pattern
+ centers = [
+ [0, 0],
+ [1, 0],
+ [1, 1],
+ [0, 1],
+ [-1, 1],
+ [-1, 0],
+ [-1, -1],
+ [0, -1],
+ [1, -1],
+ [2, -1],
+ ][:n_clusters]
+ assert len(centers) == n_clusters
+ X, labels = make_blobs(n_samples=N_SAMPLES, centers=centers, cluster_std=0.25, random_state=SEED)
+ return normalize(X), labels
+
+
+def get_circles(n_clusters):
+ X, labels = make_circles(n_samples=N_SAMPLES, factor=0.5, noise=0.05, random_state=SEED)
+ return normalize(X), labels
+
+
+def get_moons(n_clusters):
+ X, labels = make_moons(n_samples=N_SAMPLES, noise=0.05, random_state=SEED)
+ return normalize(X), labels
+
+
+def get_noise(n_clusters):
+ np.random.seed(SEED)
+ X, labels = np.random.rand(N_SAMPLES, 2), np.random.randint(0, n_clusters, size=(N_SAMPLES,))
+ return normalize(X), labels
+
+
+def get_anisotropic(n_clusters):
+ X, labels = make_blobs(n_samples=N_SAMPLES, centers=n_clusters, random_state=170)
+ transformation = [[0.6, -0.6], [-0.4, 0.8]]
+ X = np.dot(X, transformation)
+ return X, labels
+
+
+def get_varied(n_clusters):
+ cluster_std = [1.0, 2.5, 0.5, 1.0, 2.5, 0.5, 1.0, 2.5, 0.5, 1.0][:n_clusters]
+ assert len(cluster_std) == n_clusters
+ X, labels = make_blobs(
+ n_samples=N_SAMPLES, centers=n_clusters, cluster_std=cluster_std, random_state=SEED
+ )
+ return normalize(X), labels
+
+
+def get_spiral(n_clusters):
+ # from https://scikit-learn.org/stable/auto_examples/cluster/plot_agglomerative_clustering.html
+ np.random.seed(SEED)
+ t = 1.5 * np.pi * (1 + 3 * np.random.rand(1, N_SAMPLES))
+ x = t * np.cos(t)
+ y = t * np.sin(t)
+ X = np.concatenate((x, y))
+ X += 0.7 * np.random.randn(2, N_SAMPLES)
+ X = np.ascontiguousarray(X.T)
+
+ labels = np.zeros(N_SAMPLES, dtype=int)
+ return normalize(X), labels
+
+
+DATA_MAPPING = {
+ 'regular': get_regular,
+ 'circles': get_circles,
+ 'moons': get_moons,
+ 'spiral': get_spiral,
+ 'noise': get_noise,
+ 'anisotropic': get_anisotropic,
+ 'varied': get_varied,
+}
+
+
+def get_groundtruth_model(X, labels, n_clusters, **kwargs):
+ # dummy model to show true label distribution
+ class Dummy:
+ def __init__(self, y):
+ self.labels_ = labels
+
+ return Dummy(labels)
+
+
+def get_kmeans(X, labels, n_clusters, **kwargs):
+ model = KMeans(init="k-means++", n_clusters=n_clusters, n_init=10, random_state=SEED)
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_dbscan(X, labels, n_clusters, **kwargs):
+ model = DBSCAN(eps=0.3)
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_agglomerative(X, labels, n_clusters, **kwargs):
+ connectivity = kneighbors_graph(
+ X, n_neighbors=n_clusters, include_self=False
+ )
+ # make connectivity symmetric
+ connectivity = 0.5 * (connectivity + connectivity.T)
+ model = AgglomerativeClustering(
+ n_clusters=n_clusters, linkage="ward", connectivity=connectivity
+ )
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_meanshift(X, labels, n_clusters, **kwargs):
+ bandwidth = estimate_bandwidth(X, quantile=0.25)
+ model = MeanShift(bandwidth=bandwidth, bin_seeding=True)
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_spectral(X, labels, n_clusters, **kwargs):
+ model = SpectralClustering(
+ n_clusters=n_clusters,
+ eigen_solver="arpack",
+ affinity="nearest_neighbors",
+ )
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_optics(X, labels, n_clusters, **kwargs):
+ model = OPTICS(
+ min_samples=7,
+ xi=0.05,
+ min_cluster_size=0.1,
+ )
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_birch(X, labels, n_clusters, **kwargs):
+ model = Birch(n_clusters=n_clusters)
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+def get_gaussianmixture(X, labels, n_clusters, **kwargs):
+ model = GaussianMixture(
+ n_components=n_clusters, covariance_type="full", random_state=SEED,
+ )
+ model.set_params(**kwargs)
+ return model.fit(X)
+
+
+MODEL_MAPPING = {
+ 'True labels': get_groundtruth_model,
+ 'KMeans': get_kmeans,
+ 'DBSCAN': get_dbscan,
+ 'MeanShift': get_meanshift,
+ 'SpectralClustering': get_spectral,
+ 'OPTICS': get_optics,
+ 'Birch': get_birch,
+ 'GaussianMixture': get_gaussianmixture,
+ 'AgglomerativeClustering': get_agglomerative,
+}
+
+
+def plot_clusters(ax, X, labels):
+ set_clusters = set(labels)
+ set_clusters.discard(-1) # -1 signifiies outliers, which we plot separately
+ for label, color in zip(sorted(set_clusters), COLORS):
+ idx = labels == label
+ if not sum(idx):
+ continue
+ ax.scatter(X[idx, 0], X[idx, 1], color=color)
+
+ # show outliers (if any)
+ idx = labels == -1
+ if sum(idx):
+ ax.scatter(X[idx, 0], X[idx, 1], c='k', marker='x')
+
+ ax.grid(None)
+ ax.set_xticks([])
+ ax.set_yticks([])
+ return ax
+
+
+def cluster(dataset: str, n_clusters: int, clustering_algorithm: str):
+ if isinstance(n_clusters, dict):
+ n_clusters = n_clusters['value']
+ else:
+ n_clusters = int(n_clusters)
+
+ X, labels = DATA_MAPPING[dataset](n_clusters)
+ model = MODEL_MAPPING[clustering_algorithm](X, labels, n_clusters=n_clusters)
+ if hasattr(model, "labels_"):
+ y_pred = model.labels_.astype(int)
+ else:
+ y_pred = model.predict(X)
+
+ fig, ax = plt.subplots(figsize=FIGSIZE)
+
+ plot_clusters(ax, X, y_pred)
+ ax.set_title(clustering_algorithm, fontsize=16)
+
+ return fig
+
+
+title = "Clustering with Scikit-learn"
+description = (
+ "This example shows how different clustering algorithms work. Simply pick "
+ "the dataset and the number of clusters to see how the clustering algorithms work. "
+ "Colored circles are (predicted) labels and black x are outliers."
+)
+
+
+def iter_grid(n_rows, n_cols):
+ # create a grid using gradio Block
+ for _ in range(n_rows):
+ with gr.Row():
+ for _ in range(n_cols):
+ with gr.Column():
+ yield
+
+with gr.Blocks(title=title) as demo:
+ gr.HTML(f"{title} ")
+ gr.Markdown(description)
+
+ input_models = list(MODEL_MAPPING)
+ input_data = gr.Radio(
+ list(DATA_MAPPING),
+ value="regular",
+ label="dataset"
+ )
+ input_n_clusters = gr.Slider(
+ minimum=1,
+ maximum=MAX_CLUSTERS,
+ value=4,
+ step=1,
+ label='Number of clusters'
+ )
+ n_rows = int(math.ceil(len(input_models) / N_COLS))
+ counter = 0
+ for _ in iter_grid(n_rows, N_COLS):
+ if counter >= len(input_models):
+ break
+
+ input_model = input_models[counter]
+ plot = gr.Plot(label=input_model)
+ fn = partial(cluster, clustering_algorithm=input_model)
+ input_data.change(fn=fn, inputs=[input_data, input_n_clusters], outputs=plot)
+ input_n_clusters.change(fn=fn, inputs=[input_data, input_n_clusters], outputs=plot)
+ counter += 1
+
+demo.launch()
diff --git a/demo/code/file.css b/demo/code/file.css
new file mode 100644
index 0000000000000000000000000000000000000000..abc61b61cbb2045ad539bb1cc23c232a97aab8ee
--- /dev/null
+++ b/demo/code/file.css
@@ -0,0 +1,11 @@
+.class {
+ color: blue;
+}
+
+#id {
+ color: pink;
+}
+
+div {
+ color: purple;
+}
\ No newline at end of file
diff --git a/demo/code/run.ipynb b/demo/code/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..06f147924fcc15631e2a610b2476cfe5bfeaf9cc
--- /dev/null
+++ b/demo/code/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: code"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/code/file.css"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "from time import sleep\n", "\n", "\n", "css_file = os.path.join(os.path.abspath(''), \"file.css\")\n", "\n", "\n", "def set_lang(language):\n", " print(language)\n", " return gr.Code(language=language)\n", "\n", "\n", "def set_lang_from_path():\n", " sleep(1)\n", " return gr.Code((css_file,), language=\"css\")\n", "\n", "\n", "def code(language, code):\n", " return gr.Code(code, language=language)\n", "\n", "\n", "io = gr.Interface(lambda x: x, \"code\", \"code\")\n", "\n", "with gr.Blocks() as demo:\n", " lang = gr.Dropdown(value=\"python\", choices=gr.Code.languages)\n", " with gr.Row():\n", " code_in = gr.Code(\n", " language=\"python\",\n", " label=\"Input\",\n", " value='def all_odd_elements(sequence):\\n \"\"\"Returns every odd element of the sequence.\"\"\"',\n", " )\n", " code_out = gr.Code(label=\"Output\")\n", " btn = gr.Button(\"Run\")\n", " btn_two = gr.Button(\"Load File\")\n", "\n", " lang.change(set_lang, inputs=lang, outputs=code_in)\n", " btn.click(code, inputs=[lang, code_in], outputs=code_out)\n", " btn_two.click(set_lang_from_path, inputs=None, outputs=code_out)\n", " io.render()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/code/run.py b/demo/code/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a2aa6f1ee9bad7a6d248a5951a10821499ae7d1
--- /dev/null
+++ b/demo/code/run.py
@@ -0,0 +1,43 @@
+import gradio as gr
+import os
+from time import sleep
+
+
+css_file = os.path.join(os.path.dirname(__file__), "file.css")
+
+
+def set_lang(language):
+ print(language)
+ return gr.Code(language=language)
+
+
+def set_lang_from_path():
+ sleep(1)
+ return gr.Code((css_file,), language="css")
+
+
+def code(language, code):
+ return gr.Code(code, language=language)
+
+
+io = gr.Interface(lambda x: x, "code", "code")
+
+with gr.Blocks() as demo:
+ lang = gr.Dropdown(value="python", choices=gr.Code.languages)
+ with gr.Row():
+ code_in = gr.Code(
+ language="python",
+ label="Input",
+ value='def all_odd_elements(sequence):\n """Returns every odd element of the sequence."""',
+ )
+ code_out = gr.Code(label="Output")
+ btn = gr.Button("Run")
+ btn_two = gr.Button("Load File")
+
+ lang.change(set_lang, inputs=lang, outputs=code_in)
+ btn.click(code, inputs=[lang, code_in], outputs=code_out)
+ btn_two.click(set_lang_from_path, inputs=None, outputs=code_out)
+ io.render()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/code_component/run.ipynb b/demo/code_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..22ac4a3a17db8f391f490d22df26fd377d68999e
--- /dev/null
+++ b/demo/code_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: code_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Code(\n", " value=\"\"\"def hello_world():\n", " return \"Hello, world!\"\n", " \n", "print(hello_world())\"\"\",\n", " language=\"python\",\n", " interactive=True,\n", " show_label=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/code_component/run.py b/demo/code_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a43aba3c019f06f0db0034369ffd2c9eea8541c
--- /dev/null
+++ b/demo/code_component/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Code(
+ value="""def hello_world():
+ return "Hello, world!"
+
+print(hello_world())""",
+ language="python",
+ interactive=True,
+ show_label=False,
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/color_generator/requirements.txt b/demo/color_generator/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6f1e5232f72befd414bff6f6e653b3182d2b703e
--- /dev/null
+++ b/demo/color_generator/requirements.txt
@@ -0,0 +1,2 @@
+opencv-python
+numpy
\ No newline at end of file
diff --git a/demo/color_generator/run.ipynb b/demo/color_generator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f36577da5d48595c017140833d6dbb5b219acd37
--- /dev/null
+++ b/demo/color_generator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: color_generator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio opencv-python numpy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import cv2\n", "import numpy as np\n", "import random\n", "\n", "\n", "# Convert decimal color to hexadecimal color\n", "def RGB_to_Hex(rgb):\n", " color = \"#\"\n", " for i in rgb:\n", " num = int(i)\n", " color += str(hex(num))[-2:].replace(\"x\", \"0\").upper()\n", " return color\n", "\n", "\n", "# Randomly generate light or dark colors\n", "def random_color(is_light=True):\n", " return (\n", " random.randint(0, 127) + int(is_light) * 128,\n", " random.randint(0, 127) + int(is_light) * 128,\n", " random.randint(0, 127) + int(is_light) * 128,\n", " )\n", "\n", "\n", "def switch_color(color_style):\n", " if color_style == \"light\":\n", " is_light = True\n", " elif color_style == \"dark\":\n", " is_light = False\n", " back_color_ = random_color(is_light) # Randomly generate colors\n", " back_color = RGB_to_Hex(back_color_) # Convert to hexadecimal\n", "\n", " # Draw color pictures.\n", " w, h = 50, 50\n", " img = np.zeros((h, w, 3), np.uint8)\n", " cv2.rectangle(img, (0, 0), (w, h), back_color_, thickness=-1)\n", "\n", " return back_color, back_color, img\n", "\n", "\n", "inputs = [gr.Radio([\"light\", \"dark\"], value=\"light\")]\n", "\n", "outputs = [\n", " gr.ColorPicker(label=\"color\"),\n", " gr.Textbox(label=\"hexadecimal color\"),\n", " gr.Image(type=\"numpy\", label=\"color picture\"),\n", "]\n", "\n", "title = \"Color Generator\"\n", "description = (\n", " \"Click the Submit button, and a dark or light color will be randomly generated.\"\n", ")\n", "\n", "demo = gr.Interface(\n", " fn=switch_color,\n", " inputs=inputs,\n", " outputs=outputs,\n", " title=title,\n", " description=description,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/color_generator/run.py b/demo/color_generator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3b18bd0839fba3897d92660a7eb8bd79d493d2f1
--- /dev/null
+++ b/demo/color_generator/run.py
@@ -0,0 +1,63 @@
+import gradio as gr
+import cv2
+import numpy as np
+import random
+
+
+# Convert decimal color to hexadecimal color
+def RGB_to_Hex(rgb):
+ color = "#"
+ for i in rgb:
+ num = int(i)
+ color += str(hex(num))[-2:].replace("x", "0").upper()
+ return color
+
+
+# Randomly generate light or dark colors
+def random_color(is_light=True):
+ return (
+ random.randint(0, 127) + int(is_light) * 128,
+ random.randint(0, 127) + int(is_light) * 128,
+ random.randint(0, 127) + int(is_light) * 128,
+ )
+
+
+def switch_color(color_style):
+ if color_style == "light":
+ is_light = True
+ elif color_style == "dark":
+ is_light = False
+ back_color_ = random_color(is_light) # Randomly generate colors
+ back_color = RGB_to_Hex(back_color_) # Convert to hexadecimal
+
+ # Draw color pictures.
+ w, h = 50, 50
+ img = np.zeros((h, w, 3), np.uint8)
+ cv2.rectangle(img, (0, 0), (w, h), back_color_, thickness=-1)
+
+ return back_color, back_color, img
+
+
+inputs = [gr.Radio(["light", "dark"], value="light")]
+
+outputs = [
+ gr.ColorPicker(label="color"),
+ gr.Textbox(label="hexadecimal color"),
+ gr.Image(type="numpy", label="color picture"),
+]
+
+title = "Color Generator"
+description = (
+ "Click the Submit button, and a dark or light color will be randomly generated."
+)
+
+demo = gr.Interface(
+ fn=switch_color,
+ inputs=inputs,
+ outputs=outputs,
+ title=title,
+ description=description,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/color_picker/rabbit.png b/demo/color_picker/rabbit.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ccd7618e077d9ac2ed0030f93ccb3a58aea6fa5
Binary files /dev/null and b/demo/color_picker/rabbit.png differ
diff --git a/demo/color_picker/requirements.txt b/demo/color_picker/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5873a2224bf91656bb173e87f56252466b812f4e
--- /dev/null
+++ b/demo/color_picker/requirements.txt
@@ -0,0 +1 @@
+Pillow
\ No newline at end of file
diff --git a/demo/color_picker/run.ipynb b/demo/color_picker/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..83fed85097bad8b1bfc5d1c10fb5770ba4114df8
--- /dev/null
+++ b/demo/color_picker/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: color_picker"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio Pillow"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/color_picker/rabbit.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import os\n", "from PIL import Image, ImageColor\n", "\n", "\n", "def change_color(icon, color):\n", "\n", " \"\"\"\n", " Function that given an icon in .png format changes its color\n", " Args:\n", " icon: Icon whose color needs to be changed.\n", " color: Chosen color with which to edit the input icon.\n", " Returns:\n", " edited_image: Edited icon.\n", " \"\"\"\n", " img = icon.convert(\"LA\")\n", " img = img.convert(\"RGBA\")\n", " image_np = np.array(icon)\n", " _, _, _, alpha = image_np.T\n", " mask = alpha > 0\n", " image_np[..., :-1][mask.T] = ImageColor.getcolor(color, \"RGB\")\n", " edited_image = Image.fromarray(image_np)\n", " return edited_image\n", "\n", "\n", "inputs = [\n", " gr.Image(label=\"icon\", type=\"pil\", image_mode=\"RGBA\"),\n", " gr.ColorPicker(label=\"color\"),\n", "]\n", "outputs = gr.Image(label=\"colored icon\")\n", "\n", "demo = gr.Interface(\n", " fn=change_color,\n", " inputs=inputs,\n", " outputs=outputs,\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"rabbit.png\"), \"#ff0000\"],\n", " [os.path.join(os.path.abspath(''), \"rabbit.png\"), \"#0000FF\"],\n", " ],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/color_picker/run.py b/demo/color_picker/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2e460a852c979c2b5c0e01e7592525176069127
--- /dev/null
+++ b/demo/color_picker/run.py
@@ -0,0 +1,44 @@
+import gradio as gr
+import numpy as np
+import os
+from PIL import Image, ImageColor
+
+
+def change_color(icon, color):
+
+ """
+ Function that given an icon in .png format changes its color
+ Args:
+ icon: Icon whose color needs to be changed.
+ color: Chosen color with which to edit the input icon.
+ Returns:
+ edited_image: Edited icon.
+ """
+ img = icon.convert("LA")
+ img = img.convert("RGBA")
+ image_np = np.array(icon)
+ _, _, _, alpha = image_np.T
+ mask = alpha > 0
+ image_np[..., :-1][mask.T] = ImageColor.getcolor(color, "RGB")
+ edited_image = Image.fromarray(image_np)
+ return edited_image
+
+
+inputs = [
+ gr.Image(label="icon", type="pil", image_mode="RGBA"),
+ gr.ColorPicker(label="color"),
+]
+outputs = gr.Image(label="colored icon")
+
+demo = gr.Interface(
+ fn=change_color,
+ inputs=inputs,
+ outputs=outputs,
+ examples=[
+ [os.path.join(os.path.dirname(__file__), "rabbit.png"), "#ff0000"],
+ [os.path.join(os.path.dirname(__file__), "rabbit.png"), "#0000FF"],
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/color_picker/screenshot.gif b/demo/color_picker/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ce8cdd94721ec0f630b87a0143bddd5ad76e6c7
Binary files /dev/null and b/demo/color_picker/screenshot.gif differ
diff --git a/demo/color_picker/screenshot.png b/demo/color_picker/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..99b747f5ea0b86763d0933155587cddbfc80dd07
Binary files /dev/null and b/demo/color_picker/screenshot.png differ
diff --git a/demo/colorpicker_component/run.ipynb b/demo/colorpicker_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2e41a5c7ff5f2a993c72548e31b5a4ef449d4fa5
--- /dev/null
+++ b/demo/colorpicker_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: colorpicker_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.ColorPicker()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/colorpicker_component/run.py b/demo/colorpicker_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..98d5e9fb98f925c9fd0891353022855a53f6a7ec
--- /dev/null
+++ b/demo/colorpicker_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.ColorPicker()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/concurrency_with_queue/run.ipynb b/demo/concurrency_with_queue/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..30e767e07bd0525ca01982d5f5c2c67b9e3bf34a
--- /dev/null
+++ b/demo/concurrency_with_queue/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: concurrency_with_queue"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "\n", "def say_hello(name):\n", " time.sleep(5)\n", " return f\"Hello {name}!\"\n", "\n", "\n", "with gr.Blocks() as demo:\n", " inp = gr.Textbox()\n", " outp = gr.Textbox()\n", " button = gr.Button()\n", " button.click(say_hello, inp, outp)\n", "\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/concurrency_with_queue/run.py b/demo/concurrency_with_queue/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c98f235e1097fbbabfb5062e3b068e7abe4dc85
--- /dev/null
+++ b/demo/concurrency_with_queue/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+import time
+
+
+def say_hello(name):
+ time.sleep(5)
+ return f"Hello {name}!"
+
+
+with gr.Blocks() as demo:
+ inp = gr.Textbox()
+ outp = gr.Textbox()
+ button = gr.Button()
+ button.click(say_hello, inp, outp)
+
+ demo.launch()
diff --git a/demo/concurrency_without_queue/run.ipynb b/demo/concurrency_without_queue/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5418a82d71c0dc8e5746848185eef3fac418119c
--- /dev/null
+++ b/demo/concurrency_without_queue/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: concurrency_without_queue"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "\n", "def say_hello(name):\n", " time.sleep(5)\n", " return f\"Hello {name}!\"\n", "\n", "\n", "with gr.Blocks() as demo:\n", " inp = gr.Textbox()\n", " outp = gr.Textbox()\n", " button = gr.Button()\n", " button.click(say_hello, inp, outp)\n", "\n", " demo.launch(max_threads=41)\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/concurrency_without_queue/run.py b/demo/concurrency_without_queue/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa3f4458c2be115090d472ee11ca6ebb914f1d6d
--- /dev/null
+++ b/demo/concurrency_without_queue/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+import time
+
+
+def say_hello(name):
+ time.sleep(5)
+ return f"Hello {name}!"
+
+
+with gr.Blocks() as demo:
+ inp = gr.Textbox()
+ outp = gr.Textbox()
+ button = gr.Button()
+ button.click(say_hello, inp, outp)
+
+ demo.launch(max_threads=41)
diff --git a/demo/count_generator/run.ipynb b/demo/count_generator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3a75d90ac0ff7c56705df036f090ff7973eecb66
--- /dev/null
+++ b/demo/count_generator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: count_generator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "def count(n):\n", " for i in range(int(n)):\n", " time.sleep(0.5)\n", " yield i\n", "\n", "def show(n):\n", " return str(list(range(int(n))))\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Column():\n", " num = gr.Number(value=10)\n", " with gr.Row():\n", " count_btn = gr.Button(\"Count\")\n", " list_btn = gr.Button(\"List\")\n", " with gr.Column():\n", " out = gr.Textbox()\n", " \n", " count_btn.click(count, num, out)\n", " list_btn.click(show, num, out)\n", " \n", "demo.queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/count_generator/run.py b/demo/count_generator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6d2d7ee944d080c6cc1be1753c4310cc59e81e
--- /dev/null
+++ b/demo/count_generator/run.py
@@ -0,0 +1,27 @@
+import gradio as gr
+import time
+
+def count(n):
+ for i in range(int(n)):
+ time.sleep(0.5)
+ yield i
+
+def show(n):
+ return str(list(range(int(n))))
+
+with gr.Blocks() as demo:
+ with gr.Column():
+ num = gr.Number(value=10)
+ with gr.Row():
+ count_btn = gr.Button("Count")
+ list_btn = gr.Button("List")
+ with gr.Column():
+ out = gr.Textbox()
+
+ count_btn.click(count, num, out)
+ list_btn.click(show, num, out)
+
+demo.queue()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/custom_path/run.py b/demo/custom_path/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e34af799c5e12d77d924a3190298e055de66d8c
--- /dev/null
+++ b/demo/custom_path/run.py
@@ -0,0 +1,19 @@
+from fastapi import FastAPI
+import gradio as gr
+
+CUSTOM_PATH = "/gradio"
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_main():
+ return {"message": "This is your main app"}
+
+
+io = gr.Interface(lambda x: "Hello, " + x + "!", "textbox", "textbox")
+app = gr.mount_gradio_app(app, io, path=CUSTOM_PATH)
+
+
+# Run this from the terminal as you would normally start a FastAPI app: `uvicorn run:app`
+# and navigate to http://localhost:8000/gradio in your browser.
diff --git a/demo/dashboard/DESCRIPTION.md b/demo/dashboard/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..6bd25eec225bb537134eddf1e519a708a0f3b4af
--- /dev/null
+++ b/demo/dashboard/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo shows how you can build an interactive dashboard with gradio. Click on a python library on the left hand side and then on the right hand side click on the metric you'd like to see plot over time. Data is pulled from HuggingFace Hub datasets.
\ No newline at end of file
diff --git a/demo/dashboard/helpers.py b/demo/dashboard/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..b235cd1b8ddfd9ced23c38aa3a7d306dc3312b7a
--- /dev/null
+++ b/demo/dashboard/helpers.py
@@ -0,0 +1,167 @@
+import collections
+from datetime import datetime
+
+from datasets import DatasetDict, load_dataset
+import numpy as np
+
+datasets = {
+ "stars": load_dataset("open-source-metrics/stars").sort('dates'),
+ "issues": load_dataset("open-source-metrics/issues").sort('dates'),
+ "pip": load_dataset("open-source-metrics/pip").sort('day')
+}
+
+val = 0
+
+
+def _range(e):
+ global val
+ e['range'] = val
+ val += 1
+
+ current_date = datetime.strptime(e['dates'], "%Y-%m-%dT%H:%M:%SZ")
+ first_date = datetime.fromtimestamp(1)
+ week = abs(current_date - first_date).days // 7
+ e['week'] = week
+
+ return e
+
+
+def _ignore_org_members(e):
+ global val
+ e['range_non_org'] = val
+
+ if e['type']['authorAssociation'] != 'MEMBER':
+ val += 1
+
+ return e
+
+stars = {}
+for k, v in datasets['stars'].items():
+ stars[k] = v.map(_range)
+ val = 0
+
+issues = {}
+for k, v in datasets['issues'].items():
+ issues[k] = v.map(_range)
+ val = 0
+ issues[k] = issues[k].map(_ignore_org_members)
+ val = 0
+
+datasets['stars'] = DatasetDict(**stars)
+datasets['issues'] = DatasetDict(**issues)
+
+
+def link_values(library_names, returned_values):
+ previous_values = {library_name: None for library_name in library_names}
+ for library_name in library_names:
+ for i in returned_values.keys():
+ if library_name not in returned_values[i]:
+ returned_values[i][library_name] = previous_values[library_name]
+ else:
+ previous_values[library_name] = returned_values[i][library_name]
+
+ return returned_values
+
+
+def running_mean(x, N, total_length=-1):
+ cumsum = np.cumsum(np.insert(x, 0, 0))
+ to_pad = max(total_length - len(cumsum), 0)
+ return np.pad(cumsum[N:] - cumsum[:-N], (to_pad, 0)) / float(N)
+
+
+def retrieve_pip_installs(library_names, cumulated):
+
+ if cumulated:
+ returned_values = {}
+ for library_name in library_names:
+ for i in datasets['pip'][library_name]:
+ if i['day'] in returned_values:
+ returned_values[i['day']]['Cumulated'] += i['num_downloads']
+ else:
+ returned_values[i['day']] = {'Cumulated': i['num_downloads']}
+
+ library_names = ['Cumulated']
+
+ else:
+ returned_values = {}
+ for library_name in library_names:
+ for i in datasets['pip'][library_name]:
+ if i['day'] in returned_values:
+ returned_values[i['day']][library_name] = i['num_downloads']
+ else:
+ returned_values[i['day']] = {library_name: i['num_downloads']}
+
+ for library_name in library_names:
+ for i in returned_values.keys():
+ if library_name not in returned_values[i]:
+ returned_values[i][library_name] = None
+
+ returned_values = collections.OrderedDict(sorted(returned_values.items()))
+ output = {l: [k[l] for k in returned_values.values()] for l in library_names}
+ output['day'] = list(returned_values.keys())
+ return output
+
+
+def retrieve_stars(libraries, week_over_week):
+ returned_values = {}
+ dataset_dict = datasets['stars']
+
+ for library_name in libraries:
+ dataset = dataset_dict[library_name]
+
+ last_value = 0
+ last_week = dataset[0]['week']
+ for i in dataset:
+ if week_over_week and last_week == i['week']:
+ continue
+ if i['dates'] in returned_values:
+ returned_values[i['dates']][library_name] = i['range'] - last_value
+ else:
+ returned_values[i['dates']] = {library_name: i['range'] - last_value}
+
+ last_value = i['range'] if week_over_week else 0
+ last_week = i['week']
+
+ returned_values = collections.OrderedDict(sorted(returned_values.items()))
+ returned_values = link_values(libraries, returned_values)
+ output = {l: [k[l] for k in returned_values.values()][::-1] for l in libraries}
+ output['day'] = list(returned_values.keys())[::-1]
+
+ # Trim down to a smaller number of points.
+ output = {k: [v for i, v in enumerate(value) if i % int(len(value) / 100) == 0] for k, value in output.items()}
+ return output
+
+
+def retrieve_issues(libraries, exclude_org_members, week_over_week):
+
+ returned_values = {}
+ dataset_dict = datasets['issues']
+ range_id = 'range' if not exclude_org_members else 'range_non_org'
+
+ for library_name in libraries:
+ dataset = dataset_dict[library_name]
+
+ last_value = 0
+ last_week = dataset[0]['week']
+ for i in dataset:
+ if week_over_week and last_week == i['week']:
+ continue
+
+ if i['dates'] in returned_values:
+ returned_values[i['dates']][library_name] = i[range_id] - last_value
+ else:
+ returned_values[i['dates']] = {library_name: i[range_id] - last_value}
+
+ last_value = i[range_id] if week_over_week else 0
+ last_week = i['week']
+
+ returned_values = collections.OrderedDict(sorted(returned_values.items()))
+ returned_values = link_values(libraries, returned_values)
+ output = {l: [k[l] for k in returned_values.values()][::-1] for l in libraries}
+ output['day'] = list(returned_values.keys())[::-1]
+
+ # Trim down to a smaller number of points.
+ output = {
+ k: [v for i, v in enumerate(value) if i % int(len(value) / 100) == 0] for k, value in output.items()
+ }
+ return output
diff --git a/demo/dashboard/requirements.txt b/demo/dashboard/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d42d0ad03bdf8ecf9756a38df5cedf8fe431db79
--- /dev/null
+++ b/demo/dashboard/requirements.txt
@@ -0,0 +1 @@
+plotly
\ No newline at end of file
diff --git a/demo/dashboard/run.ipynb b/demo/dashboard/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ca4d20de07696209a4b3575fcff0f320e3b3b83f
--- /dev/null
+++ b/demo/dashboard/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dashboard\n", "### This demo shows how you can build an interactive dashboard with gradio. Click on a python library on the left hand side and then on the right hand side click on the metric you'd like to see plot over time. Data is pulled from HuggingFace Hub datasets.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/dashboard/helpers.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import plotly.express as px\n", "from helpers import *\n", "\n", "\n", "LIBRARIES = [\"accelerate\", \"datasets\", \"diffusers\", \"evaluate\", \"gradio\", \"hub_docs\",\n", " \"huggingface_hub\", \"optimum\", \"pytorch_image_models\", \"tokenizers\", \"transformers\"]\n", "\n", "\n", "def create_pip_plot(libraries, pip_choices):\n", " if \"Pip\" not in pip_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_pip_installs(libraries, \"Cumulated\" in pip_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Pip installs\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "def create_star_plot(libraries, star_choices):\n", " if \"Stars\" not in star_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_stars(libraries, \"Week over Week\" in star_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Number of stargazers\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "def create_issue_plot(libraries, issue_choices):\n", " if \"Issue\" not in issue_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_issues(libraries,\n", " exclude_org_members=\"Exclude org members\" in issue_choices,\n", " week_over_week=\"Week over Week\" in issue_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Cumulated number of issues, PRs, and comments\",\n", " )\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Markdown(\"## Select libraries to display\")\n", " libraries = gr.CheckboxGroup(choices=LIBRARIES, show_label=False)\n", " with gr.Column():\n", " gr.Markdown(\"## Select graphs to display\")\n", " pip = gr.CheckboxGroup(choices=[\"Pip\", \"Cumulated\"], show_label=False)\n", " stars = gr.CheckboxGroup(choices=[\"Stars\", \"Week over Week\"], show_label=False)\n", " issues = gr.CheckboxGroup(choices=[\"Issue\", \"Exclude org members\", \"week over week\"], show_label=False)\n", " with gr.Row():\n", " fetch = gr.Button(value=\"Fetch\")\n", " with gr.Row():\n", " with gr.Column():\n", " pip_plot = gr.Plot(visible=False)\n", " star_plot = gr.Plot(visible=False)\n", " issue_plot = gr.Plot(visible=False)\n", "\n", " fetch.click(create_pip_plot, inputs=[libraries, pip], outputs=pip_plot)\n", " fetch.click(create_star_plot, inputs=[libraries, stars], outputs=star_plot)\n", " fetch.click(create_issue_plot, inputs=[libraries, issues], outputs=issue_plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dashboard/run.py b/demo/dashboard/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..35835e52bd643483802f0ae732ae2afc881e37e1
--- /dev/null
+++ b/demo/dashboard/run.py
@@ -0,0 +1,71 @@
+import gradio as gr
+import pandas as pd
+import plotly.express as px
+from helpers import *
+
+
+LIBRARIES = ["accelerate", "datasets", "diffusers", "evaluate", "gradio", "hub_docs",
+ "huggingface_hub", "optimum", "pytorch_image_models", "tokenizers", "transformers"]
+
+
+def create_pip_plot(libraries, pip_choices):
+ if "Pip" not in pip_choices:
+ return gr.Plot(visible=False)
+ output = retrieve_pip_installs(libraries, "Cumulated" in pip_choices)
+ df = pd.DataFrame(output).melt(id_vars="day")
+ plot = px.line(df, x="day", y="value", color="variable",
+ title="Pip installs")
+ plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="")
+ return gr.Plot(value=plot, visible=True)
+
+
+def create_star_plot(libraries, star_choices):
+ if "Stars" not in star_choices:
+ return gr.Plot(visible=False)
+ output = retrieve_stars(libraries, "Week over Week" in star_choices)
+ df = pd.DataFrame(output).melt(id_vars="day")
+ plot = px.line(df, x="day", y="value", color="variable",
+ title="Number of stargazers")
+ plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="")
+ return gr.Plot(value=plot, visible=True)
+
+
+def create_issue_plot(libraries, issue_choices):
+ if "Issue" not in issue_choices:
+ return gr.Plot(visible=False)
+ output = retrieve_issues(libraries,
+ exclude_org_members="Exclude org members" in issue_choices,
+ week_over_week="Week over Week" in issue_choices)
+ df = pd.DataFrame(output).melt(id_vars="day")
+ plot = px.line(df, x="day", y="value", color="variable",
+ title="Cumulated number of issues, PRs, and comments",
+ )
+ plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="")
+ return gr.Plot(value=plot, visible=True)
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ gr.Markdown("## Select libraries to display")
+ libraries = gr.CheckboxGroup(choices=LIBRARIES, show_label=False)
+ with gr.Column():
+ gr.Markdown("## Select graphs to display")
+ pip = gr.CheckboxGroup(choices=["Pip", "Cumulated"], show_label=False)
+ stars = gr.CheckboxGroup(choices=["Stars", "Week over Week"], show_label=False)
+ issues = gr.CheckboxGroup(choices=["Issue", "Exclude org members", "week over week"], show_label=False)
+ with gr.Row():
+ fetch = gr.Button(value="Fetch")
+ with gr.Row():
+ with gr.Column():
+ pip_plot = gr.Plot(visible=False)
+ star_plot = gr.Plot(visible=False)
+ issue_plot = gr.Plot(visible=False)
+
+ fetch.click(create_pip_plot, inputs=[libraries, pip], outputs=pip_plot)
+ fetch.click(create_star_plot, inputs=[libraries, stars], outputs=star_plot)
+ fetch.click(create_issue_plot, inputs=[libraries, issues], outputs=issue_plot)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/dataframe_block-ui-test/run.ipynb b/demo/dataframe_block-ui-test/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..62b2ea6c3aafe4a368329c972f3ff70dcf66ffb3
--- /dev/null
+++ b/demo/dataframe_block-ui-test/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_block-ui-test"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " count = gr.Slider(minimum=1, maximum=10, step=1, label=\"count\")\n", " data = gr.DataFrame(\n", " headers=[\"A\", \"B\"], col_count=(2, \"fixed\"), type=\"array\", interactive=True\n", " )\n", " btn = gr.Button(value=\"click\")\n", " btn.click(\n", " fn=lambda cnt: [[str(2 * i), str(2 * i + 1)] for i in range(int(cnt))],\n", " inputs=[count],\n", " outputs=[data],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataframe_block-ui-test/run.py b/demo/dataframe_block-ui-test/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..20f804b0a11479673495b32c400fcb299dcdb78c
--- /dev/null
+++ b/demo/dataframe_block-ui-test/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ count = gr.Slider(minimum=1, maximum=10, step=1, label="count")
+ data = gr.DataFrame(
+ headers=["A", "B"], col_count=(2, "fixed"), type="array", interactive=True
+ )
+ btn = gr.Button(value="click")
+ btn.click(
+ fn=lambda cnt: [[str(2 * i), str(2 * i + 1)] for i in range(int(cnt))],
+ inputs=[count],
+ outputs=[data],
+ )
+
+demo.launch()
diff --git a/demo/dataframe_colorful/run.ipynb b/demo/dataframe_colorful/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..83a30371f132d8bc10e8b1760c0b75be73d55197
--- /dev/null
+++ b/demo/dataframe_colorful/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_colorful"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import pandas as pd \n", "import gradio as gr\n", "\n", "df = pd.DataFrame({\"A\" : [14, 4, 5, 4, 1], \n", "\t\t\t\t\"B\" : [5, 2, 54, 3, 2], \n", "\t\t\t\t\"C\" : [20, 20, 7, 3, 8], \n", "\t\t\t\t\"D\" : [14, 3, 6, 2, 6], \n", "\t\t\t\t\"E\" : [23, 45, 64, 32, 23]}) \n", "\n", "t = df.style.highlight_max(color = 'lightgreen', axis = 0)\n", "\n", "with gr.Blocks() as demo:\n", " gr.Dataframe(t)\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataframe_colorful/run.py b/demo/dataframe_colorful/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb97120438de5ec4214792258bf9b144b9d9974d
--- /dev/null
+++ b/demo/dataframe_colorful/run.py
@@ -0,0 +1,16 @@
+import pandas as pd
+import gradio as gr
+
+df = pd.DataFrame({"A" : [14, 4, 5, 4, 1],
+ "B" : [5, 2, 54, 3, 2],
+ "C" : [20, 20, 7, 3, 8],
+ "D" : [14, 3, 6, 2, 6],
+ "E" : [23, 45, 64, 32, 23]})
+
+t = df.style.highlight_max(color = 'lightgreen', axis = 0)
+
+with gr.Blocks() as demo:
+ gr.Dataframe(t)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/dataframe_component/run.ipynb b/demo/dataframe_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..772d394ece8d43df57d05b96a040980181a9197c
--- /dev/null
+++ b/demo/dataframe_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Dataframe(interactive=True)\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataframe_component/run.py b/demo/dataframe_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..64fd22e2b5a80b8a625364c075858207d4d2cb38
--- /dev/null
+++ b/demo/dataframe_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Dataframe(interactive=True)
+
+demo.launch()
diff --git a/demo/dataframe_datatype/run.ipynb b/demo/dataframe_datatype/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..42654a0b5a6c4162f78ee44c99fa63c1f96ed983
--- /dev/null
+++ b/demo/dataframe_datatype/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_datatype"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import numpy as np\n", "\n", "\n", "def make_dataframe(n_periods):\n", " return pd.DataFrame({\"date_1\": pd.date_range(\"2021-01-01\", periods=n_periods),\n", " \"date_2\": pd.date_range(\"2022-02-15\", periods=n_periods).strftime('%B %d, %Y, %r'),\n", " \"number\": np.random.random(n_periods).astype(np.float64),\n", " \"number_2\": np.random.randint(0, 100, n_periods).astype(np.int32),\n", " \"bool\": [True] * n_periods,\n", " \"markdown\": [\"# Hello\"] * n_periods})\n", "\n", "\n", "demo = gr.Interface(make_dataframe,\n", " gr.Number(precision=0),\n", " gr.Dataframe(datatype=[\"date\", \"date\", \"number\", \"number\", \"bool\", \"markdown\"]))\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataframe_datatype/run.py b/demo/dataframe_datatype/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb9d49bd051a4ac5d4e48fe19c3122d3c3c76d1e
--- /dev/null
+++ b/demo/dataframe_datatype/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+import pandas as pd
+import numpy as np
+
+
+def make_dataframe(n_periods):
+ return pd.DataFrame({"date_1": pd.date_range("2021-01-01", periods=n_periods),
+ "date_2": pd.date_range("2022-02-15", periods=n_periods).strftime('%B %d, %Y, %r'),
+ "number": np.random.random(n_periods).astype(np.float64),
+ "number_2": np.random.randint(0, 100, n_periods).astype(np.int32),
+ "bool": [True] * n_periods,
+ "markdown": ["# Hello"] * n_periods})
+
+
+demo = gr.Interface(make_dataframe,
+ gr.Number(precision=0),
+ gr.Dataframe(datatype=["date", "date", "number", "number", "bool", "markdown"]))
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/dataset/files/Bunny.obj b/demo/dataset/files/Bunny.obj
new file mode 100644
index 0000000000000000000000000000000000000000..9baeb363cce8feb5dd62ecaf8d64a14b6c50ce37
--- /dev/null
+++ b/demo/dataset/files/Bunny.obj
@@ -0,0 +1,7474 @@
+# OBJ file format with ext .obj
+# vertex count = 2503
+# face count = 4968
+v -3.4101800e-003 1.3031957e-001 2.1754370e-002
+v -8.1719160e-002 1.5250145e-001 2.9656090e-002
+v -3.0543480e-002 1.2477885e-001 1.0983400e-003
+v -2.4901590e-002 1.1211138e-001 3.7560240e-002
+v -1.8405680e-002 1.7843055e-001 -2.4219580e-002
+v 1.9067940e-002 1.2144925e-001 3.1968440e-002
+v 6.0412000e-003 1.2494359e-001 3.2652890e-002
+v -1.3469030e-002 1.6299355e-001 -1.2000020e-002
+v -3.4393240e-002 1.7236688e-001 -9.8213000e-004
+v -8.4314160e-002 1.0957263e-001 3.7097300e-003
+v -4.2233540e-002 1.7211574e-001 -4.1799800e-003
+v -6.3308390e-002 1.5660615e-001 -1.3838790e-002
+v -7.6903950e-002 1.6708033e-001 -2.6931360e-002
+v -7.2253920e-002 1.1539550e-001 5.1670300e-002
+v 1.2981330e-002 1.1366375e-001 3.8302950e-002
+v -3.7857280e-002 1.7010102e-001 1.4236000e-003
+v 4.8689400e-003 3.7962370e-002 4.5867630e-002
+v -5.7180550e-002 4.0918830e-002 4.6301340e-002
+v -4.5209070e-002 3.8839100e-002 4.4503770e-002
+v -3.3761490e-002 1.2617876e-001 1.7132300e-003
+v -5.0242270e-002 1.5773747e-001 9.3944500e-003
+v -2.1216950e-002 1.5887938e-001 -4.6923700e-003
+v -5.6472950e-002 1.5778406e-001 8.1786500e-003
+v -5.2802060e-002 4.1319860e-002 4.6169800e-002
+v -4.9960340e-002 4.3101950e-002 4.4462650e-002
+v -2.9748750e-002 3.6539860e-002 5.2493310e-002
+v -3.5438900e-003 4.2659770e-002 4.7541530e-002
+v 4.9304900e-003 4.1982660e-002 4.5723390e-002
+v -3.9088180e-002 1.6872020e-001 -1.1924680e-002
+v -5.6901000e-002 4.5437000e-002 4.3236960e-002
+v -4.1244880e-002 4.3098890e-002 4.2129560e-002
+v -2.6471980e-002 4.5034530e-002 5.1219460e-002
+v -2.1866970e-002 4.4022930e-002 5.3243800e-002
+v -3.6996250e-002 1.6899301e-001 1.3256300e-003
+v -6.7216590e-002 1.6171340e-001 -1.3733710e-002
+v 4.9760060e-002 7.0235220e-002 2.3732020e-002
+v -4.9186640e-002 4.6411230e-002 4.1170040e-002
+v -4.4590380e-002 4.3797990e-002 4.2685460e-002
+v -4.3686470e-002 4.7154500e-002 4.0286310e-002
+v -2.2491950e-002 4.6513620e-002 5.1885310e-002
+v -6.5174200e-003 4.5036200e-002 4.7502780e-002
+v 3.7699000e-004 4.4935790e-002 4.6519930e-002
+v 3.4023920e-002 1.1353879e-001 2.4595280e-002
+v -2.6467900e-002 1.8104250e-001 -8.0811700e-003
+v -1.7533470e-002 4.7964250e-002 4.8829630e-002
+v -7.0012600e-003 4.6416520e-002 4.7485540e-002
+v 5.9862300e-003 4.6689140e-002 4.9073620e-002
+v 9.1007200e-003 4.8474490e-002 4.9353190e-002
+v -3.5453700e-002 1.1244769e-001 3.5055410e-002
+v -7.5983200e-002 1.3820800e-001 4.9216580e-002
+v 3.4838440e-002 4.3153410e-002 2.8954310e-002
+v -5.2655550e-002 4.8494220e-002 3.8731190e-002
+v -4.7378940e-002 4.8456670e-002 3.9126790e-002
+v -3.8933750e-002 4.6364270e-002 4.0364780e-002
+v -2.6468940e-002 4.7816430e-002 4.9322590e-002
+v -2.2365790e-002 4.8073650e-002 5.0126500e-002
+v -1.3373430e-002 4.7892410e-002 4.7883850e-002
+v -1.2193490e-002 4.9470300e-002 4.9484490e-002
+v -6.3364000e-004 4.7193060e-002 4.9136900e-002
+v 2.0656800e-003 5.0104680e-002 5.2290220e-002
+v -2.2749270e-002 4.9883880e-002 4.6605520e-002
+v -1.8002080e-002 4.9917850e-002 4.6947970e-002
+v -7.8036800e-003 5.0169310e-002 5.0988650e-002
+v -2.6843800e-003 5.1247420e-002 5.3186790e-002
+v -6.3875650e-002 1.6140094e-001 -2.0064210e-002
+v 3.2434000e-002 4.5333970e-002 3.0316760e-002
+v -8.8064570e-002 1.2496764e-001 5.7412000e-004
+v -4.1503710e-002 1.6748512e-001 3.2765900e-003
+v -6.4457010e-002 1.5342891e-001 -5.1180400e-003
+v -3.4303190e-002 5.0520150e-002 3.8286020e-002
+v -2.2949400e-002 5.1020650e-002 4.3926450e-002
+v -1.4354710e-002 5.4428200e-002 5.0710310e-002
+v 1.3773100e-003 5.2302710e-002 5.3149010e-002
+v 3.6285000e-003 5.3198640e-002 5.3422710e-002
+v 8.0723800e-003 5.1574140e-002 5.1773560e-002
+v -7.2665890e-002 1.3005582e-001 5.1668200e-002
+v 3.7992780e-002 4.9793200e-002 3.1902020e-002
+v 3.8497260e-002 4.8062400e-002 3.1737450e-002
+v 2.1503510e-002 1.2563988e-001 2.1252620e-002
+v -7.6481330e-002 1.4827412e-001 -8.9376200e-003
+v -8.7240410e-002 1.1967213e-001 -1.7813000e-004
+v -4.3719960e-002 1.6822738e-001 2.3425000e-003
+v -4.0652200e-002 1.2266506e-001 2.6290300e-002
+v -4.6686180e-002 5.4570720e-002 3.7587370e-002
+v -4.4071750e-002 5.1058250e-002 3.8977810e-002
+v -3.8144110e-002 5.0599600e-002 3.9302160e-002
+v -1.9875770e-002 5.1607710e-002 4.6142000e-002
+v -1.6911250e-002 5.1843550e-002 4.8459320e-002
+v -1.6249190e-002 5.4292110e-002 5.0306940e-002
+v -1.0446540e-002 5.3685970e-002 5.1958610e-002
+v -4.3090900e-003 5.4467500e-002 5.3908250e-002
+v 7.8152700e-003 5.5050680e-002 5.2750250e-002
+v 3.7955090e-002 1.0488710e-001 -3.2031800e-003
+v -7.9003790e-002 1.2850550e-001 5.3149340e-002
+v -7.9778990e-002 1.3448894e-001 5.0990290e-002
+v -5.9129700e-002 1.5039712e-001 3.4489540e-002
+v -6.5691790e-002 1.4961818e-001 3.8160980e-002
+v -3.1951660e-002 1.2518394e-001 1.9400580e-002
+v -6.9372590e-002 1.6061775e-001 -9.1905000e-003
+v -4.5225500e-002 1.2935459e-001 2.0377520e-002
+v -4.1879110e-002 5.6164390e-002 3.9796700e-002
+v -3.0614840e-002 5.4412650e-002 3.6694290e-002
+v -2.4787600e-002 5.2606220e-002 4.0839760e-002
+v -2.1588860e-002 5.6836920e-002 4.5467040e-002
+v -2.4264000e-004 5.4536020e-002 5.4641200e-002
+v -8.0900510e-002 1.2558713e-001 5.2155370e-002
+v -2.9996210e-002 1.7811137e-001 -5.2358200e-003
+v 3.5515390e-002 5.0449570e-002 3.1439830e-002
+v 4.3315550e-002 5.2145550e-002 3.2492110e-002
+v -6.3938540e-002 1.5262699e-001 3.4481070e-002
+v -4.4489440e-002 6.1077710e-002 3.9545320e-002
+v -3.8979900e-002 5.7996270e-002 4.0151390e-002
+v -7.9087730e-002 1.7044488e-001 -4.1373170e-002
+v -4.6247300e-003 5.7759650e-002 5.3990710e-002
+v -1.4985500e-003 5.5925480e-002 5.4630800e-002
+v 5.1981700e-003 5.7017990e-002 5.3423530e-002
+v 3.0920000e-005 1.2315746e-001 3.4749660e-002
+v 3.3568300e-002 1.1523716e-001 2.1798410e-002
+v 3.8686300e-002 5.6450590e-002 3.1188930e-002
+v -3.4385780e-002 5.4096000e-002 3.8060290e-002
+v -8.5308300e-003 6.0159420e-002 5.5308950e-002
+v -4.4024000e-004 5.8343410e-002 5.4483410e-002
+v -9.1078730e-002 1.1506037e-001 4.0141810e-002
+v 4.0775480e-002 5.4557490e-002 3.2014740e-002
+v 4.5636880e-002 5.7402620e-002 3.1992220e-002
+v 2.0358850e-002 1.2448747e-001 2.5906340e-002
+v -1.4169700e-002 1.2767892e-001 1.3080500e-003
+v -1.1987590e-002 5.7493210e-002 5.2752420e-002
+v 3.2514500e-003 5.9828640e-002 5.5464300e-002
+v -1.2395240e-002 1.2264726e-001 3.3588280e-002
+v 1.3813780e-002 1.2322188e-001 3.2502590e-002
+v -7.7004310e-002 1.5521281e-001 2.4534770e-002
+v -2.8001360e-002 6.1075420e-002 3.7471210e-002
+v -8.5480000e-004 6.0593520e-002 5.5824810e-002
+v -3.8050200e-002 1.1527068e-001 3.3178540e-002
+v -1.6231340e-002 1.2382942e-001 2.9576990e-002
+v -2.5373550e-002 1.5840012e-001 -1.4801300e-003
+v -6.7818590e-002 1.5454353e-001 3.0233720e-002
+v -4.3082600e-003 6.1418570e-002 5.5688490e-002
+v -3.1958900e-003 1.1912518e-001 3.8349580e-002
+v -6.4292400e-003 1.2201090e-001 3.5740890e-002
+v 4.2312960e-002 5.9099150e-002 3.0848420e-002
+v 4.8510010e-002 6.1780760e-002 3.0347250e-002
+v 5.0412290e-002 6.0312610e-002 3.0245060e-002
+v -3.9185590e-002 6.3074530e-002 4.1382890e-002
+v -3.4448660e-002 6.0780500e-002 3.9543990e-002
+v -1.4746030e-002 6.5583910e-002 5.3730860e-002
+v 2.6645200e-003 6.2700010e-002 5.6525210e-002
+v -1.3991610e-002 1.1962575e-001 3.6251540e-002
+v 1.9659170e-002 1.1236219e-001 3.7545270e-002
+v -3.2597160e-002 1.7498725e-001 -2.5953100e-003
+v -2.1513900e-003 9.9437380e-002 4.9849750e-002
+v -5.6001390e-002 6.1830670e-002 2.7931150e-002
+v -5.4707260e-002 6.3461570e-002 3.1670590e-002
+v -5.1307940e-002 6.0521660e-002 3.1434930e-002
+v -4.1979320e-002 6.9629980e-002 4.1824930e-002
+v -3.0272490e-002 6.2474660e-002 3.7982220e-002
+v -1.1387860e-002 6.4742460e-002 5.4918000e-002
+v 6.9544900e-003 6.4700130e-002 5.5599150e-002
+v 4.3015090e-002 9.7690960e-002 1.0258300e-003
+v 4.0635900e-002 6.1574860e-002 2.9841250e-002
+v 4.6183560e-002 6.1910110e-002 3.0223400e-002
+v 3.7552960e-002 1.0685291e-001 2.6303470e-002
+v -7.8640730e-002 1.6387238e-001 -2.8387790e-002
+v -6.1996240e-002 1.4761484e-001 -4.3256800e-003
+v -5.7499800e-003 6.5488980e-002 5.6173390e-002
+v 2.5369000e-004 6.5741170e-002 5.6569260e-002
+v -2.0542550e-002 1.1979518e-001 3.3003670e-002
+v 4.3155900e-003 1.2782561e-001 2.8646880e-002
+v -4.6549580e-002 6.7652130e-002 3.9635790e-002
+v -1.7420580e-002 6.9659490e-002 5.4089530e-002
+v -1.5242190e-002 7.0909900e-002 5.5004790e-002
+v -1.0282890e-002 6.8926360e-002 5.5289610e-002
+v -1.1289000e-004 6.9288200e-002 5.6579790e-002
+v -3.6309330e-002 1.1876943e-001 3.0674020e-002
+v -7.0325800e-002 6.3367770e-002 1.9809180e-002
+v 4.3023100e-002 6.3795810e-002 2.8039210e-002
+v 4.2831110e-002 8.5556040e-002 2.7873760e-002
+v 1.6981600e-002 1.2715003e-001 2.2931490e-002
+v -4.2121490e-002 1.2825104e-001 1.0751500e-003
+v 1.6329230e-002 1.2251895e-001 3.1375390e-002
+v -8.1264160e-002 1.5381172e-001 2.5897830e-002
+v -3.2257870e-002 8.8192600e-002 -2.5130960e-002
+v -1.3774950e-002 7.0887950e-002 5.4695630e-002
+v 5.2929600e-003 6.8006030e-002 5.5670490e-002
+v 7.6962500e-003 7.2375600e-002 5.6062150e-002
+v 3.4830600e-003 1.2002635e-001 3.6911950e-002
+v 6.6532500e-003 1.1673563e-001 3.8716340e-002
+v 4.6086570e-002 6.6473930e-002 2.6808990e-002
+v 5.2327290e-002 6.4327070e-002 2.8281890e-002
+v -6.1897630e-002 1.2297065e-001 -8.7725500e-003
+v -6.3934700e-003 1.0524472e-001 -2.2841900e-002
+v -3.5218330e-002 6.8559830e-002 4.1381470e-002
+v -3.2689880e-002 6.7729720e-002 4.0124390e-002
+v -2.9245440e-002 6.9551520e-002 3.9369010e-002
+v -5.0024500e-003 6.9655000e-002 5.6892510e-002
+v 1.6573960e-002 1.1890153e-001 3.5042300e-002
+v -8.9385100e-002 9.9024040e-002 1.7521830e-002
+v 4.5719230e-002 6.9489400e-002 2.3549340e-002
+v 5.4537210e-002 6.8796720e-002 2.4517690e-002
+v -4.4989450e-002 7.1577330e-002 4.1929250e-002
+v -4.2439400e-003 1.2914902e-001 2.5829230e-002
+v -7.3880090e-002 1.2091638e-001 5.3395800e-002
+v -7.4033870e-002 1.4406894e-001 4.4994970e-002
+v 5.0400010e-002 6.7292480e-002 2.6851470e-002
+v -5.4056890e-002 1.5671602e-001 -2.4865900e-003
+v 2.6148110e-002 1.2014725e-001 2.7308010e-002
+v -1.0736490e-002 1.2990285e-001 1.0993790e-002
+v -4.5078840e-002 8.7261130e-002 -2.1865520e-002
+v -3.8340900e-002 6.8843770e-002 4.1846470e-002
+v -2.9255580e-002 7.5169210e-002 4.1186430e-002
+v -4.7311210e-002 1.6296037e-001 6.0740300e-003
+v -1.1866030e-002 7.3183750e-002 5.6250050e-002
+v -6.3734600e-003 7.2184340e-002 5.7972980e-002
+v -2.9935300e-003 7.2186440e-002 5.8167190e-002
+v -2.5781060e-002 9.3778180e-002 -2.8388220e-002
+v -1.6692560e-002 1.1568553e-001 3.7853150e-002
+v -8.4123410e-002 1.0832050e-001 2.4730980e-002
+v -7.4294080e-002 1.6356850e-001 -1.5534220e-002
+v -9.4297150e-002 1.2617744e-001 1.9224650e-002
+v -3.5207090e-002 1.2505219e-001 2.1635690e-002
+v -4.9495940e-002 7.3436340e-002 4.1673570e-002
+v -3.3064160e-002 7.6654840e-002 4.1277900e-002
+v -7.3157300e-003 7.3919590e-002 5.7971690e-002
+v 2.1850000e-005 7.3496040e-002 5.7696650e-002
+v 4.1934400e-003 7.2915170e-002 5.6298730e-002
+v -7.7256080e-002 1.4565854e-001 4.3122930e-002
+v 4.1073260e-002 8.8724320e-002 -9.7879400e-003
+v 3.7418710e-002 1.0850822e-001 3.3973000e-004
+v -5.5111380e-002 7.4687840e-002 4.1939740e-002
+v -4.2740230e-002 7.6995340e-002 4.2804080e-002
+v -6.8531190e-002 1.5630045e-001 2.0997710e-002
+v -9.9440200e-003 7.6343100e-002 5.7388560e-002
+v -3.2479200e-003 7.5710690e-002 5.8714640e-002
+v 1.3414380e-002 9.3073740e-002 5.1467750e-002
+v -7.3504440e-002 9.3883340e-002 -1.4751720e-002
+v -7.4471830e-002 1.3507476e-001 5.0688900e-002
+v -2.5851310e-002 1.2182948e-001 2.6079670e-002
+v -3.4022940e-002 1.7597076e-001 -3.7271600e-003
+v -7.5405850e-002 1.6839072e-001 -2.6792980e-002
+v -3.6658410e-002 7.5087300e-002 4.2006940e-002
+v -1.7795480e-002 7.7486190e-002 5.6087240e-002
+v -1.1378660e-002 7.9877150e-002 5.7698880e-002
+v -1.0415000e-004 7.6881950e-002 5.8190740e-002
+v 2.7381400e-003 7.9105680e-002 5.6719190e-002
+v 5.5681200e-003 7.6397140e-002 5.6327220e-002
+v -6.1895860e-002 1.5424247e-001 -1.9018600e-002
+v -7.2646960e-002 1.4098943e-001 4.6976640e-002
+v 1.5799740e-002 1.2901416e-001 1.3236870e-002
+v -1.1703420e-002 9.7355720e-002 5.1592080e-002
+v -5.8922160e-002 7.7545490e-002 4.2961390e-002
+v -5.3121320e-002 7.7912430e-002 4.3334920e-002
+v -5.0745740e-002 7.6148400e-002 4.3137630e-002
+v -4.7401820e-002 7.5550340e-002 4.2630140e-002
+v -4.5055620e-002 7.8796280e-002 4.2341310e-002
+v -3.9517650e-002 7.8127780e-002 4.2918620e-002
+v -1.5245570e-002 8.2940770e-002 5.6934590e-002
+v -1.4557790e-002 7.6582160e-002 5.6493250e-002
+v -5.9406000e-003 7.9038240e-002 5.7969830e-002
+v 3.7176540e-002 1.1064404e-001 1.8811330e-002
+v 2.3929700e-003 1.3162713e-001 1.1955100e-002
+v -9.3644210e-002 1.1789378e-001 1.8662080e-002
+v -6.3939810e-002 7.8621830e-002 4.2083520e-002
+v -4.5376460e-002 8.2383550e-002 4.3282120e-002
+v -3.6505460e-002 8.1152260e-002 4.3162320e-002
+v -3.3244340e-002 8.2266590e-002 4.1852180e-002
+v -3.0800650e-002 8.0068420e-002 4.1798070e-002
+v -2.0578500e-003 8.0998290e-002 5.7553840e-002
+v 8.1848100e-003 8.0756170e-002 5.5374510e-002
+v -1.2953370e-002 1.1593580e-001 3.8920230e-002
+v -7.8081470e-002 1.2351940e-001 5.2136990e-002
+v -2.6580930e-002 1.5567694e-001 -4.1963400e-003
+v -8.2471600e-002 1.1624130e-001 -2.3236300e-003
+v -2.7538480e-002 7.9964780e-002 4.7697210e-002
+v 1.2556400e-003 8.3845570e-002 5.7446440e-002
+v 6.1508300e-003 8.3406240e-002 5.6463500e-002
+v -6.2433240e-002 8.4035270e-002 4.4203120e-002
+v -5.9867170e-002 8.0540510e-002 4.3277090e-002
+v -5.5238340e-002 8.1999450e-002 4.4984770e-002
+v -5.4000400e-002 8.0568410e-002 4.4601460e-002
+v -5.0027020e-002 8.1311330e-002 4.4264180e-002
+v -4.1996120e-002 8.1083670e-002 4.2456150e-002
+v -3.9357940e-002 8.3631380e-002 4.3502350e-002
+v -8.6161480e-002 1.0838594e-001 1.8244920e-002
+v -8.6723010e-002 9.9917250e-002 3.5537100e-003
+v -2.2413700e-002 8.3283520e-002 5.5590700e-002
+v -1.6993180e-002 8.2555820e-002 5.7523880e-002
+v -1.2406010e-002 8.5222570e-002 5.7267780e-002
+v -7.4442100e-003 1.1693417e-001 3.9283850e-002
+v -2.1452000e-003 1.1143287e-001 4.2436620e-002
+v -7.5718220e-002 1.2522734e-001 5.3087330e-002
+v -7.7056660e-002 1.3193469e-001 5.2462430e-002
+v -6.1121040e-002 1.5569660e-001 2.2517050e-002
+v -3.7538540e-002 1.2744127e-001 1.5320870e-002
+v -2.0516700e-003 1.0093469e-001 4.5625920e-002
+v -6.4992150e-002 8.4550900e-002 4.4120060e-002
+v -5.7861950e-002 8.3944360e-002 4.4186030e-002
+v -4.5681080e-002 8.4988010e-002 4.4159500e-002
+v -3.5022640e-002 8.2888160e-002 4.2912760e-002
+v -2.9982010e-002 8.5402300e-002 4.3745080e-002
+v -8.8892260e-002 9.9209100e-002 9.5703200e-003
+v -1.9135300e-002 8.3474800e-002 5.7217390e-002
+v -8.3489710e-002 1.0724729e-001 7.5790000e-004
+v -7.0112800e-002 1.1790350e-001 5.2714160e-002
+v -3.5526320e-002 1.7595563e-001 -4.8676200e-003
+v -7.0831390e-002 1.2254425e-001 5.3274880e-002
+v 4.5133810e-002 9.3630690e-002 6.2336800e-003
+v -5.3616700e-002 8.5346850e-002 4.5332470e-002
+v -4.9000840e-002 8.6221680e-002 4.5352040e-002
+v -3.6744880e-002 8.6083690e-002 4.3612890e-002
+v -1.0872600e-002 8.8826770e-002 5.6665490e-002
+v -3.8450200e-003 8.4787810e-002 5.7197980e-002
+v -4.9020070e-002 1.1771293e-001 3.1581430e-002
+v -4.2914400e-002 1.1835991e-001 3.0645040e-002
+v -5.7684530e-002 1.5561695e-001 1.2983110e-002
+v -2.5411730e-002 1.2472533e-001 1.2886000e-004
+v 1.9012230e-002 1.2736197e-001 1.7786580e-002
+v -5.9498600e-002 8.8845470e-002 4.5109290e-002
+v -5.6931050e-002 8.8101500e-002 4.4692930e-002
+v 3.5765600e-003 1.3138981e-001 7.2086000e-003
+v -1.6683350e-002 8.7266690e-002 5.6741190e-002
+v -8.4980800e-003 8.3990470e-002 5.7605220e-002
+v 3.5078200e-003 8.6339520e-002 5.7048320e-002
+v -2.8398700e-002 1.8070650e-001 -7.8469500e-003
+v -7.6565830e-002 1.1674037e-001 5.1489350e-002
+v 1.7869430e-002 9.0898610e-002 4.8712940e-002
+v -4.0342100e-002 1.1669551e-001 3.2460200e-002
+v 5.9105700e-003 1.3140929e-001 1.6823750e-002
+v -8.5777550e-002 9.1701370e-002 -4.6970000e-005
+v -5.0372230e-002 8.8844660e-002 4.5188000e-002
+v -4.4434130e-002 8.7654530e-002 4.3477620e-002
+v -4.2056390e-002 8.6711520e-002 4.2534630e-002
+v -3.3058460e-002 8.6185500e-002 4.2560350e-002
+v -2.9241910e-002 9.0453360e-002 4.4236610e-002
+v -6.8964100e-003 8.4432910e-002 5.7168580e-002
+v -6.6210600e-003 9.0415250e-002 5.6879750e-002
+v -1.2439100e-003 8.9093200e-002 5.6552120e-002
+v 9.4076000e-003 9.0328050e-002 5.4214140e-002
+v 4.0194810e-002 1.0231597e-001 -2.0048600e-003
+v -8.6227130e-002 1.1466841e-001 2.2102000e-003
+v -8.9495490e-002 9.5632430e-002 1.4234810e-002
+v -6.7132160e-002 1.5709447e-001 -6.2032000e-003
+v -5.2935640e-002 9.0913520e-002 4.4568870e-002
+v -3.6744910e-002 8.8886950e-002 4.3312050e-002
+v -1.3626110e-002 8.9787930e-002 5.6674380e-002
+v 2.3337130e-002 1.2353449e-001 2.4874140e-002
+v -3.7053790e-002 1.2715094e-001 3.5474000e-004
+v -7.3696690e-002 1.5613015e-001 1.4359790e-002
+v -6.5592380e-002 9.1042400e-002 4.4092080e-002
+v -5.8997380e-002 9.2030670e-002 4.5335270e-002
+v -3.3238910e-002 8.8573580e-002 4.3697040e-002
+v -3.1834990e-002 9.0722970e-002 4.4173460e-002
+v -2.0022170e-002 8.8032110e-002 5.5589350e-002
+v -1.1213830e-002 9.2366370e-002 5.6105260e-002
+v 3.9108440e-002 1.0829072e-001 1.3142330e-002
+v 2.8675700e-002 1.1959600e-001 2.4545910e-002
+v -6.8940210e-002 1.5652777e-001 -1.9716000e-003
+v -6.2615110e-002 9.1126880e-002 4.5090730e-002
+v 3.0444560e-002 1.1886441e-001 2.0821750e-002
+v -1.5241090e-002 9.1821720e-002 5.5817230e-002
+v -5.6221700e-003 9.3235010e-002 5.5893630e-002
+v 4.7989900e-003 9.1654840e-002 5.4715170e-002
+v -6.8282400e-002 9.2376840e-002 4.2388730e-002
+v -5.5623730e-002 9.2187420e-002 4.5054970e-002
+v -5.1901030e-002 9.5457620e-002 4.3937650e-002
+v -4.8809030e-002 9.1083890e-002 4.4456690e-002
+v -4.5411560e-002 9.1002130e-002 4.3252770e-002
+v -4.4514550e-002 9.4860420e-002 4.2972490e-002
+v -3.9430320e-002 8.9597620e-002 4.3177890e-002
+v -3.5642240e-002 9.2617410e-002 4.4238490e-002
+v -1.2246000e-004 9.3201160e-002 5.5398380e-002
+v 9.5104600e-003 9.5483870e-002 5.0910600e-002
+v 2.1441660e-002 9.1354960e-002 4.8043360e-002
+v -8.9830300e-003 1.6926449e-001 -2.2683480e-002
+v -7.3019050e-002 1.5602104e-001 2.2419340e-002
+v -6.4760430e-002 1.5311588e-001 -2.0371200e-003
+v -6.9368510e-002 9.5242790e-002 4.2129000e-002
+v -6.0117140e-002 9.5552910e-002 4.4183820e-002
+v -2.9241690e-002 9.4290440e-002 4.4821190e-002
+v -2.6561430e-002 9.3289510e-002 4.4975420e-002
+v -1.4394030e-002 9.4587640e-002 5.3993500e-002
+v -8.8691600e-003 9.5400260e-002 5.4445980e-002
+v -1.2188700e-003 9.6201750e-002 5.3815910e-002
+v 4.0479000e-003 9.5817360e-002 5.2936770e-002
+v -4.6019400e-003 1.2428544e-001 3.3471960e-002
+v -7.8436460e-002 1.3928013e-001 4.8329360e-002
+v 1.0774610e-002 1.3079162e-001 1.4341740e-002
+v -5.6623730e-002 9.6322170e-002 4.3667910e-002
+v -3.6298870e-002 9.5695620e-002 4.3580310e-002
+v -2.4379930e-002 9.5866450e-002 4.4434530e-002
+v 1.0915500e-002 1.2633629e-001 2.9857020e-002
+v -5.8622700e-003 9.7350210e-002 5.2743650e-002
+v 1.6973450e-002 9.7106620e-002 4.7440920e-002
+v -6.7231980e-002 9.9173950e-002 4.1593880e-002
+v -5.4994210e-002 9.9640820e-002 4.2955230e-002
+v -4.8617990e-002 9.6452700e-002 4.4183060e-002
+v -5.5369000e-002 1.5442476e-001 1.6160650e-002
+v -9.4243550e-002 1.2207432e-001 2.3568470e-002
+v 1.3242990e-002 9.6738240e-002 4.8750160e-002
+v 2.0639290e-002 9.6602480e-002 4.6971000e-002
+v 7.3429700e-003 1.2098188e-001 3.5973430e-002
+v -1.3493870e-002 1.2882438e-001 5.9690700e-003
+v -2.0110640e-002 1.2504545e-001 2.3588310e-002
+v -6.9438450e-002 1.6479930e-001 -1.7218700e-002
+v -6.4028050e-002 9.7838670e-002 4.2565330e-002
+v -5.1996350e-002 9.9707850e-002 4.2716590e-002
+v -4.3990880e-002 9.9425460e-002 4.2383430e-002
+v -3.9738250e-002 1.0215357e-001 4.0574410e-002
+v -3.5931490e-002 9.9809950e-002 4.2335800e-002
+v -3.0867600e-002 9.6914680e-002 4.4651400e-002
+v -2.8342070e-002 9.7782680e-002 4.3761280e-002
+v -2.5622580e-002 9.8713420e-002 4.4210890e-002
+v -8.5236620e-002 1.1077356e-001 2.4537670e-002
+v 7.1936000e-003 9.8859470e-002 4.8419510e-002
+v 9.6509200e-003 1.0108782e-001 4.7373080e-002
+v 1.3487100e-002 1.0076420e-001 4.7454290e-002
+v 7.7389800e-003 1.3147500e-001 1.1682970e-002
+v 8.0905000e-004 1.1633319e-001 4.0167560e-002
+v -7.2652570e-002 1.6567918e-001 -1.8212480e-002
+v -5.6009400e-003 1.3076674e-001 1.0516060e-002
+v -2.6303720e-002 1.2518875e-001 1.7392980e-002
+v -4.7590430e-002 1.0081180e-001 4.2349150e-002
+v -4.1460830e-002 9.8544800e-002 4.1778620e-002
+v -3.3582070e-002 1.0383908e-001 4.0737990e-002
+v -2.2870240e-002 1.0284737e-001 4.3544750e-002
+v -2.2361970e-002 9.8207610e-002 4.4765940e-002
+v -1.8870510e-002 9.8973200e-002 4.4489280e-002
+v -7.1433690e-002 7.7573520e-002 3.8060760e-002
+v -7.3001150e-002 1.1826712e-001 5.3034590e-002
+v -6.8466430e-002 1.3498146e-001 -8.3359800e-003
+v -7.4683810e-002 1.0786100e-001 -9.0477100e-003
+v -6.4958960e-002 1.5852021e-001 -1.2595320e-002
+v -7.8931700e-002 1.5093057e-001 3.5151900e-002
+v -7.4113550e-002 9.9442520e-002 3.8337710e-002
+v -7.0456930e-002 1.0098777e-001 3.9794060e-002
+v -5.9058760e-002 1.0041260e-001 4.2725130e-002
+v -4.9187330e-002 1.0452012e-001 4.0301390e-002
+v -2.9151180e-002 1.0197369e-001 4.2633060e-002
+v -1.1599720e-002 1.0107813e-001 4.4191660e-002
+v 5.1450400e-003 1.0163906e-001 4.5423010e-002
+v -5.1495700e-002 1.0496738e-001 4.0347210e-002
+v -2.0218210e-002 1.0214391e-001 4.3701160e-002
+v 4.2515900e-003 1.0523743e-001 4.2563550e-002
+v 1.6832800e-002 1.0337487e-001 4.5287270e-002
+v -2.5661080e-002 1.2562669e-001 4.5537500e-003
+v -7.2141950e-002 1.0536685e-001 3.7523210e-002
+v -6.4984570e-002 1.0371550e-001 4.0647810e-002
+v -6.0652480e-002 1.0467197e-001 4.0906390e-002
+v -5.5308980e-002 1.0365394e-001 4.1516690e-002
+v -4.4243240e-002 1.0431726e-001 4.1339990e-002
+v -1.5513340e-002 1.0436131e-001 4.2919420e-002
+v -7.6323200e-003 1.0304531e-001 4.3710640e-002
+v -7.8046900e-003 1.0516619e-001 4.3825460e-002
+v 9.7163200e-003 1.0523506e-001 4.3603830e-002
+v 3.0300390e-002 1.1553645e-001 2.8685010e-002
+v -4.7496910e-002 1.0635662e-001 4.0165640e-002
+v -3.8978950e-002 1.0683037e-001 3.8247660e-002
+v -2.5869310e-002 1.0426705e-001 4.2207540e-002
+v -1.8057930e-002 1.0503919e-001 4.2802830e-002
+v -1.5180030e-002 1.0807750e-001 4.2350430e-002
+v -3.8981500e-003 1.0566175e-001 4.4047190e-002
+v 2.6820000e-005 1.0446731e-001 4.3775910e-002
+v 1.1978350e-002 1.0403629e-001 4.5396310e-002
+v 1.5004970e-002 1.0726898e-001 4.1811990e-002
+v 2.6488060e-002 1.2230287e-001 2.0398110e-002
+v -3.6225630e-002 1.0634244e-001 3.8644860e-002
+v -2.1126780e-002 1.0932290e-001 4.0715320e-002
+v -1.2819810e-002 1.0457100e-001 4.3465690e-002
+v 5.2847900e-003 1.0943666e-001 4.1674980e-002
+v 8.9403700e-003 1.0710645e-001 4.1243400e-002
+v -5.1839670e-002 1.6062039e-001 7.1421300e-003
+v -5.4201370e-002 1.1451730e-001 3.4843990e-002
+v 1.3226250e-002 1.2958070e-001 1.9689610e-002
+v -6.9382410e-002 1.0865787e-001 3.7507800e-002
+v -6.7691040e-002 1.0734145e-001 3.8018440e-002
+v -6.3782400e-002 1.1037270e-001 3.7579790e-002
+v -5.0749390e-002 1.0928682e-001 3.8297580e-002
+v -9.3936200e-003 1.0742813e-001 4.3454570e-002
+v 1.1760100e-003 1.0932531e-001 4.2662800e-002
+v 9.8020300e-003 1.1003994e-001 3.9945400e-002
+v 2.0131290e-002 1.0732778e-001 4.0323840e-002
+v -2.7872800e-003 1.0577531e-001 -2.2459030e-002
+v -5.4996890e-002 1.0774199e-001 3.9424590e-002
+v -4.5966740e-002 1.0905146e-001 3.8754110e-002
+v -4.2324540e-002 1.0737278e-001 3.9456440e-002
+v -3.2161240e-002 1.0896504e-001 3.8102720e-002
+v -3.0770180e-002 1.1597313e-001 3.2858800e-002
+v -1.1608610e-002 1.0983707e-001 4.2475330e-002
+v -2.9428320e-002 9.3166620e-002 -2.4931860e-002
+v -8.0043570e-002 9.2080160e-002 -9.4198200e-003
+v -4.9797430e-002 1.1342104e-001 3.5117920e-002
+v -4.3723850e-002 1.6191369e-001 5.7713400e-003
+v -5.7981740e-002 1.0943152e-001 3.7997640e-002
+v -4.1491180e-002 1.1224766e-001 3.5873450e-002
+v -2.4929830e-002 1.1592775e-001 3.4094730e-002
+v -2.0881690e-002 1.1409528e-001 3.7872990e-002
+v -7.5519700e-003 1.1183813e-001 4.2039690e-002
+v 3.7667200e-003 1.1240547e-001 4.1494710e-002
+v -6.2829620e-002 1.5189480e-001 -9.2373400e-003
+v -5.9195950e-002 1.1320797e-001 3.6234680e-002
+v -5.1079080e-002 9.3892810e-002 -2.1761690e-002
+v -7.3945370e-002 8.4374880e-002 -1.5154490e-002
+v -7.2146240e-002 1.3486431e-001 -7.7592200e-003
+v -1.9408870e-002 1.7041104e-001 -2.0994830e-002
+v -5.5530450e-002 1.4905531e-001 -1.9602100e-003
+v 1.6688460e-002 3.6976600e-002 4.3000600e-002
+v -5.2277330e-002 1.1775075e-001 3.3769460e-002
+v -6.9201380e-002 9.3039200e-002 -1.6486120e-002
+v 2.6579210e-002 1.1702438e-001 3.0867940e-002
+v -2.3574310e-002 3.7036910e-002 5.4144750e-002
+v -7.3775100e-003 3.8988430e-002 4.8929450e-002
+v 1.3234660e-002 3.8453060e-002 4.4501470e-002
+v 1.9487350e-002 4.0809290e-002 4.2641060e-002
+v -6.3953930e-002 1.4694729e-001 3.8484200e-002
+v -4.9579470e-002 3.6096540e-002 4.5955360e-002
+v -4.3323650e-002 3.6286400e-002 4.4042360e-002
+v -2.9047200e-002 1.2556338e-001 7.7617700e-003
+v -1.7343100e-003 3.9476800e-002 4.7262900e-002
+v -3.1358130e-002 1.5362199e-001 -4.6738900e-003
+v 2.5822000e-003 1.0747582e-001 -2.0606030e-002
+v -5.6802300e-002 1.4514674e-001 3.1740300e-002
+v -5.6464330e-002 3.7683110e-002 4.6819640e-002
+v -5.0964750e-002 3.8312290e-002 4.6286140e-002
+v -5.0980410e-002 1.3486613e-001 2.7585000e-002
+v -2.5647410e-002 3.8860730e-002 5.4161390e-002
+v -2.2542110e-002 4.0615780e-002 5.3986030e-002
+v -1.7618010e-002 3.8911170e-002 5.2403440e-002
+v -1.9711750e-002 1.6829145e-001 -1.3020960e-002
+v 2.3780070e-002 9.5222940e-002 4.6347330e-002
+v 1.4744290e-002 4.2716950e-002 4.4510310e-002
+v 2.1691360e-002 4.0161530e-002 4.0846450e-002
+v -6.4067240e-002 9.0172190e-002 -1.8855520e-002
+v 2.0319150e-002 1.0041961e-001 4.5760520e-002
+v -3.6425000e-002 9.3630690e-002 -2.3534630e-002
+v -1.4981170e-002 4.2571420e-002 5.1404530e-002
+v -5.7335340e-002 1.2340101e-001 4.0231470e-002
+v -5.4172560e-002 1.2337919e-001 3.7576440e-002
+v 2.2625210e-002 4.3621680e-002 4.0904580e-002
+v 2.8810520e-002 4.3352290e-002 3.2157720e-002
+v -4.2764160e-002 1.5727487e-001 5.2016200e-003
+v 9.2231900e-003 4.4125090e-002 4.5057440e-002
+v 1.5048210e-002 4.5755840e-002 4.3793870e-002
+v -6.3757290e-002 1.0251144e-001 -1.7484400e-002
+v -3.4070430e-002 1.6148975e-001 -1.3786960e-002
+v -8.2191500e-002 7.5610200e-002 1.6542620e-002
+v -6.6299420e-002 1.2337119e-001 5.0615920e-002
+v -1.5510100e-002 4.5283110e-002 5.0653040e-002
+v 1.8928020e-002 4.4249610e-002 4.3009830e-002
+v 2.5821800e-002 4.6326610e-002 3.8277230e-002
+v 2.7268700e-002 4.4547790e-002 3.6152520e-002
+v -4.5301340e-002 1.5695057e-001 7.2036900e-003
+v 2.3855760e-002 1.0616625e-001 3.9378080e-002
+v 2.1632670e-002 4.8127270e-002 4.0694430e-002
+v 4.3785360e-002 4.8803700e-002 3.1343420e-002
+v 4.8074790e-002 4.8969960e-002 2.8165490e-002
+v 5.2663090e-002 4.7673620e-002 2.1201270e-002
+v -5.2722450e-002 4.4722850e-002 4.4143250e-002
+v -3.0071610e-002 1.7258324e-001 -6.3597700e-003
+v -3.4508050e-002 1.5447469e-001 1.6504600e-003
+v 1.0629710e-002 4.6711810e-002 4.6472020e-002
+v 1.6743440e-002 4.8439000e-002 4.3678630e-002
+v 2.8827050e-002 9.2133370e-002 4.3920090e-002
+v -5.9937100e-002 1.2726188e-001 4.0771270e-002
+v -3.6752090e-002 1.5802075e-001 4.1862000e-003
+v -3.7885390e-002 1.6199719e-001 2.4686000e-004
+v -2.2047790e-002 1.8348586e-001 -1.2094990e-002
+v -2.4364620e-002 1.8096836e-001 -9.8312000e-003
+v -4.4882280e-002 1.5052959e-001 7.6451700e-003
+v 2.6996760e-002 5.1317780e-002 3.8752040e-002
+v 4.7735750e-002 5.2751040e-002 3.0797290e-002
+v 5.1703790e-002 4.8857380e-002 2.4147970e-002
+v -6.7504360e-002 1.1424088e-001 4.8036050e-002
+v -1.6257520e-002 1.6031250e-001 -9.6926000e-003
+v -6.3926300e-002 1.6792441e-001 -4.0730420e-002
+v -4.1665290e-002 1.4996141e-001 4.5405000e-003
+v -3.5203230e-002 1.6493551e-001 -2.6810000e-003
+v 4.1318770e-002 9.9496740e-002 2.4275750e-002
+v 1.4055220e-002 5.2523910e-002 4.8593880e-002
+v 1.9421220e-002 5.1321300e-002 4.4798910e-002
+v 2.3677990e-002 5.1474390e-002 4.1053270e-002
+v 3.4258130e-002 5.1930810e-002 3.2757880e-002
+v 5.5957340e-002 5.3147410e-002 2.3197720e-002
+v -3.9937960e-002 1.4922850e-001 1.6017200e-003
+v -4.6988800e-002 1.2600802e-001 2.6985500e-002
+v -2.7708370e-002 9.0081290e-002 -3.1911460e-002
+v 1.9204630e-002 5.5166510e-002 4.7722150e-002
+v 2.1886000e-002 5.3927560e-002 4.5102460e-002
+v 3.1286270e-002 5.2863840e-002 3.6913620e-002
+v 4.6661160e-002 5.4719230e-002 3.1976810e-002
+v 5.1823730e-002 5.3276700e-002 2.7927010e-002
+v -2.9264880e-002 1.6140418e-001 -2.1039500e-003
+v -6.8700770e-002 1.4463537e-001 4.3041630e-002
+v -5.6070060e-002 1.5000706e-001 2.9867640e-002
+v 4.4717850e-002 9.4802660e-002 1.2024710e-002
+v -4.1804090e-002 1.5582081e-001 6.4548200e-003
+v -6.8369340e-002 1.2289287e-001 5.2437860e-002
+v -6.4114810e-002 9.5509880e-002 -1.8114610e-002
+v -1.8383130e-002 1.8543664e-001 -1.7136370e-002
+v 1.1745400e-002 5.6678340e-002 5.1914060e-002
+v -5.9375360e-002 1.1998238e-001 4.0548240e-002
+v 5.9092080e-002 5.7956980e-002 2.0270120e-002
+v 4.3547740e-002 9.7389400e-002 1.7314650e-002
+v -2.6291780e-002 1.5963381e-001 -5.1845000e-004
+v 1.4904780e-002 5.6350380e-002 4.9522780e-002
+v 2.4286200e-002 5.4958580e-002 4.3086850e-002
+v 2.8952610e-002 5.6125250e-002 4.0388970e-002
+v -4.9507770e-002 1.2949500e-001 3.0259270e-002
+v 4.0824790e-002 9.5170220e-002 2.8657920e-002
+v 1.7774800e-002 5.8243780e-002 4.8864720e-002
+v 3.3573840e-002 5.8515260e-002 3.8310990e-002
+v 3.6385040e-002 5.6996480e-002 3.3601460e-002
+v -6.4205010e-002 1.2243894e-001 4.8008340e-002
+v -6.5424500e-002 1.4011279e-001 4.1308960e-002
+v 5.0801340e-002 5.7308080e-002 3.0001390e-002
+v 5.6671750e-002 5.6970820e-002 2.4291920e-002
+v -4.9349930e-002 1.4913519e-001 1.1274060e-002
+v -6.9760570e-002 1.3442855e-001 4.8265220e-002
+v 1.9537060e-002 6.0003780e-002 4.8576140e-002
+v 2.7013910e-002 5.9952790e-002 4.3454420e-002
+v 5.7679430e-002 6.1392970e-002 2.4201790e-002
+v -5.6916540e-002 1.2623512e-001 3.9426610e-002
+v 2.3469280e-002 1.1656262e-001 3.3537270e-002
+v -5.8298640e-002 1.3885500e-001 3.2937460e-002
+v 6.4598400e-003 6.0297430e-002 5.4780030e-002
+v 1.0406020e-002 5.9162400e-002 5.2484370e-002
+v 2.3183950e-002 5.8654360e-002 4.5871060e-002
+v 3.3040360e-002 6.1773840e-002 3.9781440e-002
+v -6.4348220e-002 1.2628088e-001 4.6650200e-002
+v -5.7031440e-002 1.1562007e-001 3.6494880e-002
+v 5.4451560e-002 5.8342890e-002 2.7653010e-002
+v -3.0134400e-002 1.7011322e-001 -7.3591600e-003
+v -3.7077100e-002 1.5986369e-001 1.6096500e-003
+v -5.6032760e-002 1.3731083e-001 3.1970590e-002
+v -6.7676470e-002 1.4150325e-001 4.3868140e-002
+v 9.9911700e-003 6.2735270e-002 5.4009240e-002
+v 1.4521510e-002 6.1382890e-002 5.0500900e-002
+v 3.0051740e-002 6.2169610e-002 4.1545810e-002
+v 3.7519170e-002 6.1062710e-002 3.4366020e-002
+v 5.3944010e-002 6.1391550e-002 2.8268530e-002
+v 5.9119900e-002 6.3128810e-002 2.1561830e-002
+v -2.4366390e-002 1.7693266e-001 -1.1719630e-002
+v -1.3253420e-002 1.6627152e-001 -1.4120370e-002
+v 3.9218740e-002 1.0669250e-001 2.0450190e-002
+v -1.7968980e-002 1.8078031e-001 -1.8103430e-002
+v 2.1902390e-002 6.0875970e-002 4.7282360e-002
+v 3.5341750e-002 6.1630030e-002 3.7606020e-002
+v -6.2145620e-002 1.3599775e-001 3.6700970e-002
+v 5.6820620e-002 6.3691150e-002 2.5286090e-002
+v -3.2800040e-002 1.5948699e-001 2.1962800e-003
+v 1.1212140e-002 6.6584120e-002 5.3982180e-002
+v 1.2919590e-002 6.4203580e-002 5.2441150e-002
+v 2.0126950e-002 6.3851330e-002 4.7919660e-002
+v 3.5971760e-002 6.6669610e-002 3.7781400e-002
+v 3.9906940e-002 6.4361260e-002 3.1686660e-002
+v -6.6702350e-002 1.3210600e-001 4.5480940e-002
+v -4.1601430e-002 1.5978000e-001 3.5374700e-003
+v 3.3044580e-002 1.0766252e-001 3.1916150e-002
+v 2.4672100e-002 6.3694500e-002 4.5204640e-002
+v 2.6108660e-002 6.8007640e-002 4.3902690e-002
+v 3.3363940e-002 6.7054760e-002 3.9729480e-002
+v 4.2915790e-002 6.6707700e-002 2.6994720e-002
+v 5.4714960e-002 6.4697160e-002 2.6979680e-002
+v -1.6530940e-002 1.6325000e-001 -9.2475200e-003
+v -1.7891600e-002 1.6113800e-001 -6.7072700e-003
+v 4.1118120e-002 9.7491260e-002 -3.9756700e-003
+v 2.3386770e-002 7.0075990e-002 4.7012620e-002
+v 3.8102900e-002 6.5678440e-002 3.5132520e-002
+v 1.0145240e-002 1.2221678e-001 3.4718950e-002
+v 5.8392410e-002 6.6741240e-002 2.1979460e-002
+v 3.8302050e-002 8.4549140e-002 -1.4478830e-002
+v 3.4126440e-002 9.7053980e-002 3.7590390e-002
+v -3.1355740e-002 1.5809888e-001 1.9128800e-003
+v -5.8259510e-002 1.4099493e-001 3.2440640e-002
+v -6.6817230e-002 1.1951525e-001 5.1490220e-002
+v -6.8090040e-002 1.1647050e-001 5.1151230e-002
+v 1.6568300e-002 6.6269890e-002 5.1009890e-002
+v 2.9362870e-002 6.6509780e-002 4.2289380e-002
+v 3.7027180e-002 9.3949630e-002 -1.1674040e-002
+v 5.6412730e-002 6.7659930e-002 2.3969320e-002
+v -6.1295740e-002 1.4519988e-001 3.7137830e-002
+v 8.3873000e-003 1.1336223e-001 3.9792610e-002
+v 1.1807030e-002 7.0920980e-002 5.4240490e-002
+v 2.9741730e-002 7.0647100e-002 4.1653890e-002
+v 3.6294410e-002 7.1220700e-002 3.7114610e-002
+v 3.9899680e-002 7.0294820e-002 3.2720020e-002
+v -6.2763130e-002 1.3778012e-001 3.6678590e-002
+v -1.5815440e-002 1.7504938e-001 -1.8654160e-002
+v -9.2268990e-002 1.1475156e-001 1.7017380e-002
+v -9.4964000e-004 1.0141111e-001 4.4290070e-002
+v -6.3712920e-002 1.1274250e-001 3.8006760e-002
+v -6.1096020e-002 1.1701650e-001 3.9654020e-002
+v 2.0991870e-002 6.9335450e-002 4.9003540e-002
+v 2.5658530e-002 7.0550460e-002 4.4539930e-002
+v 3.2978560e-002 7.3500690e-002 4.0486510e-002
+v 4.2156130e-002 6.9717580e-002 2.8318230e-002
+v -5.5516860e-002 1.2956070e-001 3.6598450e-002
+v -4.0802290e-002 1.6436059e-001 3.7448800e-003
+v -6.2546500e-003 1.0121650e-001 4.4322030e-002
+v -1.0986820e-002 1.6621199e-001 -1.6047550e-002
+v -3.0351420e-002 1.6448158e-001 -5.3291400e-003
+v 2.6110920e-002 1.0088990e-001 4.1733260e-002
+v -6.5599940e-002 1.1329504e-001 4.2318710e-002
+v 2.8814660e-002 9.6712680e-002 4.2257700e-002
+v 1.5263280e-002 7.1571940e-002 5.2717390e-002
+v 2.8982400e-002 7.4088480e-002 4.3447240e-002
+v 4.4872540e-002 7.5516710e-002 2.3155250e-002
+v -7.8225230e-002 1.4962481e-001 -2.5019400e-003
+v -4.6094940e-002 1.5296850e-001 9.0029700e-003
+v -5.2369030e-002 1.4682913e-001 1.8934650e-002
+v -2.1592100e-002 1.5763440e-001 -6.8623600e-003
+v 1.7176770e-002 7.3066230e-002 5.1826600e-002
+v 2.2687500e-002 7.5149180e-002 4.9312500e-002
+v 3.5472040e-002 7.3076670e-002 3.8482270e-002
+v -8.9480840e-002 1.3839976e-001 2.5061450e-002
+v -5.3216730e-002 1.3221978e-001 3.2978380e-002
+v -3.7776780e-002 1.5551947e-001 4.3700800e-003
+v -9.0549380e-002 1.3511875e-001 2.1680550e-002
+v -6.3366580e-002 1.3037076e-001 4.1669940e-002
+v 1.4074270e-002 7.6651720e-002 5.4221350e-002
+v 1.8109790e-002 7.5806590e-002 5.2488260e-002
+v 4.2209940e-002 7.8861480e-002 2.9187200e-002
+v -5.2115930e-002 1.4179906e-001 2.0510310e-002
+v 2.9063090e-002 1.1149602e-001 3.3805790e-002
+v -5.4731460e-002 1.4267229e-001 2.8980480e-002
+v 2.5903640e-002 7.5536040e-002 4.6416650e-002
+v 3.1298760e-002 7.5907440e-002 4.2699060e-002
+v 3.8446170e-002 7.5649430e-002 3.5050640e-002
+v 4.6351670e-002 7.4079520e-002 1.8354320e-002
+v -4.7656560e-002 1.3077525e-001 2.5523570e-002
+v -1.1447430e-002 1.7131059e-001 -1.9602980e-002
+v -3.6647240e-002 1.6640131e-001 -2.8167000e-004
+v -4.6653530e-002 1.5917824e-001 7.8019000e-003
+v -4.5569890e-002 1.4663612e-001 5.6514200e-003
+v 4.1438880e-002 9.2365100e-002 -7.4587000e-003
+v -6.4287420e-002 1.3463625e-001 3.9945640e-002
+v -6.1128890e-002 1.3178328e-001 3.8915910e-002
+v -4.7843540e-002 1.2215063e-001 2.8833160e-002
+v -4.9536830e-002 1.2491344e-001 3.1778440e-002
+v -7.1135380e-002 1.3817656e-001 4.7853960e-002
+v 1.0113870e-002 7.6468110e-002 5.5256790e-002
+v 1.7897450e-002 7.9516550e-002 5.2759530e-002
+v 2.1740850e-002 8.0250650e-002 5.0425390e-002
+v 2.5271590e-002 7.8724920e-002 4.8026570e-002
+v 3.0885040e-002 7.8999480e-002 4.3388770e-002
+v -6.2441930e-002 1.4084781e-001 3.6965840e-002
+v -6.2165060e-002 1.5666850e-001 -1.7837760e-002
+v 2.0657260e-002 1.0416830e-001 4.3004680e-002
+v -6.3602800e-002 1.1571453e-001 4.2572290e-002
+v 1.4424020e-002 8.0085500e-002 5.3755600e-002
+v 2.8779340e-002 8.2553250e-002 4.4527350e-002
+v 4.4450130e-002 8.1846900e-002 2.4552920e-002
+v 4.5541990e-002 8.3338380e-002 1.9700850e-002
+v -4.9665810e-002 1.2063801e-001 3.2163270e-002
+v -2.9177290e-002 1.7619959e-001 -5.6241100e-003
+v -5.8203130e-002 1.3270975e-001 3.6918680e-002
+v 3.8997050e-002 9.7088220e-002 -7.7799300e-003
+v -5.4725800e-002 1.2071262e-001 3.7451450e-002
+v 1.3189120e-002 8.4211180e-002 5.3065830e-002
+v -1.9926300e-002 1.6489742e-001 -9.9900200e-003
+v 2.0153130e-002 1.1849719e-001 3.4271250e-002
+v -5.5859940e-002 1.1774313e-001 3.7253480e-002
+v 1.8045260e-002 8.3623160e-002 5.1285840e-002
+v -6.3757130e-002 1.5912175e-001 -5.0155730e-002
+v -1.8527620e-002 1.7653197e-001 -1.7043540e-002
+v 2.8734400e-002 1.0360053e-001 3.8035240e-002
+v 4.1414010e-002 1.0284216e-001 1.6578920e-002
+v 2.4411730e-002 9.8016880e-002 4.4687400e-002
+v 2.0925180e-002 8.6311430e-002 4.9433120e-002
+v 3.0445010e-002 8.4959560e-002 4.3011090e-002
+v 3.3030090e-002 8.3781640e-002 4.1636930e-002
+v 3.6975090e-002 7.9876480e-002 3.7198390e-002
+v -7.7721460e-002 1.1355888e-001 4.8155990e-002
+v 2.9250000e-002 1.0651935e-001 3.6590330e-002
+v -5.3078180e-002 1.3754688e-001 2.8266470e-002
+v -6.2990590e-002 1.1999459e-001 4.5235530e-002
+v -6.5398320e-002 1.1751956e-001 4.8735570e-002
+v 3.3373910e-002 1.1227890e-001 2.7788130e-002
+v 3.8413590e-002 8.7489930e-002 3.5185850e-002
+v -6.1945930e-002 1.6479234e-001 -5.6647670e-002
+v -2.2876480e-002 1.7392813e-001 -1.3431140e-002
+v 4.3766230e-002 8.8390020e-002 -3.5708800e-003
+v 3.9291530e-002 1.0125969e-001 2.7550520e-002
+v 1.0936230e-002 8.6027290e-002 5.4732670e-002
+v 2.4108720e-002 8.4492600e-002 4.8292310e-002
+v 3.6758390e-002 9.9195470e-002 3.2837670e-002
+v -5.1941640e-002 1.2565987e-001 3.4587860e-002
+v -3.1582110e-002 1.6641850e-001 -5.7320000e-003
+v 7.6405900e-003 8.6427230e-002 5.6117850e-002
+v 1.6771020e-002 8.8644690e-002 5.0522960e-002
+v 3.4404610e-002 8.6932850e-002 4.0574270e-002
+v 3.6143820e-002 8.4439200e-002 3.7936930e-002
+v 4.1258830e-002 1.0361081e-001 2.6760600e-003
+v 2.4766140e-002 1.1081111e-001 3.6728360e-002
+v -2.2601590e-002 1.6250449e-001 -6.0717000e-003
+v -1.2893670e-002 1.7879041e-001 -2.2624750e-002
+v -2.4939150e-002 1.7031135e-001 -1.1329700e-002
+v -4.8468630e-002 1.4559606e-001 8.3661500e-003
+v 1.2534490e-002 8.9593930e-002 5.3394630e-002
+v 2.5872860e-002 8.8482290e-002 4.6655260e-002
+v 3.2756470e-002 8.8969130e-002 4.2215450e-002
+v -2.3343620e-002 1.6103450e-001 -3.1862400e-003
+v -9.2594970e-002 1.1943826e-001 2.6802950e-002
+v -7.4314840e-002 1.3761738e-001 -6.6698800e-003
+v -9.2499230e-002 1.2131500e-001 2.9256200e-002
+v -7.7378260e-002 1.5764266e-001 -1.4133650e-002
+v -9.2907340e-002 1.2307021e-001 3.6523230e-002
+v 2.8423340e-002 8.8011080e-002 4.4234200e-002
+v 3.5251680e-002 9.0836820e-002 3.9183920e-002
+v 1.5760560e-002 9.3203560e-002 4.9939310e-002
+v 3.8785530e-002 9.4954300e-002 3.2520220e-002
+v -6.1511220e-002 1.2373565e-001 4.3062680e-002
+v -6.8145120e-002 1.2748676e-001 5.0148970e-002
+v -2.0616710e-002 1.8237588e-001 -1.4299100e-002
+v 1.5137190e-002 1.1571495e-001 3.7031980e-002
+v -5.0718270e-002 1.5276300e-001 1.1816680e-002
+v 3.0168690e-002 1.0048686e-001 3.9404710e-002
+v -8.7426500e-002 9.5469530e-002 4.0312400e-003
+v -6.0010390e-002 1.4284463e-001 3.5449690e-002
+v -5.8603310e-002 1.4637237e-001 3.3808800e-002
+v 3.2411650e-002 9.3736150e-002 4.0890240e-002
+v -7.5917780e-002 1.4997690e-001 -1.6842050e-002
+v 1.8596570e-002 3.5293940e-002 -8.6782200e-003
+v 1.7209800e-002 3.5259400e-002 -1.4685160e-002
+v 4.4326540e-002 9.0818120e-002 2.2097520e-002
+v 3.8335910e-002 3.8830830e-002 3.0938100e-003
+v 2.2192920e-002 3.6775320e-002 -2.0919300e-003
+v 1.9636020e-002 3.8234010e-002 -1.2507670e-002
+v 2.3682120e-002 3.9762540e-002 3.7148760e-002
+v 4.6693280e-002 4.2465320e-002 6.5649500e-003
+v 2.1621110e-002 3.7657240e-002 -4.7021600e-003
+v 1.6638610e-002 3.8196090e-002 -1.9884930e-002
+v -9.0253980e-002 1.1366307e-001 3.7720210e-002
+v -9.0593870e-002 1.1373094e-001 1.0276770e-002
+v -6.2541690e-002 1.7679461e-001 -5.7821820e-002
+v -1.1091940e-002 1.7992082e-001 -2.5996430e-002
+v -6.2263130e-002 1.5219935e-001 -2.2578880e-002
+v -4.2276760e-002 9.4982570e-002 -2.2562420e-002
+v 4.3293410e-002 4.1864140e-002 2.0634400e-003
+v 4.3779590e-002 4.4530720e-002 -1.2622500e-003
+v 2.1696990e-002 4.0427270e-002 -9.4629500e-003
+v -1.1183700e-002 1.6450000e-001 -1.6151690e-002
+v -6.2372570e-002 1.5313041e-001 -2.8997120e-002
+v -9.2489300e-003 1.7725850e-001 -2.8270200e-002
+v 4.1477400e-002 8.5509410e-002 -9.1575000e-003
+v -8.1268710e-002 1.0879438e-001 2.9440660e-002
+v 4.9575680e-002 4.3815900e-002 1.4582960e-002
+v 5.2987960e-002 4.7747690e-002 5.0420000e-003
+v 2.1977540e-002 4.2855330e-002 -1.4536230e-002
+v 1.8505700e-002 3.8294100e-002 -1.7136500e-002
+v -3.5100500e-002 1.5203437e-001 -1.3279000e-004
+v 4.8749130e-002 4.5265000e-002 2.3023500e-003
+v 3.1912900e-002 9.9870060e-002 -1.4620980e-002
+v -1.4222520e-002 1.6167426e-001 -1.3349060e-002
+v -4.8663640e-002 1.3638523e-001 6.8063900e-003
+v -9.5837200e-003 1.7426102e-001 -2.8390760e-002
+v 5.2801850e-002 4.6539940e-002 1.0427720e-002
+v 5.1433800e-002 4.8485200e-002 1.0401000e-003
+v 2.3911240e-002 9.8021670e-002 -2.0807290e-002
+v 2.4567060e-002 4.4130110e-002 -1.0820840e-002
+v 2.0356810e-002 4.3662400e-002 -2.0456280e-002
+v -2.1882420e-002 1.1087418e-001 -1.9695320e-002
+v -5.3831800e-002 1.4981693e-001 2.5066610e-002
+v 5.4114210e-002 4.7773090e-002 1.7484000e-002
+v 5.6730570e-002 5.0515740e-002 1.0627080e-002
+v 4.5941820e-002 4.8138820e-002 -3.8715700e-003
+v -8.3817760e-002 1.1109094e-001 2.8524490e-002
+v 2.9207770e-002 4.7450250e-002 -8.5081800e-003
+v 2.8454920e-002 4.8067390e-002 -1.2847240e-002
+v 2.6637260e-002 4.7607100e-002 -1.6427740e-002
+v 2.2040110e-002 4.4992500e-002 -1.7528500e-002
+v 1.9120080e-002 4.7167750e-002 -2.2114680e-002
+v -1.5782200e-002 1.0072957e-001 -2.3724130e-002
+v -6.2514170e-002 1.7213119e-001 -5.2788100e-002
+v -6.2345600e-002 1.4745498e-001 -7.6600200e-003
+v 4.5598180e-002 8.8151720e-002 1.3124070e-002
+v -4.9422610e-002 1.4283525e-001 8.9728300e-003
+v -8.2761860e-002 1.1162341e-001 4.4221460e-002
+v -5.2166220e-002 1.5013661e-001 1.7448750e-002
+v -6.3616740e-002 1.4801371e-001 -2.0170260e-002
+v -5.1492690e-002 1.3796388e-001 2.3662180e-002
+v -6.1517580e-002 1.7517449e-001 -6.0631700e-002
+v 5.6524870e-002 5.0125660e-002 1.5564490e-002
+v 5.5257900e-002 5.1416260e-002 3.2062600e-003
+v 5.0318130e-002 5.2786370e-002 -3.4166300e-003
+v -6.2681950e-002 1.6744086e-001 -4.5713890e-002
+v 5.6520150e-002 5.1179900e-002 1.9940560e-002
+v 5.6907980e-002 5.1578130e-002 7.2538300e-003
+v 5.2854160e-002 5.1898670e-002 -6.2070000e-004
+v -3.8921140e-002 3.3767390e-002 -2.9042560e-002
+v 2.9740700e-002 5.0324690e-002 -1.3990860e-002
+v -6.8796190e-002 3.5117720e-002 -5.2067400e-003
+v 5.8826020e-002 5.5503780e-002 1.8647920e-002
+v -2.6160570e-002 1.2309988e-001 -4.4735500e-003
+v -5.3341960e-002 1.4401200e-001 2.4261390e-002
+v 5.8177390e-002 5.2821320e-002 1.5182420e-002
+v 5.9798140e-002 5.6840180e-002 1.3342730e-002
+v 5.4549870e-002 5.6044630e-002 -6.6158000e-004
+v 2.6775460e-002 5.1423450e-002 -2.0234060e-002
+v -8.6960400e-003 1.7291588e-001 -2.6708770e-002
+v -7.7039560e-002 7.1967020e-002 2.6405070e-002
+v -6.3069890e-002 1.5897471e-001 -4.2951850e-002
+v 3.5706690e-002 5.6083040e-002 -8.9993300e-003
+v 3.2600380e-002 5.3707520e-002 -1.1006150e-002
+v 2.9739960e-002 5.2538430e-002 -1.6224950e-002
+v 5.9238530e-002 5.6362780e-002 9.4530800e-003
+v 5.7421750e-002 5.6012210e-002 4.0245600e-003
+v 2.9062990e-002 5.5210580e-002 -1.8042060e-002
+v -1.7224410e-002 9.5214090e-002 -3.2085300e-002
+v -8.5911380e-002 1.0968787e-001 7.6582400e-003
+v 6.0594930e-002 6.1677210e-002 1.5591560e-002
+v 5.9531640e-002 6.0504600e-002 5.8397000e-003
+v 5.7306470e-002 5.9944620e-002 1.8886400e-003
+v 3.8829380e-002 5.9839830e-002 -6.4252500e-003
+v 3.0662770e-002 5.7300390e-002 -1.6518370e-002
+v -2.7762070e-002 1.2068537e-001 -9.0152900e-003
+v -8.8194590e-002 1.0314633e-001 1.7509020e-002
+v 6.0778800e-002 6.1646560e-002 1.0463990e-002
+v 3.5915080e-002 5.9916380e-002 -1.1966510e-002
+v 2.4251860e-002 5.6457470e-002 -2.4254800e-002
+v -6.1954390e-002 1.6865320e-001 -5.2621160e-002
+v -9.0557930e-002 1.1275994e-001 1.6141030e-002
+v -8.8469220e-002 1.1124294e-001 1.2679160e-002
+v 5.9558010e-002 6.3099260e-002 5.9471000e-003
+v 3.0940440e-002 6.0518080e-002 -1.8132720e-002
+v -9.3575750e-002 1.2474629e-001 2.6213300e-002
+v -9.3189820e-002 1.2019919e-001 3.7913720e-002
+v -9.2296100e-003 1.7314463e-001 -2.4197660e-002
+v -8.1739460e-002 7.6861340e-002 2.3313610e-002
+v -3.6992750e-002 1.5063932e-001 -2.0372300e-003
+v 6.0093570e-002 6.5693450e-002 1.8533320e-002
+v 5.9837240e-002 6.6423180e-002 8.5139400e-003
+v 4.0706180e-002 6.4475310e-002 -5.5920300e-003
+v 3.4745940e-002 6.3261340e-002 -1.4646740e-002
+v -6.1879660e-002 1.6000450e-001 -2.5806250e-002
+v -7.6537810e-002 1.5344875e-001 -1.2898750e-002
+v 3.8111070e-002 6.4811810e-002 -1.1142000e-002
+v 3.1909340e-002 6.4657050e-002 -1.8473410e-002
+v -8.3159350e-002 1.4674277e-001 3.0757900e-003
+v -8.7055900e-002 1.0562761e-001 9.7651100e-003
+v -7.1448330e-002 1.8105301e-001 -5.5478550e-002
+v -8.5632110e-002 1.2461094e-001 -2.7335800e-003
+v 6.0728970e-002 6.5806600e-002 1.3974830e-002
+v 3.9909650e-002 6.8171740e-002 -9.5698200e-003
+v 3.4981790e-002 6.7740790e-002 -1.5683210e-002
+v -9.1822030e-002 1.2747346e-001 3.6458650e-002
+v -6.2425420e-002 1.6366637e-001 -4.9667290e-002
+v -7.1168950e-002 1.4740156e-001 -2.7590940e-002
+v -5.0364760e-002 1.3715763e-001 1.9526100e-003
+v -5.0492650e-002 1.4159899e-001 1.6291740e-002
+v 5.9886670e-002 6.8513050e-002 1.6171610e-002
+v -6.1406990e-002 1.7268822e-001 -5.8265750e-002
+v 2.4990740e-002 6.5897320e-002 -2.3568270e-002
+v -7.4852750e-002 1.4993112e-001 -2.7752940e-002
+v -6.2225690e-002 6.0265200e-002 2.0449290e-002
+v -6.2001940e-002 3.6435020e-002 4.3918940e-002
+v 5.8374570e-002 7.1186410e-002 1.3072740e-002
+v -3.6125040e-002 1.2286688e-001 -8.2927900e-003
+v 2.9216510e-002 6.7850250e-002 -2.0418570e-002
+v -4.1681700e-002 1.2575112e-001 -7.0193300e-003
+v -7.4226550e-002 1.6437012e-001 -3.8240340e-002
+v -9.7845700e-003 1.6928488e-001 -2.4756660e-002
+v -8.9577950e-002 1.2078310e-001 3.5229100e-003
+v -6.2311930e-002 1.6371109e-001 -4.0623990e-002
+v 4.3514770e-002 9.1519890e-002 -2.6468100e-003
+v -4.8434350e-002 1.3754973e-001 1.3244980e-002
+v -8.9313160e-002 1.3653006e-001 3.0458750e-002
+v -7.4230190e-002 1.5652681e-001 -2.5167090e-002
+v 3.7378600e-002 7.3093410e-002 -1.2635370e-002
+v 2.6321810e-002 7.0240650e-002 -2.3878680e-002
+v -4.8023620e-002 1.4426649e-001 4.2498600e-003
+v -9.2019580e-002 1.1611534e-001 3.5842730e-002
+v -7.1305510e-002 7.3899020e-002 3.5969780e-002
+v -6.2059290e-002 1.5697807e-001 -3.3784580e-002
+v -9.7015300e-003 1.6738863e-001 -1.9360250e-002
+v 4.3342140e-002 7.1676120e-002 -2.2304600e-003
+v 4.1772460e-002 6.9568020e-002 -6.1596000e-003
+v 3.3505410e-002 7.2809860e-002 -1.7034800e-002
+v 2.9665000e-002 7.1506830e-002 -2.1282340e-002
+v -2.9460160e-002 1.5550263e-001 -1.1914700e-003
+v -8.6396440e-002 1.0479356e-001 5.9820600e-003
+v -5.4910700e-002 1.4662313e-001 2.8438970e-002
+v 4.4203810e-002 8.5204260e-002 -2.1170500e-003
+v 4.3264350e-002 7.5810540e-002 -3.8843900e-003
+v 1.3096990e-002 9.1126480e-002 -2.9269770e-002
+v -6.7069210e-002 9.1144610e-002 -1.7425950e-002
+v -9.0821680e-002 1.2276896e-001 6.0998500e-003
+v 4.5620000e-002 7.4684430e-002 2.6073900e-003
+v -9.3039800e-002 1.2026416e-001 1.1216820e-002
+v 4.4635590e-002 9.2794290e-002 1.7832070e-002
+v -1.1243390e-002 1.6457514e-001 -1.8240780e-002
+v 4.5511190e-002 8.6953050e-002 3.8865500e-003
+v 4.6252720e-002 7.7373870e-002 6.9140800e-003
+v 4.0281640e-002 7.2637130e-002 -9.2881000e-003
+v 4.3218200e-002 9.9486740e-002 5.0153300e-003
+v -5.1108270e-002 1.4520219e-001 1.4279480e-002
+v 4.4692980e-002 9.2688550e-002 2.2466700e-003
+v 4.3422540e-002 9.1860370e-002 2.4538450e-002
+v 4.0751360e-002 1.0554729e-001 7.5074100e-003
+v -8.5613030e-002 9.6277110e-002 -6.6514000e-004
+v 4.0721470e-002 7.8475530e-002 -8.2130000e-003
+v 3.5538080e-002 7.6062960e-002 -1.4434750e-002
+v -9.2736510e-002 1.2073095e-001 3.2692730e-002
+v -6.2278520e-002 1.5166598e-001 -1.4672730e-002
+v 4.4960220e-002 8.0942630e-002 6.1119000e-004
+v 3.7814740e-002 7.9698150e-002 -1.3289630e-002
+v 3.3864490e-002 7.8656690e-002 -1.7632490e-002
+v -9.1044280e-002 1.4199862e-001 2.1729630e-002
+v -7.4004450e-002 1.7818523e-001 -5.3916320e-002
+v -6.1768650e-002 1.6067957e-001 -3.4046350e-002
+v -4.9747450e-002 1.4112519e-001 5.2937500e-003
+v 4.1065440e-002 9.0460700e-002 2.9888620e-002
+v -7.2916360e-002 6.5057400e-002 1.8794620e-002
+v -9.0949690e-002 1.3895375e-001 1.7371130e-002
+v 4.2879050e-002 1.0093777e-001 9.4753200e-003
+v -7.2455480e-002 1.7610676e-001 -5.3535420e-002
+v -7.5862940e-002 1.5071299e-001 -9.0209000e-003
+v -8.5269820e-002 1.0267793e-001 1.3935600e-003
+v -7.7025570e-002 1.1396763e-001 -4.6168100e-003
+v 4.6280880e-002 7.8702020e-002 1.4786330e-002
+v 4.2106910e-002 8.1533160e-002 -6.6690900e-003
+v 3.6523880e-002 8.1991750e-002 -1.6229590e-002
+v -3.7420220e-002 4.5428500e-002 -2.4226790e-002
+v -8.5148910e-002 1.3965520e-001 2.4808500e-003
+v -6.3313300e-002 1.6503258e-001 -3.2895120e-002
+v -6.1591410e-002 1.5681572e-001 -2.5945630e-002
+v 4.5918540e-002 8.7036220e-002 8.4236300e-003
+v 4.4631140e-002 8.4178380e-002 8.2665000e-004
+v -4.4842870e-002 1.4629393e-001 1.7114800e-003
+v -6.4124180e-002 1.7953625e-001 -5.8730420e-002
+v -6.7070300e-002 1.8072682e-001 -5.6618620e-002
+v -6.4793760e-002 1.7885275e-001 -5.5883250e-002
+v -6.4371030e-002 1.7296209e-001 -4.9225660e-002
+v -7.0381530e-002 1.8071180e-001 -5.3172590e-002
+v -7.5269270e-002 1.5232949e-001 3.4374060e-002
+v -1.6273090e-002 1.2844514e-001 1.6683610e-002
+v -6.2116150e-002 1.5600787e-001 1.8034420e-002
+v -5.6010790e-002 1.5381662e-001 2.5369280e-002
+v -3.7277920e-002 1.7289068e-001 -8.6627000e-004
+v -7.4158700e-002 1.7987275e-001 -5.0794750e-002
+v -7.9039960e-002 1.5537445e-001 1.5141810e-002
+v -7.2505530e-002 1.5459529e-001 2.9588830e-002
+v -6.7738180e-002 1.7728865e-001 -5.0375960e-002
+v -7.5346900e-003 1.0021302e-001 4.7488700e-002
+v -5.9575620e-002 1.5472401e-001 2.6373250e-002
+v -7.7382710e-002 1.5346600e-001 3.0894990e-002
+v -8.1496670e-002 1.5473104e-001 1.9697340e-002
+v -7.2223320e-002 1.5896734e-001 -5.4242300e-003
+v -1.3708500e-002 1.8491150e-001 -2.5549550e-002
+v -4.3465340e-002 1.2451145e-001 2.2518890e-002
+v -6.9103650e-002 1.5559479e-001 1.6370800e-003
+v -7.3748080e-002 1.5539253e-001 2.3491700e-003
+v -6.8192410e-002 1.7439828e-001 -4.5365870e-002
+v -6.0052850e-002 1.5280350e-001 3.2887630e-002
+v -2.3459490e-002 1.2615386e-001 1.6613770e-002
+v -7.2777220e-002 1.7854465e-001 -4.8208800e-002
+v -7.6595580e-002 1.7753227e-001 -4.7118080e-002
+v 1.3906410e-002 1.2790838e-001 2.5110240e-002
+v -8.6367510e-002 1.0906537e-001 1.1980640e-002
+v -3.1358850e-002 1.2140977e-001 2.5971090e-002
+v -4.9104590e-002 1.3666879e-001 1.9314030e-002
+v -4.2930640e-002 1.2928436e-001 9.2700700e-003
+v -6.5320350e-002 1.5390322e-001 9.1386000e-004
+v -3.7606490e-002 1.2422605e-001 2.4313530e-002
+v 9.5078400e-003 1.3041865e-001 2.0715020e-002
+v -1.7976800e-003 1.3117283e-001 1.6360660e-002
+v 3.6231700e-003 1.3076791e-001 2.1168600e-002
+v -9.2674700e-002 1.1701945e-001 1.1889520e-002
+v -6.5739720e-002 1.5565338e-001 2.6017600e-002
+v -8.6561940e-002 1.4249188e-001 8.4326800e-003
+v -7.0731530e-002 1.5569959e-001 6.9058200e-003
+v -8.0840700e-003 1.3030537e-001 1.6872280e-002
+v -4.4286250e-002 1.2606625e-001 2.0795220e-002
+v -7.0222260e-002 1.5143521e-001 3.6718910e-002
+v -1.5210690e-002 1.8463639e-001 -2.2057240e-002
+v -1.7270750e-002 1.8699602e-001 -1.9977570e-002
+v -8.3560950e-002 1.5255943e-001 7.6806700e-003
+v -8.8130280e-002 9.7540510e-002 5.6788000e-003
+v -8.8399240e-002 1.3899000e-001 1.0640660e-002
+v -6.7780550e-002 1.5614453e-001 1.4276320e-002
+v -6.5864600e-003 1.2641717e-001 3.0226390e-002
+v -8.8746180e-002 1.3625578e-001 7.1477800e-003
+v -7.7206730e-002 1.5639950e-001 -1.8972540e-002
+v -9.3176480e-002 1.1821016e-001 2.3362360e-002
+v -2.3506850e-002 1.2672006e-001 1.0996900e-002
+v -6.6546650e-002 1.7171115e-001 -4.2127770e-002
+v -6.9136000e-002 1.7247836e-001 -3.9013330e-002
+v 5.7180270e-002 7.1107690e-002 8.0307600e-003
+v -7.5390870e-002 1.7952824e-001 -5.2402050e-002
+v -3.1828840e-002 1.2639115e-001 1.0013410e-002
+v -8.9888800e-003 1.2952269e-001 2.2026810e-002
+v 3.4325880e-002 1.1193312e-001 -2.2406500e-003
+v -8.1414950e-002 9.7100250e-002 -6.8745800e-003
+v -2.3298830e-002 1.8324307e-001 -1.7923000e-002
+v -6.1641660e-002 1.5582039e-001 1.1099820e-002
+v -8.8826450e-002 9.0483320e-002 2.1204700e-002
+v 5.8373130e-002 6.8067590e-002 5.7247600e-003
+v -4.3045630e-002 1.2785122e-001 1.6842260e-002
+v 3.0835720e-002 1.1554234e-001 -3.1785500e-003
+v -8.8631270e-002 9.4881200e-002 7.9337600e-003
+v -9.1715140e-002 1.1709957e-001 3.0809400e-002
+v -7.2083780e-002 1.7499844e-001 -4.1930320e-002
+v -6.9540630e-002 1.5308527e-001 3.3865720e-002
+v 6.0078690e-002 6.8129260e-002 1.1454500e-002
+v -4.0081060e-002 1.2628381e-001 1.9607250e-002
+v 3.2819930e-002 1.1655625e-001 4.4458600e-003
+v -7.2823220e-002 1.4510601e-001 -1.5654680e-002
+v -8.5270210e-002 1.0551770e-001 2.3290940e-002
+v -7.6051320e-002 1.1103825e-001 -6.2722100e-003
+v -8.6537730e-002 1.5154801e-001 2.5875370e-002
+v 5.5888480e-002 7.2579250e-002 1.0669650e-002
+v -5.4642360e-002 1.5522963e-001 1.2612400e-002
+v 3.6729960e-002 1.1116756e-001 3.8670600e-003
+v 3.1501870e-002 1.1725172e-001 1.6855100e-003
+v -7.8751550e-002 9.5240290e-002 -1.0600670e-002
+v -8.9408160e-002 1.4352815e-001 3.0924750e-002
+v -2.0891130e-002 1.8595338e-001 -1.5037360e-002
+v -7.0863560e-002 1.6136525e-001 -9.7324600e-003
+v -7.0919760e-002 1.7136688e-001 -3.2763750e-002
+v -3.0771290e-002 1.2564075e-001 1.6594770e-002
+v -5.4454180e-002 1.5297699e-001 2.2505190e-002
+v -1.5539500e-003 1.2754717e-001 2.9232870e-002
+v 2.9130550e-002 1.2027445e-001 6.1117500e-003
+v 2.5725940e-002 1.2122705e-001 -3.6150000e-005
+v -8.9318970e-002 9.9546980e-002 1.3418110e-002
+v -7.5429500e-002 1.7095605e-001 -3.2879890e-002
+v -2.8596020e-002 1.1901156e-001 2.9888170e-002
+v 2.1069780e-002 1.2497756e-001 1.0998100e-003
+v -9.2240760e-002 1.1816838e-001 4.1201730e-002
+v 2.4094600e-003 1.0016785e-001 4.6938070e-002
+v -5.6627620e-002 1.5270606e-001 2.9629030e-002
+v -5.7264800e-002 1.5506250e-001 1.9322430e-002
+v -3.6452070e-002 1.2199869e-001 2.7670650e-002
+v -7.4108160e-002 1.7355729e-001 -3.7986840e-002
+v 5.1537130e-002 7.3496690e-002 1.2698700e-002
+v -6.6096040e-002 1.5532529e-001 7.1561800e-003
+v 3.6102000e-002 1.1266103e-001 1.0491780e-002
+v 1.6715210e-002 1.2689851e-001 2.2331000e-004
+v -8.0767920e-002 1.4301400e-001 -1.5312800e-003
+v -9.1757600e-002 1.4334588e-001 1.7790710e-002
+v -8.6824940e-002 1.5280775e-001 1.5521450e-002
+v -6.5808100e-002 1.6764344e-001 -3.0558670e-002
+v -7.8217340e-002 1.6873975e-001 -3.3564250e-002
+v -7.2567060e-002 1.4753230e-001 4.1714090e-002
+v 5.8439960e-002 7.0200810e-002 1.7779620e-002
+v 5.6847560e-002 7.2017160e-002 1.7139380e-002
+v 5.4919390e-002 7.3161610e-002 1.5223590e-002
+v 4.7446900e-002 7.3691410e-002 1.2430020e-002
+v 1.2319360e-002 1.2903768e-001 1.3336200e-003
+v -7.9790640e-002 1.0351662e-001 -6.6275400e-003
+v -7.6655210e-002 1.5509766e-001 7.9686300e-003
+v 2.1747320e-002 1.2118456e-001 3.0878810e-002
+v -7.5260490e-002 1.4938613e-001 3.9175980e-002
+v -2.5919610e-002 1.8272826e-001 -1.3541090e-002
+v -6.7983790e-002 1.6974781e-001 -3.1627490e-002
+v 1.6831110e-002 1.2487146e-001 2.8425580e-002
+v 5.4016490e-002 7.2883850e-002 1.8678010e-002
+v 5.0522750e-002 7.3397910e-002 1.6166890e-002
+v -5.9582440e-002 1.5623338e-001 7.9209900e-003
+v 2.5343500e-002 1.2374750e-001 9.9818800e-003
+v 1.9262750e-002 1.2689390e-001 5.5552100e-003
+v -9.0758520e-002 1.4223375e-001 2.6008130e-002
+v -4.6548490e-002 1.3320769e-001 1.6889630e-002
+v -2.4106950e-002 1.8380887e-001 -1.1544760e-002
+v 8.6784400e-003 1.2894574e-001 2.6156880e-002
+v 2.4919200e-003 1.2983563e-001 2.4847110e-002
+v 5.7345150e-002 6.9482720e-002 2.1153510e-002
+v -8.5329840e-002 1.5339912e-001 2.0378290e-002
+v 3.2877320e-002 1.1691463e-001 9.2957500e-003
+v 2.4246630e-002 1.2377758e-001 4.8764500e-003
+v -4.7765650e-002 1.3301969e-001 2.2874020e-002
+v -6.3541830e-002 1.6332115e-001 -2.5912990e-002
+v -6.6605200e-002 1.6477375e-001 -2.0670760e-002
+v -6.8504220e-002 1.6732018e-001 -2.3959570e-002
+v -7.2759160e-002 1.6965906e-001 -2.7013420e-002
+v 4.8206850e-002 7.2698580e-002 1.6994630e-002
+v -2.7383180e-002 1.2324257e-001 2.1658860e-002
+v -4.5077500e-002 1.3124443e-001 1.1145770e-002
+v 2.9253150e-002 1.2057701e-001 1.2299330e-002
+v 1.3677610e-002 1.2967262e-001 6.9327400e-003
+v 8.4210900e-003 1.3090986e-001 6.2754400e-003
+v 9.6836000e-004 1.3064303e-001 2.5865900e-003
+v 3.0802000e-003 9.8307360e-002 5.0535640e-002
+v -5.2420170e-002 1.5310101e-001 1.2927370e-002
+v -7.0359720e-002 1.6906988e-001 -2.6144260e-002
+v 5.4359390e-002 7.1467260e-002 2.1381250e-002
+v 4.5161440e-002 7.1030380e-002 2.2530690e-002
+v 1.9320440e-002 1.2738348e-001 1.1296310e-002
+v -9.3281210e-002 1.2691094e-001 1.3505010e-002
+v -8.7405060e-002 1.0593990e-001 1.3645920e-002
+v -2.2851640e-002 9.0635040e-002 5.2280460e-002
+v -6.2099370e-002 1.5406697e-001 3.0837360e-002
+v -4.5851560e-002 1.2072981e-001 2.7665040e-002
+v 5.0781670e-002 7.2155170e-002 2.0680180e-002
+v -8.9607270e-002 1.3971105e-001 2.9308560e-002
+v -5.3323050e-002 1.5273520e-001 1.6213860e-002
+v -1.5227080e-002 1.2784878e-001 2.1545200e-002
+v 3.3663540e-002 1.1574212e-001 1.7181290e-002
+v 2.4000260e-002 1.2468761e-001 1.5517930e-002
+v -8.4166840e-002 9.7756820e-002 -3.2761900e-003
+v -3.6223590e-002 1.2777519e-001 9.8501500e-003
+v -3.9189580e-002 1.2828193e-001 5.0346300e-003
+v -3.3674050e-002 1.7774449e-001 -8.1799500e-003
+v -7.4488620e-002 1.5649443e-001 -2.5954600e-003
+v -4.6755620e-002 1.3284294e-001 8.1212800e-003
+v -8.4970410e-002 1.5322309e-001 1.2654460e-002
+v -1.0866210e-002 1.2691699e-001 2.7575440e-002
+v -3.1074000e-003 1.3072898e-001 5.6428500e-003
+v -8.8760540e-002 9.7037440e-002 2.1079040e-002
+v -6.4811320e-002 3.4530640e-002 1.5508440e-002
+v -6.4300260e-002 3.5086450e-002 2.4272050e-002
+v -6.6727020e-002 3.5895770e-002 3.3849430e-002
+v 1.9838510e-002 9.6518890e-002 -2.2785880e-002
+v -3.8670510e-002 1.6070199e-001 -1.2357760e-002
+v -7.6890090e-002 1.3041906e-001 -6.9570100e-003
+v -7.2539730e-002 3.5399270e-002 7.0298800e-003
+v -6.9209050e-002 3.5454810e-002 1.2042140e-002
+v -6.4160810e-002 3.5900770e-002 1.7687570e-002
+v -6.6804150e-002 3.7377740e-002 3.3296290e-002
+v -6.2928350e-002 3.9061660e-002 4.2707680e-002
+v -7.1752230e-002 3.6789350e-002 8.6966700e-003
+v -6.5171380e-002 3.7289500e-002 2.5953770e-002
+v -6.6392030e-002 3.7712350e-002 2.9621950e-002
+v -6.4558720e-002 3.9639900e-002 3.9411530e-002
+v -6.0145790e-002 4.1202050e-002 4.4293830e-002
+v -6.0318430e-002 3.8442990e-002 4.5245950e-002
+v -3.6756310e-002 8.8663360e-002 -2.3868800e-002
+v -3.9494750e-002 3.7551570e-002 4.2870900e-002
+v -7.2016030e-002 3.7572700e-002 3.9789400e-003
+v -7.1693630e-002 3.9461000e-002 6.0145000e-003
+v -7.1165950e-002 3.9366310e-002 8.1142100e-003
+v -6.9000300e-002 3.8467710e-002 1.0768900e-002
+v -6.7253420e-002 3.8142160e-002 1.3533960e-002
+v -6.1125670e-002 3.7790050e-002 1.9710900e-002
+v -3.9179680e-002 4.2406740e-002 4.1476070e-002
+v -3.5145960e-002 3.8585920e-002 4.7732690e-002
+v -2.8950940e-002 3.9285940e-002 5.3309090e-002
+v -1.8223900e-002 9.7494570e-002 4.6847940e-002
+v -6.6916260e-002 1.2278907e-001 -8.9077400e-003
+v -6.3754640e-002 3.8250120e-002 1.6593500e-002
+v -6.4415760e-002 4.1283840e-002 2.8243480e-002
+v -8.5856340e-002 9.7025390e-002 2.7414960e-002
+v -3.7501130e-002 4.0221900e-002 4.4296550e-002
+v -3.4333970e-002 4.0923630e-002 4.8425810e-002
+v -3.1172890e-002 4.0294330e-002 5.1312460e-002
+v -6.9997320e-002 4.2073080e-002 6.6897800e-003
+v -8.0379330e-002 9.7800660e-002 3.3645750e-002
+v -2.6273160e-002 7.7631160e-002 4.8356180e-002
+v -3.7501450e-002 4.2736690e-002 4.2988400e-002
+v -2.6177500e-002 4.2498930e-002 5.3315220e-002
+v -6.9637250e-002 4.1881270e-002 3.1825800e-003
+v -6.7156510e-002 4.1972860e-002 1.0240940e-002
+v -8.7405510e-002 1.0205209e-001 2.2020360e-002
+v -2.3944380e-002 7.8800140e-002 5.3534730e-002
+v -6.0902360e-002 4.3429500e-002 4.2678530e-002
+v -3.1217880e-002 4.3847510e-002 4.9780920e-002
+v -7.5729440e-002 1.0354026e-001 3.6070970e-002
+v -6.2425320e-002 4.1885720e-002 1.4646770e-002
+v -6.1051660e-002 4.4392230e-002 1.2421940e-002
+v 2.5855060e-002 8.9610660e-002 -2.2701840e-002
+v -7.7644960e-002 8.2214940e-002 3.5797660e-002
+v -6.0381270e-002 4.5921420e-002 4.0088740e-002
+v -2.4982010e-002 8.1777650e-002 5.3421060e-002
+v -3.4453850e-002 4.4563960e-002 4.5422990e-002
+v -2.9842910e-002 4.6782280e-002 4.7746920e-002
+v -1.5119580e-002 9.9930020e-002 4.4500270e-002
+v -6.7306470e-002 4.4176830e-002 7.5958300e-003
+v -5.7852990e-002 4.6444500e-002 1.1062610e-002
+v -5.1815260e-002 1.6392582e-001 1.7488800e-003
+v -5.5174130e-002 4.8383880e-002 3.8517780e-002
+v -7.8849150e-002 1.1867375e-001 5.0622870e-002
+v -2.7229070e-002 8.7991480e-002 4.7909730e-002
+v -7.5536880e-002 1.5977062e-001 -1.0438650e-002
+v -3.6151280e-002 4.6505140e-002 4.0740900e-002
+v -2.5439220e-002 9.0677870e-002 4.8852330e-002
+v -8.0050370e-002 1.1670406e-001 4.8762460e-002
+v -5.2513640e-002 4.7577880e-002 1.4858440e-002
+v -3.2043560e-002 5.0461830e-002 3.9341520e-002
+v -3.1487770e-002 4.6930210e-002 4.5253210e-002
+v -2.0321500e-002 9.3999570e-002 5.1588540e-002
+v -7.2145040e-002 9.1556450e-002 4.1494780e-002
+v -5.3644200e-002 4.9358170e-002 1.2201850e-002
+v -8.2403890e-002 1.2186563e-001 4.9365030e-002
+v -4.9754420e-002 4.9738300e-002 3.7037110e-002
+v -3.2332060e-002 4.8672840e-002 4.2523960e-002
+v -2.3122950e-002 9.4515900e-002 4.7358870e-002
+v -8.6347140e-002 9.1722090e-002 2.6811080e-002
+v -5.7713110e-002 4.8717820e-002 7.2765100e-003
+v -8.6970360e-002 8.8912090e-002 2.4879860e-002
+v -9.2237750e-002 1.2488519e-001 4.0786530e-002
+v -1.5862800e-002 9.7021620e-002 5.0139360e-002
+v -2.7720040e-002 5.0502090e-002 4.3340720e-002
+v -8.5918770e-002 1.4263412e-001 3.9849810e-002
+v -7.5097360e-002 9.0073560e-002 3.9581000e-002
+v -8.9430840e-002 1.4730552e-001 2.7694960e-002
+v -5.3288350e-002 5.1925760e-002 1.1730350e-002
+v -5.0168720e-002 5.3462260e-002 1.6255440e-002
+v -8.5986050e-002 1.4670902e-001 3.4827030e-002
+v -6.9937250e-002 8.6076860e-002 4.2175690e-002
+v -5.0399320e-002 5.1831330e-002 3.4037400e-002
+v -8.3298980e-002 1.4960772e-001 3.3740890e-002
+v -2.9174820e-002 5.2264530e-002 3.7637320e-002
+v -8.8763730e-002 1.1944938e-001 4.6560090e-002
+v -7.7693460e-002 1.7367969e-001 -4.1478670e-002
+v -8.3418140e-002 9.4127440e-002 3.0898450e-002
+v -5.6067510e-002 5.3470630e-002 7.3718200e-003
+v -7.8935630e-002 1.4817228e-001 3.9463070e-002
+v -6.7902770e-002 8.7817230e-002 4.3526990e-002
+v -4.4111240e-002 9.2883990e-002 -2.2373210e-002
+v -8.6605100e-002 1.3226807e-001 4.6783020e-002
+v -9.2654280e-002 1.2084025e-001 4.1629650e-002
+v -5.0887310e-002 5.2727900e-002 1.4455790e-002
+v -4.9763410e-002 5.6241200e-002 3.3624250e-002
+v -8.9771330e-002 1.2904861e-001 4.3022990e-002
+v -2.8054240e-002 5.4551030e-002 3.6786850e-002
+v -2.5867080e-002 5.6689210e-002 3.9182240e-002
+v -8.3702200e-002 1.2226381e-001 -3.7301400e-003
+v -8.1455470e-002 1.3012213e-001 5.2117660e-002
+v -5.1458550e-002 5.5878150e-002 1.5900350e-002
+v -7.8597700e-002 1.7441574e-001 -4.6607580e-002
+v -5.2909820e-002 5.7043070e-002 2.0988410e-002
+v -5.2978500e-002 5.9553770e-002 2.6211920e-002
+v -5.2130640e-002 5.6302970e-002 2.6672460e-002
+v -4.7714500e-002 6.1944520e-002 3.6705820e-002
+v -8.3539790e-002 8.1169560e-002 2.7014070e-002
+v -1.8340000e-002 5.7489970e-002 4.9763020e-002
+v -8.0069810e-002 9.0586130e-002 3.4593070e-002
+v -8.3812250e-002 8.6337700e-002 2.9223270e-002
+v -5.5436650e-002 5.9420250e-002 2.3018970e-002
+v -8.2227680e-002 1.4513771e-001 4.0600080e-002
+v -2.4187580e-002 7.2269150e-002 4.7681090e-002
+v -2.5353150e-002 6.2567200e-002 4.0642170e-002
+v -9.1132110e-002 1.2282100e-001 4.4115160e-002
+v -4.6076290e-002 1.6819719e-001 7.3744000e-004
+v -8.7829280e-002 1.4351461e-001 3.5707670e-002
+v -8.6990640e-002 1.3812326e-001 4.2316550e-002
+v -1.5715900e-002 6.0822970e-002 5.2365440e-002
+v -8.3803580e-002 1.2561100e-001 5.0440490e-002
+v -6.2786680e-002 1.1274190e-001 -1.3605440e-002
+v -8.1033840e-002 8.4698180e-002 3.3106400e-002
+v -8.8563540e-002 1.1624535e-001 4.5392840e-002
+v -2.0268380e-002 6.2266810e-002 4.8212120e-002
+v -1.2619630e-002 6.1635030e-002 5.4424080e-002
+v -7.0491190e-002 8.1818160e-002 4.0609890e-002
+v -8.3882520e-002 1.3331465e-001 4.9113540e-002
+v -5.6560350e-002 4.8355540e-002 3.6607050e-002
+v 9.9444900e-003 1.0919723e-001 -1.9472810e-002
+v -5.5928250e-002 3.5917310e-002 4.6376100e-002
+v -7.6003260e-002 1.6361344e-001 -1.8021110e-002
+v -8.3798850e-002 1.0290691e-001 2.8038330e-002
+v -8.8252110e-002 1.2692730e-001 4.6141300e-002
+v -7.9126720e-002 1.0619883e-001 3.2050700e-002
+v -8.8206230e-002 9.4485700e-002 2.3744010e-002
+v -8.9110330e-002 1.3851394e-001 3.7658780e-002
+v -1.9321360e-002 9.2123890e-002 5.3820650e-002
+v -5.8265630e-002 9.0926390e-002 -2.0948690e-002
+v -2.7046310e-002 6.7014450e-002 3.9672140e-002
+v -2.1416300e-002 1.7977662e-001 -2.1732520e-002
+v -7.8240000e-003 1.0924112e-001 -2.2185670e-002
+v -2.3988340e-002 8.5995590e-002 5.3716430e-002
+v -6.0483580e-002 1.5567975e-001 4.3343800e-003
+v -8.6389150e-002 1.2168475e-001 4.8412440e-002
+v -7.4084360e-002 1.4987744e-001 -3.2610050e-002
+v -2.0580600e-002 7.9572500e-002 5.6013880e-002
+v -8.3837500e-002 1.3927865e-001 4.4893850e-002
+v -2.2933960e-002 3.5632910e-002 5.2865490e-002
+v -8.6153620e-002 1.2735612e-001 4.8563960e-002
+v -6.5728590e-002 1.0709818e-001 -1.4317670e-002
+v -2.1481090e-002 7.4194460e-002 5.2857680e-002
+v -7.6423900e-002 1.5736285e-001 -9.0354600e-003
+v -7.7216010e-002 8.5594880e-002 3.7420770e-002
+v -8.4150830e-002 1.2955013e-001 5.0483700e-002
+v -8.1221440e-002 8.1003250e-002 3.1255840e-002
+v -8.1704000e-002 1.0167226e-001 3.0939660e-002
+v -8.6252730e-002 1.0106846e-001 2.5413770e-002
+v -8.0944970e-002 1.3903572e-001 4.7359080e-002
+v -7.8908350e-002 9.4830900e-002 3.5435500e-002
+v -7.3440160e-002 9.5412600e-002 4.0210650e-002
+v -5.2675780e-002 8.8220740e-002 -2.1886300e-002
+v -7.6440670e-002 7.7511060e-002 3.3748300e-002
+v -2.1791140e-002 1.0658035e-001 -2.2327000e-002
+v -8.8360940e-002 1.4996706e-001 2.6044170e-002
+v -2.4078870e-002 6.7906700e-002 4.5178370e-002
+v -2.0018090e-002 6.7569300e-002 5.1565340e-002
+v -8.3577750e-002 1.2052625e-001 4.9177500e-002
+v -1.4655950e-002 1.7456543e-001 -2.5972690e-002
+v -2.7395940e-002 8.4108300e-002 4.8745680e-002
+v -4.1933580e-002 8.8463400e-002 -2.2126350e-002
+v -3.1693900e-002 1.0261265e-001 -2.2352310e-002
+v -2.7890200e-002 1.0440703e-001 -2.2830920e-002
+v -7.3790400e-002 1.2016662e-001 -7.8851200e-003
+v -4.6124160e-002 1.0506369e-001 -2.0457580e-002
+v -2.7412650e-002 7.3269450e-002 4.2641380e-002
+v -4.5532880e-002 3.4736480e-002 -2.1363200e-002
+v -4.4993030e-002 3.9017010e-002 -2.1097830e-002
+v -4.6462610e-002 3.6800270e-002 -1.7778710e-002
+v -8.8366460e-002 1.1361863e-001 5.8227800e-003
+v 5.1746240e-002 7.2897250e-002 9.0647400e-003
+v -7.0385250e-002 3.7450300e-002 -9.3190000e-004
+v -6.0923170e-002 3.8621820e-002 2.2468850e-002
+v -7.7696720e-002 1.7027889e-001 -4.3117910e-002
+v -4.3793210e-002 1.6955506e-001 -7.3026400e-003
+v -7.7587180e-002 1.7717875e-001 -5.0221090e-002
+v -4.0541880e-002 3.8886010e-002 -2.7364950e-002
+v -4.4215850e-002 3.6131460e-002 -2.4252210e-002
+v -6.6634880e-002 4.0430310e-002 -5.0180700e-003
+v -6.9242120e-002 4.1474050e-002 1.9289000e-004
+v -7.5640690e-002 1.5930400e-001 -2.6908460e-002
+v -6.3087030e-002 3.9614170e-002 2.5181560e-002
+v -7.2303020e-002 1.5186699e-001 -4.1544310e-002
+v -4.1051490e-002 4.1528620e-002 -2.4061000e-002
+v -4.6990580e-002 3.8892380e-002 -1.4016920e-002
+v -8.9559690e-002 1.2851666e-001 4.5457500e-003
+v -7.6987340e-002 1.5369375e-001 -2.2970800e-003
+v -7.0121670e-002 1.6882633e-001 -5.1173650e-002
+v -6.4792610e-002 4.1724530e-002 3.1616900e-002
+v -4.2148060e-002 1.2409627e-001 -9.5602500e-003
+v -4.8069700e-002 1.2493027e-001 -8.4076400e-003
+v -4.2150480e-002 4.3343970e-002 -2.1508710e-002
+v -6.7315160e-002 4.4034000e-002 1.5741800e-003
+v -7.3386640e-002 1.5463418e-001 -2.9943830e-002
+v -5.5352770e-002 4.2936210e-002 1.9135490e-002
+v -6.0067770e-002 4.1419500e-002 2.2953280e-002
+v -6.5488460e-002 4.0937780e-002 3.5315470e-002
+v -8.0066400e-002 1.5039650e-001 6.0518000e-004
+v -4.4031300e-002 4.1949070e-002 -1.7993960e-002
+v -4.5186510e-002 4.2453420e-002 -1.4193620e-002
+v -8.3109430e-002 1.0265445e-001 -3.2933400e-003
+v -6.5472800e-002 4.5627570e-002 4.5575400e-003
+v -7.5427730e-002 1.5201213e-001 -1.4393690e-002
+v -5.4473420e-002 4.5937510e-002 2.3612600e-002
+v -6.2464100e-002 4.3722000e-002 2.8493310e-002
+v -6.2832600e-002 4.5182750e-002 3.4622890e-002
+v -6.3538130e-002 4.3524020e-002 3.7974010e-002
+v -6.0255260e-002 4.4749620e-002 -4.1316200e-003
+v -6.3242050e-002 4.5549700e-002 4.8428000e-004
+v -6.2249430e-002 4.6540050e-002 7.1903500e-003
+v -9.1003650e-002 1.4885725e-001 2.1507030e-002
+v -5.7094130e-002 4.5996540e-002 2.6865280e-002
+v -5.7276490e-002 4.7299580e-002 2.9889950e-002
+v -3.9519900e-002 1.7385855e-001 -7.5752600e-003
+v -8.9641110e-002 1.3841920e-001 3.4141800e-002
+v -9.2601430e-002 1.3018652e-001 2.5183580e-002
+v -9.2280860e-002 1.2762053e-001 2.9751670e-002
+v -3.3957310e-002 4.1025060e-002 -2.9660250e-002
+v -9.0199540e-002 1.1657506e-001 5.6754900e-003
+v -5.8515890e-002 4.7731310e-002 2.1246000e-004
+v -7.1723560e-002 1.4617438e-001 -2.1567820e-002
+v -5.2389820e-002 4.5449130e-002 1.7686300e-002
+v -5.9414350e-002 4.7277990e-002 3.4172420e-002
+v -5.7520620e-002 1.5877600e-001 4.1621200e-003
+v -8.0959140e-002 1.0926674e-001 -2.0189900e-003
+v -5.1904000e-002 4.6100060e-002 1.9421290e-002
+v -5.1830050e-002 4.8568730e-002 2.1647030e-002
+v -7.7650400e-002 1.5658012e-001 -1.6599150e-002
+v -3.7416450e-002 4.7682130e-002 -1.7147280e-002
+v -7.8876110e-002 1.5347012e-001 3.9875800e-003
+v -5.7635420e-002 5.0425540e-002 4.6108400e-003
+v -5.2625440e-002 5.0434620e-002 2.9046740e-002
+v -5.2998720e-002 4.9169020e-002 3.3967600e-002
+v -7.3502600e-002 1.6871934e-001 -4.4791800e-002
+v -5.4420720e-002 4.7836520e-002 -5.9186900e-003
+v -5.2312740e-002 5.1085350e-002 2.4485690e-002
+v -7.9129930e-002 1.6736568e-001 -3.5506230e-002
+v 9.4115700e-003 1.2350285e-001 -9.8291000e-003
+v -3.2715700e-002 1.0896631e-001 -1.8941410e-002
+v -3.1133380e-002 4.9607260e-002 -1.9406940e-002
+v 4.5997330e-002 6.9814450e-002 3.0143300e-003
+v 3.3525460e-002 1.0966209e-001 -6.9894800e-003
+v -5.5047160e-002 5.2767560e-002 -3.9461300e-003
+v -5.6897890e-002 4.9655570e-002 -1.5319000e-003
+v -5.0290500e-002 4.9098930e-002 1.7164780e-002
+v -5.0595170e-002 4.9923270e-002 1.9174130e-002
+v -5.1887420e-002 5.3324670e-002 2.8705560e-002
+v -6.7684480e-002 1.6533627e-001 -5.5466400e-002
+v -3.0271440e-002 5.2106080e-002 -1.7676140e-002
+v -9.1087300e-003 1.1141669e-001 -2.0543230e-002
+v -5.7069360e-002 5.4424380e-002 2.3395500e-003
+v -3.2748380e-002 1.7759875e-001 -1.1627470e-002
+v -2.9009580e-002 5.1265290e-002 -2.2175780e-002
+v -3.1383130e-002 5.1791310e-002 -1.3886800e-002
+v -5.5673960e-002 5.6983850e-002 -3.3510400e-003
+v -5.0916050e-002 5.3813610e-002 1.9753140e-002
+v -8.8875380e-002 1.5169443e-001 2.0086580e-002
+v -7.7153050e-002 1.7378676e-001 -4.7867620e-002
+v -7.8577770e-002 1.6420639e-001 -3.1825860e-002
+v -2.7545910e-002 5.4021570e-002 -2.5147390e-002
+v -5.4463660e-002 5.5357450e-002 1.0326840e-002
+v -8.7041410e-002 1.3058932e-001 9.1161000e-004
+v -9.0009340e-002 1.3278082e-001 5.9220600e-003
+v -9.2232620e-002 1.3195400e-001 1.5430650e-002
+v -4.8639980e-002 1.6472475e-001 -5.0591500e-003
+v -5.4066480e-002 5.9959350e-002 -7.5992200e-003
+v -5.7434090e-002 5.7683500e-002 8.7259700e-003
+v -8.6794730e-002 1.3850688e-001 4.5575900e-003
+v -9.2989530e-002 1.3092307e-001 1.9919290e-002
+v -9.1282030e-002 1.3311897e-001 2.4688630e-002
+v 2.1815020e-002 1.1770533e-001 -1.0015300e-002
+v -2.9647120e-002 5.8104260e-002 -2.1311320e-002
+v -3.1289530e-002 5.5208570e-002 -1.4387840e-002
+v -5.9002160e-002 5.9234620e-002 2.6140800e-003
+v -9.0241700e-002 1.3575994e-001 1.4149160e-002
+v -6.1569420e-002 1.7084875e-001 -6.1679170e-002
+v -6.6070180e-002 1.6557822e-001 -5.8644080e-002
+v -2.4539930e-002 1.8005865e-001 -1.8726950e-002
+v -1.6131750e-002 1.8298848e-001 -2.6037190e-002
+v -3.0809390e-002 5.6998040e-002 -1.7835020e-002
+v 1.0464280e-002 9.6180450e-002 -2.5898970e-002
+v -5.7491630e-002 5.9530160e-002 -1.0786100e-003
+v -8.9146460e-002 1.3650500e-001 2.5952780e-002
+v 4.3714500e-003 1.0391901e-001 -2.1515100e-002
+v -9.0377040e-002 1.3252490e-001 3.1082650e-002
+v -9.0795450e-002 1.3855232e-001 2.0562560e-002
+v -9.4237710e-002 1.2615419e-001 2.2201450e-002
+v -9.0336910e-002 1.3119830e-001 3.8138790e-002
+v -4.5082610e-002 1.2218447e-001 -1.1569430e-002
+v 1.1348010e-002 9.8243750e-002 -2.3024250e-002
+v -3.9227920e-002 9.9184630e-002 -2.1912720e-002
+v -6.5509530e-002 1.5857325e-001 -5.5600270e-002
+v -7.7409510e-002 1.6260515e-001 -2.0754580e-002
+v -4.8580010e-002 1.6689211e-001 -2.5256100e-003
+v -7.6922910e-002 1.5351394e-001 -9.0785600e-003
+v -6.7750580e-002 1.5734825e-001 -5.3982110e-002
+v 5.2906410e-002 6.5230450e-002 -5.1112000e-004
+v -2.9054820e-002 6.1084120e-002 -2.4918230e-002
+v -3.1066920e-002 6.5058860e-002 -2.2751080e-002
+v 2.4249720e-002 1.0266151e-001 -1.8313830e-002
+v -5.5473660e-002 1.6050213e-001 1.3763500e-003
+v -6.6642850e-002 1.6040875e-001 -5.6842680e-002
+v -7.8200320e-002 1.6073213e-001 -2.3999690e-002
+v -1.8320680e-002 1.1968625e-001 -1.1110660e-002
+v 2.1712970e-002 1.0956342e-001 -1.5081090e-002
+v -6.8382640e-002 1.5980248e-001 -5.4208800e-002
+v -2.5445620e-002 6.0208550e-002 -3.0864700e-002
+v -2.6540330e-002 6.5084000e-002 -3.1664870e-002
+v -2.8425710e-002 6.2199610e-002 -2.7938500e-002
+v -3.2605750e-002 6.1264600e-002 -1.5453010e-002
+v -7.0872290e-002 1.1611638e-001 -7.9563700e-003
+v -6.9780530e-002 1.5938570e-001 -4.9418240e-002
+v -3.0324870e-002 6.7694720e-002 -2.7654950e-002
+v -3.2977370e-002 6.6365180e-002 -1.8385530e-002
+v 1.3533490e-002 1.0255388e-001 -2.1579310e-002
+v 4.4408530e-002 6.9758860e-002 9.4765000e-004
+v -2.1999000e-003 1.1215881e-001 -1.9658660e-002
+v -7.2028500e-002 6.7046610e-002 -7.2256000e-004
+v -7.8699630e-002 1.7313910e-001 -4.2720470e-002
+v -8.3211970e-002 1.5072131e-001 4.2128500e-003
+v -8.7439060e-002 1.3374875e-001 2.3974700e-003
+v 2.6348020e-002 8.4562230e-002 -2.3151710e-002
+v -7.4901490e-002 7.0419350e-002 -2.2854300e-003
+v -5.4576350e-002 9.1562950e-002 -2.2098700e-002
+v -7.3242520e-002 1.5231332e-001 -3.5703520e-002
+v -7.4550960e-002 1.7218738e-001 -4.7551010e-002
+v -2.8680680e-002 6.8283500e-002 -3.0610160e-002
+v 1.7372900e-002 1.0246037e-001 -2.1487700e-002
+v -8.1257430e-002 7.3025200e-002 7.1020400e-003
+v -7.4982300e-002 1.5407794e-001 -1.8974470e-002
+v -9.1556500e-002 1.3196262e-001 1.0638150e-002
+v -8.2448000e-004 9.5165120e-002 -3.2056320e-002
+v -7.7618830e-002 7.3999130e-002 -5.3263500e-003
+v -7.9858790e-002 7.2755040e-002 3.0420200e-003
+v -8.1627470e-002 7.3470610e-002 1.1161690e-002
+v -7.3679290e-002 1.4785987e-001 -2.0236290e-002
+v -9.1309820e-002 1.4848588e-001 1.6270070e-002
+v -9.0850140e-002 1.4625613e-001 1.4809050e-002
+v -6.8543890e-002 1.7513008e-001 -5.7187900e-002
+v -2.7253960e-002 1.0747453e-001 -2.1279680e-002
+v 2.1443580e-002 1.2273826e-001 -2.9316700e-003
+v -7.9061200e-002 7.3724300e-002 -8.4521000e-004
+v -8.2063500e-002 7.5993670e-002 1.7615500e-003
+v -8.3736580e-002 7.6771840e-002 8.9586000e-003
+v -9.0205720e-002 1.4947775e-001 1.3035090e-002
+v 8.4818000e-004 1.1670025e-001 -1.7337090e-002
+v -7.4577550e-002 1.5164041e-001 -2.8647990e-002
+v -2.9087460e-002 7.2924630e-002 -3.3354470e-002
+v -3.1184020e-002 7.3989530e-002 -3.0339870e-002
+v -3.2606620e-002 7.1955620e-002 -2.4866580e-002
+v -8.0575990e-002 7.6607800e-002 -2.9879400e-003
+v -8.9491020e-002 1.4392581e-001 1.2488490e-002
+v -7.7388410e-002 1.4656426e-001 -4.3543000e-003
+v -7.2896160e-002 1.5834962e-001 -3.4109420e-002
+v 7.1346500e-003 1.1468229e-001 -1.8345640e-002
+v -3.4502610e-002 7.6130020e-002 -2.2373150e-002
+v -8.3890740e-002 8.0789530e-002 2.2951400e-003
+v -8.3740480e-002 7.7240270e-002 4.6673300e-003
+v -8.6204620e-002 8.0930750e-002 1.0535420e-002
+v -8.6061500e-002 7.9931100e-002 1.4440780e-002
+v -8.1542760e-002 7.7950660e-002 2.6727280e-002
+v 2.6666170e-002 1.1268609e-001 -1.0509540e-002
+v -7.6041430e-002 1.5663068e-001 -2.1420480e-002
+v -9.0012110e-002 1.5083344e-001 1.5752740e-002
+v -7.1156510e-002 1.6335125e-001 -4.5360530e-002
+v -3.3210960e-002 7.6873190e-002 -2.7708380e-002
+v -7.3263090e-002 7.9983830e-002 -1.3749940e-002
+v -7.9285950e-002 8.0048830e-002 -7.0125500e-003
+v -8.6034510e-002 8.2645720e-002 1.9542680e-002
+v -8.4335410e-002 8.0729950e-002 2.2180460e-002
+v -7.1351460e-002 1.5727092e-001 -4.2183090e-002
+v -7.3548450e-002 1.6120822e-001 -3.5288420e-002
+v 1.6732620e-002 1.0991230e-001 -1.7020040e-002
+v -3.0978770e-002 7.7020860e-002 -3.2816490e-002
+v -6.2359240e-002 1.7544824e-001 -6.1485990e-002
+v -1.7587870e-002 1.1491318e-001 -1.7205040e-002
+v -8.2354050e-002 8.0876320e-002 -2.4038900e-003
+v -7.8578910e-002 1.4050129e-001 -4.6031000e-003
+v -2.8931080e-002 7.9247620e-002 -3.5049800e-002
+v -3.1225710e-002 8.0413100e-002 -3.2182320e-002
+v -3.3258680e-002 7.9621670e-002 -2.7146060e-002
+v -4.4697400e-002 1.1791537e-001 -1.4725860e-002
+v -7.9723740e-002 8.4226660e-002 -8.7608600e-003
+v -8.5042160e-002 8.3817830e-002 -7.7640000e-005
+v -8.6776400e-002 8.4344860e-002 1.2419030e-002
+v -8.6674670e-002 8.2665010e-002 1.5174340e-002
+v -8.5106250e-002 8.5176580e-002 2.5679440e-002
+v -7.6975760e-002 8.2935940e-002 -1.1450630e-002
+v -8.2776390e-002 8.3430890e-002 -4.3687000e-003
+v -8.6180440e-002 8.2572150e-002 6.3639000e-003
+v -9.1160820e-002 1.4144362e-001 1.5673910e-002
+v -7.4638800e-002 1.4398484e-001 -7.1504600e-003
+v -8.3448500e-002 1.3393299e-001 -1.6873200e-003
+v -7.5804700e-002 1.5134475e-001 -1.9881200e-002
+v -7.4924140e-002 1.5273013e-001 -1.9397440e-002
+v -5.2314440e-002 1.2159646e-001 -1.0798060e-002
+v -3.0734050e-002 8.5427560e-002 -3.0506670e-002
+v -3.2590560e-002 8.1942660e-002 -2.9100210e-002
+v -8.6454830e-002 8.6940490e-002 9.1667000e-004
+v -1.2501820e-002 1.0634409e-001 -2.2360190e-002
+v -8.8585880e-002 1.4605869e-001 9.8780000e-003
+v -8.5609750e-002 1.4712513e-001 6.5981100e-003
+v -8.7511210e-002 1.5061504e-001 1.0152460e-002
+v -6.0113540e-002 3.5550440e-002 4.4907580e-002
+v -8.8284200e-002 8.6869110e-002 8.1029200e-003
+v -8.8812560e-002 8.7765490e-002 1.4226540e-002
+v -8.8001070e-002 8.6626430e-002 1.5466680e-002
+v -8.6991110e-002 8.6444700e-002 2.2420950e-002
+v -7.4609990e-002 1.4727815e-001 -1.4172380e-002
+v -3.4707910e-002 8.4035880e-002 -2.4302260e-002
+v -8.4964900e-002 8.9962540e-002 -3.0068000e-003
+v -8.8091450e-002 8.7741580e-002 4.8489900e-003
+v -9.1490470e-002 1.4543178e-001 2.2277220e-002
+v -9.4380420e-002 1.2183919e-001 1.7904340e-002
+v -2.9164530e-002 8.5393440e-002 -3.3666780e-002
+v -3.0557790e-002 8.8625920e-002 -2.7550670e-002
+v -7.7770550e-002 8.7844840e-002 -1.1694810e-002
+v -8.0728260e-002 8.8204150e-002 -7.8003100e-003
+v -8.3272540e-002 8.9476690e-002 -5.6502900e-003
+v -8.9398710e-002 8.9539000e-002 1.1645550e-002
+v -8.9698390e-002 1.3971257e-001 1.3774760e-002
+v -7.7134890e-002 1.5151225e-001 -5.5823000e-003
+v -5.1121410e-002 1.6374125e-001 -2.6640500e-003
+v -8.6442960e-002 1.2767438e-001 -1.4864100e-003
+v -6.9605590e-002 1.5490763e-001 -5.0188670e-002
+v -8.7265180e-002 9.2110030e-002 4.2059000e-003
+v -8.9086250e-002 9.2377120e-002 1.0569860e-002
+v -8.9612340e-002 9.1599880e-002 1.7812280e-002
+v -8.2732460e-002 1.4196856e-001 1.2529100e-003
+v -7.2618370e-002 1.4368135e-001 -1.0987100e-002
+v -7.7677230e-002 1.6610992e-001 -3.6777320e-002
+v -1.5078060e-002 9.3863440e-002 -3.4317310e-002
+v -7.1057280e-002 1.5476885e-001 -4.5778530e-002
+v -9.2331920e-002 1.2523886e-001 9.1589500e-003
+v -7.6046700e-002 9.1037250e-002 -1.3643150e-002
+v -8.2942810e-002 9.3291700e-002 -6.1856300e-003
+v -1.0411170e-002 9.4592340e-002 -3.3784850e-002
+v -2.9331140e-002 1.1476230e-001 -1.5844640e-002
+v -3.7218250e-002 1.1594244e-001 -1.5173050e-002
+v -1.2429920e-002 1.0286006e-001 -2.3822480e-002
+v 6.6509600e-003 8.8144500e-002 -3.2945810e-002
+v -6.4119900e-003 9.2876210e-002 -3.4817640e-002
+v 1.5800150e-002 1.1996558e-001 -1.1415630e-002
+v 2.9102740e-002 1.0247506e-001 -1.5768380e-002
+v 4.2080690e-002 6.3480630e-002 -2.5405300e-003
+v 2.8723120e-002 9.7943220e-002 -1.7497350e-002
+v -1.9987640e-002 1.0278313e-001 -2.3392920e-002
+v 3.3748350e-002 8.3644140e-002 -1.8630450e-002
+v -1.8685680e-002 1.8689625e-001 -2.0248700e-002
+v 6.4154900e-003 1.1790181e-001 -1.6282740e-002
+v 5.6305210e-002 6.7769910e-002 2.6525000e-003
+v -5.3608300e-003 1.1289400e-001 -1.9613290e-002
+v 4.5769430e-002 6.4628800e-002 -1.2166100e-003
+v -1.0090870e-002 9.8229650e-002 -2.7731360e-002
+v -6.0458520e-002 1.1755645e-001 -1.1354580e-002
+v 1.2933940e-002 1.1887250e-001 -1.3979370e-002
+v 1.5235680e-002 9.4977900e-002 -2.4437140e-002
+v -3.0892950e-002 4.7409030e-002 -2.4954000e-002
+v -1.7766190e-002 1.8572344e-001 -2.3049280e-002
+v -1.3034890e-002 1.1002855e-001 -2.0161170e-002
+v -7.1206550e-002 3.8608570e-002 7.7218000e-004
+v 1.7904800e-002 1.0627709e-001 -1.7729250e-002
+v -3.3623490e-002 1.1840428e-001 -1.1927480e-002
+v -4.9906840e-002 1.1788332e-001 -1.4402480e-002
+v -6.6878100e-003 1.1747209e-001 -1.5359280e-002
+v -1.5451470e-002 1.8597600e-001 -2.4795870e-002
+v -3.0603900e-002 3.8038460e-002 -3.0123840e-002
+v -1.3220270e-002 1.8397188e-001 -2.7519460e-002
+v -4.7859450e-002 1.1162729e-001 -1.7482120e-002
+v -1.3098990e-002 9.0776040e-002 -3.6659270e-002
+v -6.3117340e-002 1.5425437e-001 2.9730400e-003
+v -5.5139750e-002 1.1051601e-001 -1.7672740e-002
+v -1.1096770e-002 1.8202324e-001 -2.8042450e-002
+v -2.6568900e-002 3.4695830e-002 -2.9113750e-002
+v -6.6396600e-003 1.0222209e-001 -2.3519320e-002
+v -5.6996400e-002 1.5741713e-001 6.0244000e-004
+v 1.9076550e-002 9.1870620e-002 -2.4890230e-002
+v 1.3473090e-002 1.2429893e-001 -6.8361400e-003
+v -2.1730490e-002 9.8410960e-002 -2.4306850e-002
+v -1.7142170e-002 9.8057460e-002 -2.4924330e-002
+v -5.8698110e-002 1.5137318e-001 -6.5801000e-004
+v 3.5641100e-003 1.2764883e-001 -4.4672400e-003
+v -8.5369800e-003 9.9921220e-002 -2.4351070e-002
+v -1.2171980e-002 1.8125102e-001 -2.9061170e-002
+v -6.1113980e-002 1.5305212e-001 9.9983000e-004
+v -2.9570620e-002 1.1713871e-001 -1.3675530e-002
+v 3.0530110e-002 1.1221207e-001 -8.1860600e-003
+v -3.1714100e-002 3.5111530e-002 -3.0658990e-002
+v -1.3691130e-002 1.7914707e-001 -2.8126410e-002
+v 1.1620840e-002 1.1548972e-001 -1.6385680e-002
+v -6.1993570e-002 1.5028063e-001 -1.6297100e-003
+v 3.6684020e-002 1.0099570e-001 -9.8485900e-003
+v 4.8512670e-002 7.1798180e-002 6.0005000e-003
+v -4.6583000e-004 1.1983662e-001 -1.3610580e-002
+v 1.6747170e-002 9.0113950e-002 -2.7127190e-002
+v 6.9832400e-003 9.7730080e-002 -2.4800310e-002
+v -4.3226830e-002 4.6263570e-002 -1.1771730e-002
+v -8.3562500e-003 1.1373600e-001 -1.8239810e-002
+v -1.2354410e-002 1.1556773e-001 -1.6486930e-002
+v 4.6834470e-002 7.4354100e-002 1.0139500e-002
+v 2.5319170e-002 1.0931725e-001 -1.3579660e-002
+v -4.2459500e-002 1.1392482e-001 -1.6188050e-002
+v 5.7744640e-002 6.4158440e-002 2.6277600e-003
+v -5.9710530e-002 3.6535780e-002 -9.4949000e-003
+v -3.2078400e-003 1.0962100e-001 -2.1523850e-002
+v 2.7020740e-002 6.1345700e-002 -2.2292060e-002
+v 7.1030200e-003 1.0191162e-001 -2.1230990e-002
+v -3.8225680e-002 1.2465525e-001 -7.3257400e-003
+v 2.5941540e-002 1.1576352e-001 -8.2193900e-003
+v -6.1297960e-002 3.3900220e-002 -9.3216600e-003
+v -5.9466670e-002 1.4743956e-001 -1.8885400e-003
+v 1.0506610e-002 1.0087700e-001 -2.2109510e-002
+v 3.3081340e-002 1.0273382e-001 -1.2787210e-002
+v 1.2517840e-002 1.0475378e-001 -1.9915960e-002
+v 2.3087990e-002 9.3998720e-002 -2.2210680e-002
+v 3.1555430e-002 9.2484730e-002 -1.8204280e-002
+v 6.2723100e-003 9.9910370e-002 -2.2296890e-002
+v -4.0917240e-002 4.6121780e-002 -1.7942580e-002
+v 3.5407360e-002 9.8188850e-002 -1.2008970e-002
+v 9.4135900e-003 1.2121902e-001 -1.2937780e-002
+v 5.3735190e-002 7.2027350e-002 6.8010000e-003
+v 2.5620340e-002 1.1880719e-001 -5.0330800e-003
+v -3.8150260e-002 4.2466610e-002 -2.6893990e-002
+v -2.8212410e-002 1.1116862e-001 -1.8001930e-002
+v -6.0253590e-002 1.4339100e-001 -3.7906300e-003
+v 1.9016880e-002 1.0401450e-001 -1.9333120e-002
+v 7.5446700e-003 9.1682150e-002 -3.1643140e-002
+v -7.0760800e-003 1.2240119e-001 -1.1364410e-002
+v -1.9047500e-002 9.6562130e-002 -2.7579900e-002
+v -1.6953390e-002 1.0669256e-001 -2.2002990e-002
+v -6.7307000e-004 1.0119875e-001 -2.2857770e-002
+v -9.0179300e-003 1.2528031e-001 -7.7912000e-003
+v -6.8136180e-002 1.8006113e-001 -5.8816050e-002
+v -2.3600190e-002 1.1513818e-001 -1.5577390e-002
+v -5.9831220e-002 4.2842260e-002 -6.6469100e-003
+v 5.3124070e-002 5.9012380e-002 -2.8853800e-003
+v -3.6931840e-002 3.7107370e-002 -2.9714170e-002
+v -5.6215140e-002 1.4139213e-001 -2.8027300e-003
+v 3.6695880e-002 1.0372844e-001 -7.9621500e-003
+v -3.5885070e-002 1.2040038e-001 -1.0640470e-002
+v -9.3569500e-003 8.5423730e-002 -3.8112540e-002
+v -6.0127340e-002 1.2041391e-001 -9.3791100e-003
+v -3.9842790e-002 1.2156113e-001 -1.1570310e-002
+v 2.8322200e-002 1.0847957e-001 -1.2623390e-002
+v -1.8733500e-003 1.1593910e-001 -1.7169430e-002
+v 3.8648150e-002 9.0153340e-002 -1.2549680e-002
+v -1.7359200e-003 9.2244170e-002 -3.4310460e-002
+v 5.0000820e-002 6.1612070e-002 -3.4649900e-003
+v 5.5858960e-002 6.2910170e-002 6.9037000e-004
+v 2.0461520e-002 1.1515372e-001 -1.3103780e-002
+v -1.5165840e-002 1.1798075e-001 -1.4465520e-002
+v -7.0859540e-002 7.1510150e-002 3.3895100e-002
+v 2.2674030e-002 8.6606050e-002 -2.4925490e-002
+v 3.5358840e-002 8.7438890e-002 -1.7109050e-002
+v 1.8400920e-002 1.2145507e-001 -7.6804200e-003
+v -2.5425900e-002 4.1421010e-002 -2.9204830e-002
+v -8.2085100e-003 9.6777440e-002 -3.0809780e-002
+v -5.6810660e-002 3.3873940e-002 -1.1166310e-002
+v -3.4588640e-002 4.4744960e-002 -2.7122900e-002
+v -4.0251680e-002 1.1827531e-001 -1.3674080e-002
+v 1.6387020e-002 1.1402346e-001 -1.5496900e-002
+v 4.2635280e-002 6.0797460e-002 -3.4583700e-003
+v -5.0687200e-002 3.5935870e-002 -1.2380790e-002
+v 7.3446800e-003 9.4509570e-002 -2.9683220e-002
+v -1.9706700e-002 9.2917340e-002 -3.4636880e-002
+v -1.2083040e-002 1.2219229e-001 -9.7120900e-003
+v 4.8805930e-002 6.8457810e-002 1.6952900e-003
+v -3.0869700e-003 9.8402500e-002 -2.7403170e-002
+v -5.3198790e-002 1.3672896e-001 -1.6580500e-003
+v -4.7290060e-002 1.3055355e-001 1.6909100e-003
+v 4.4651700e-003 1.2044039e-001 -1.3931400e-002
+v -2.3850100e-003 1.2290534e-001 -1.0382460e-002
+v -2.4833330e-002 9.5858030e-002 -2.5162110e-002
+v -4.2296900e-002 3.6291920e-002 -2.7253600e-002
+v -5.4388260e-002 1.3404922e-001 -3.9920400e-003
+v -5.0539380e-002 1.3336659e-001 -1.0872200e-003
+v 2.6040300e-003 9.6942660e-002 -2.8407060e-002
+v -7.8163100e-003 1.2821209e-001 -1.9430400e-003
+v 6.5111700e-003 1.3002517e-001 9.2881000e-004
+v 3.4742860e-002 9.2274140e-002 -1.5654590e-002
+v -6.7787700e-002 1.8088887e-001 -5.8191050e-002
+v -3.3715410e-002 1.1151566e-001 -1.8078440e-002
+v 4.4630400e-003 1.2427294e-001 -9.4291400e-003
+v -2.3370170e-002 9.3392760e-002 -3.2031820e-002
+v -4.8982070e-002 1.2980647e-001 -1.3229400e-003
+v -7.8164000e-004 1.2822918e-001 -3.2490000e-003
+v 2.4960400e-003 8.9857600e-002 -3.3628450e-002
+v 7.4553300e-003 1.1196790e-001 -1.9554260e-002
+v 2.8791140e-002 9.1157340e-002 -2.0370210e-002
+v -5.3590150e-002 1.2437450e-001 -7.3470400e-003
+v -4.7743630e-002 1.2064432e-001 -1.2812990e-002
+v -1.9616230e-002 1.2109197e-001 -9.5487700e-003
+v -6.5047370e-002 1.7999148e-001 -5.9758600e-002
+v -5.1704160e-002 3.7620360e-002 -1.1763450e-002
+v -5.2124270e-002 1.2929832e-001 -4.1187000e-003
+v -4.5334450e-002 1.2891494e-001 1.5819100e-003
+v -3.0471200e-003 1.2919453e-001 -1.0688000e-003
+v 7.2129600e-003 1.2721957e-001 -5.2073700e-003
+v 1.1669320e-002 1.2720154e-001 -3.1850900e-003
+v 5.3056400e-002 6.9708830e-002 3.1291400e-003
+v -6.3021150e-002 1.7810951e-001 -6.0393570e-002
+v 2.8204800e-002 6.4391270e-002 -2.0698040e-002
+v 3.4400180e-002 1.0503000e-001 -1.0224920e-002
+v 3.0975190e-002 1.0790250e-001 -1.1058430e-002
+v -4.8984390e-002 1.1480518e-001 -1.5966690e-002
+v -3.2821710e-002 1.2300500e-001 -5.9088300e-003
+v -5.0792860e-002 1.2716487e-001 -4.8183200e-003
+v -3.5301670e-002 1.2547815e-001 -3.1542800e-003
+v 5.6455250e-002 6.9951490e-002 4.9191700e-003
+v -1.6240450e-002 1.2512177e-001 -3.6499700e-003
+v -1.6970400e-002 1.1119793e-001 -1.9586410e-002
+v -5.4088120e-002 3.9781210e-002 -1.0544680e-002
+v -3.4190490e-002 4.7514010e-002 -2.2301500e-002
+v 1.3699090e-002 9.3914220e-002 -2.6427690e-002
+v 8.8000000e-004 9.9234930e-002 -2.4355670e-002
+v -4.6459460e-002 1.2723953e-001 -4.8843300e-003
+v -4.1735500e-002 1.2687599e-001 -4.1742000e-003
+v -2.1000480e-002 1.2313643e-001 -6.1190100e-003
+v -1.2130450e-002 1.2572568e-001 -5.2007900e-003
+v -4.3822400e-003 1.2640753e-001 -6.9495200e-003
+v 1.4085700e-003 3.4781990e-002 -2.3265200e-002
+v -1.4846200e-002 3.5070930e-002 -2.6071900e-002
+v -2.1399500e-002 3.4795120e-002 -2.7958820e-002
+v 1.2009220e-002 3.5961900e-002 -2.1735750e-002
+v 3.8249200e-003 3.6129220e-002 -2.3878090e-002
+v -5.1139560e-002 9.6617580e-002 -2.2095120e-002
+v -5.4813320e-002 9.8102480e-002 -2.1425370e-002
+v -2.7597040e-002 1.6979824e-001 -1.8170420e-002
+v 1.3359870e-002 3.9377410e-002 -2.2496330e-002
+v 4.3919300e-003 3.8674430e-002 -2.4170290e-002
+v -6.8478200e-003 3.6444540e-002 -2.5177120e-002
+v -1.3280260e-002 3.7699590e-002 -2.6391810e-002
+v -4.7672760e-002 3.6116650e-002 -1.3301210e-002
+v -4.5590120e-002 1.0853826e-001 -1.8796680e-002
+v -5.0095670e-002 1.0990925e-001 -1.8504510e-002
+v -6.5766640e-002 3.6469550e-002 -7.2073000e-003
+v -2.3455840e-002 1.6824727e-001 -1.8822880e-002
+v -4.5918000e-003 3.8404570e-002 -2.5412870e-002
+v -2.4954130e-002 3.7441060e-002 -2.9152720e-002
+v 2.9007770e-002 3.7358220e-002 -2.7474000e-004
+v -7.9468800e-003 4.1489920e-002 -2.5911270e-002
+v -1.6803800e-002 3.9753810e-002 -2.7565350e-002
+v -6.5156150e-002 1.4034537e-001 -7.6848600e-003
+v -4.7080100e-002 4.0700690e-002 -1.1869830e-002
+v -6.8470630e-002 3.7477700e-002 -4.9557400e-003
+v 3.7326850e-002 4.0209510e-002 -8.5850000e-004
+v 3.5349870e-002 4.1257050e-002 -2.8075100e-003
+v 5.1820700e-003 4.1536320e-002 -2.4065670e-002
+v 1.8660660e-002 1.0030784e-001 -2.2127290e-002
+v -6.0510780e-002 1.0748450e-001 -1.7042300e-002
+v -6.2374340e-002 4.0146090e-002 -7.4040200e-003
+v 2.5456950e-002 3.9483890e-002 -4.0251400e-003
+v -2.2828000e-004 4.3394940e-002 -2.5124420e-002
+v -8.1088400e-003 4.3439060e-002 -2.6140070e-002
+v -1.7362450e-002 4.3237420e-002 -2.7665190e-002
+v -2.6416670e-002 4.4674020e-002 -2.8209740e-002
+v 3.8064500e-003 1.0944331e-001 -2.0203790e-002
+v -5.8232370e-002 9.5690400e-002 -2.0616030e-002
+v -6.6122370e-002 4.2341260e-002 -2.7538800e-003
+v -6.0959920e-002 9.4173040e-002 -1.9015670e-002
+v 3.1352250e-002 4.2649280e-002 -4.6745000e-003
+v -3.3540900e-002 3.6342620e-002 4.9089960e-002
+v 1.7252780e-002 4.4335610e-002 -2.3067190e-002
+v 1.0637660e-002 4.4161560e-002 -2.4926170e-002
+v 4.3843100e-003 4.5806710e-002 -2.6788990e-002
+v -8.2506400e-003 4.5148720e-002 -2.8441070e-002
+v -1.5748410e-002 4.5043860e-002 -2.7877790e-002
+v 2.8990330e-002 4.4697850e-002 -6.1863000e-003
+v 8.1686400e-003 4.5053030e-002 -2.5178740e-002
+v -9.6291000e-004 4.5378230e-002 -2.7308280e-002
+v -1.7033400e-003 4.7819200e-002 -2.9928930e-002
+v -3.1535830e-002 4.4740410e-002 -2.8079410e-002
+v -3.3619650e-002 1.5691468e-001 -1.1024870e-002
+v -5.0751180e-002 4.3109620e-002 -1.0018680e-002
+v 3.6890890e-002 4.7353200e-002 -6.1057100e-003
+v 2.4975630e-002 4.2644580e-002 -7.0169900e-003
+v 2.4562420e-002 4.8369560e-002 -1.9672760e-002
+v 1.3964040e-002 4.5579170e-002 -2.4706510e-002
+v 1.3376130e-002 4.8630300e-002 -2.6551500e-002
+v 3.7308900e-003 4.8127990e-002 -2.9025970e-002
+v -8.7947000e-003 4.7056850e-002 -2.9881630e-002
+v -1.3753770e-002 5.1865060e-002 -3.2243480e-002
+v -2.1200840e-002 4.6657090e-002 -2.7951320e-002
+v 3.9693540e-002 4.5658580e-002 -4.5274100e-003
+v 3.3627400e-002 4.8717730e-002 -6.3904600e-003
+v -6.5352120e-002 9.9294570e-002 -1.6820150e-002
+v 1.2868100e-003 5.0383670e-002 -3.0357440e-002
+v -8.1797500e-003 4.9845800e-002 -3.1071390e-002
+v -1.7184350e-002 4.8210500e-002 -2.9741930e-002
+v -2.6049450e-002 4.7692500e-002 -2.6149500e-002
+v -8.4747010e-002 1.1078350e-001 3.9488380e-002
+v -5.1316870e-002 4.8270690e-002 -7.9310500e-003
+v -8.2506510e-002 1.2765487e-001 -4.6796400e-003
+v 3.8663690e-002 5.1696670e-002 -6.6910200e-003
+v -7.5643160e-002 9.9440450e-002 -1.1927610e-002
+v 2.0284470e-002 5.1349190e-002 -2.4895380e-002
+v 5.9436000e-003 5.0976660e-002 -2.9119360e-002
+v -2.5528290e-002 5.1472710e-002 -2.6884680e-002
+v -3.5562670e-002 4.9399890e-002 -1.2865040e-002
+v -4.2818980e-002 1.6220182e-001 -1.0337510e-002
+v -6.5593600e-002 1.7665711e-001 -6.0504730e-002
+v -3.4151080e-002 1.7442797e-001 -1.3312550e-002
+v 4.3673180e-002 5.0162230e-002 -5.9843500e-003
+v -5.0342410e-002 1.5546197e-001 -5.1927700e-003
+v 2.5464180e-002 5.4029700e-002 -2.1691010e-002
+v 1.0149790e-002 4.9258540e-002 -2.7750590e-002
+v -2.2043190e-002 5.3612020e-002 -3.0135610e-002
+v -3.2875520e-002 5.1677630e-002 -1.0888650e-002
+v -3.7613820e-002 4.9534770e-002 -1.1626140e-002
+v -4.0750630e-002 4.9285110e-002 -1.1286200e-002
+v -4.6385170e-002 4.7490850e-002 -1.0085980e-002
+v 4.4473170e-002 5.3293010e-002 -6.3327900e-003
+v 3.3205620e-002 5.1020650e-002 -7.2382500e-003
+v 1.5678350e-002 5.1169270e-002 -2.6397810e-002
+v 6.8341700e-003 5.5010170e-002 -3.0561130e-002
+v 2.1424700e-003 5.5502800e-002 -3.1334400e-002
+v 5.9285000e-004 5.2867950e-002 -3.0513830e-002
+v -3.6481400e-003 5.1869000e-002 -3.1457940e-002
+v -9.4245600e-003 5.5399220e-002 -3.3653980e-002
+v -1.9302150e-002 5.8224770e-002 -3.3919700e-002
+v -6.1084270e-002 1.3386190e-001 -7.2248900e-003
+v -4.3309760e-002 5.5656840e-002 -1.1402110e-002
+v -6.1080540e-002 1.6833773e-001 -5.9192060e-002
+v 4.7574690e-002 5.2943630e-002 -5.1300300e-003
+v -3.7403030e-002 1.1150775e-001 -1.8243310e-002
+v 1.9972490e-002 5.4409710e-002 -2.7108230e-002
+v 5.3974800e-003 5.8382570e-002 -3.0903760e-002
+v -1.0603590e-002 5.3602910e-002 -3.3403350e-002
+v -3.4998290e-002 5.2331560e-002 -1.0347380e-002
+v -4.6471230e-002 5.1304340e-002 -9.8299800e-003
+v -6.7945360e-002 1.1493603e-001 -9.5107300e-003
+v -7.1048210e-002 1.5161088e-001 -4.4679270e-002
+v -5.8903800e-003 3.4790620e-002 -2.4224470e-002
+v 1.6842140e-002 5.5555670e-002 -2.8284560e-002
+v 1.0711040e-002 5.4687610e-002 -2.9767520e-002
+v -1.1826800e-003 5.9492420e-002 -3.3360920e-002
+v -5.2325900e-003 5.5688960e-002 -3.2840220e-002
+v -5.1705830e-002 5.2470760e-002 -7.4047200e-003
+v -5.2626360e-002 6.0043760e-002 -8.9566900e-003
+v -7.2598590e-002 9.7762720e-002 -1.4434510e-002
+v 4.4331260e-002 5.5818010e-002 -6.0362700e-003
+v 3.8463400e-002 5.4934820e-002 -6.1822500e-003
+v 3.8838620e-002 5.7808260e-002 -5.2584800e-003
+v -9.2015400e-003 5.9510130e-002 -3.4437110e-002
+v -3.5262560e-002 5.5284900e-002 -1.0545060e-002
+v -3.8336450e-002 5.4503540e-002 -1.0905320e-002
+v -1.7727540e-002 3.6289540e-002 5.2222250e-002
+v 5.0006490e-002 5.8095800e-002 -4.6211800e-003
+v 4.6133970e-002 5.9278810e-002 -4.7769600e-003
+v 1.5110300e-002 5.9819840e-002 -2.8645750e-002
+v 1.0312380e-002 5.7586530e-002 -2.9995250e-002
+v -6.1353400e-003 6.0256790e-002 -3.4695830e-002
+v -1.2318220e-002 5.9396390e-002 -3.5268510e-002
+v -1.4466910e-002 6.3136020e-002 -3.6865870e-002
+v -4.6650260e-002 5.9840950e-002 -1.2135840e-002
+v -5.6572080e-002 1.2480275e-001 -7.1885700e-003
+v -7.9237500e-002 1.2055419e-001 -5.6744800e-003
+v -7.9334790e-002 1.2560650e-001 -6.1175900e-003
+v 2.2340000e-002 5.8492230e-002 -2.6014120e-002
+v 7.6270400e-003 6.2098330e-002 -3.1135840e-002
+v 3.3101700e-003 6.0456840e-002 -3.2481070e-002
+v -1.6811880e-002 6.1275230e-002 -3.5929330e-002
+v -3.2491910e-002 5.7196350e-002 -1.2104730e-002
+v -3.4108240e-002 6.1466560e-002 -1.3053130e-002
+v -3.3896980e-002 5.7025330e-002 -1.1047570e-002
+v -3.8623580e-002 5.8303290e-002 -1.1505750e-002
+v -4.5008400e-002 6.2723940e-002 -1.3390450e-002
+v -5.6896010e-002 1.3398739e-001 -5.6270700e-003
+v -4.4853890e-002 1.5746031e-001 -8.6731600e-003
+v -7.8609550e-002 6.9656870e-002 1.1810740e-002
+v -2.3730020e-002 1.0186156e-001 -2.3836400e-002
+v -2.8122930e-002 9.9322390e-002 -2.3580130e-002
+v -5.0076720e-002 1.4997652e-001 -3.6419700e-003
+v -3.3048420e-002 9.5958590e-002 -2.3426460e-002
+v 1.9520390e-002 6.2064770e-002 -2.7292470e-002
+v -3.8864710e-002 1.0333987e-001 -2.0641400e-002
+v -4.8952940e-002 5.6281090e-002 -1.0220880e-002
+v -5.3993040e-002 1.4498656e-001 -1.1093400e-003
+v -4.5530560e-002 9.8510850e-002 -2.1729510e-002
+v -5.0910960e-002 1.0074570e-001 -2.1619430e-002
+v 2.3245830e-002 6.2792530e-002 -2.5047990e-002
+v 9.7412800e-003 6.3181400e-002 -3.1141370e-002
+v -8.6614000e-004 6.4559630e-002 -3.4490930e-002
+v -8.5264000e-003 6.4001730e-002 -3.5850480e-002
+v -4.8451500e-002 6.4794120e-002 -1.3029910e-002
+v -5.2325160e-002 1.0614813e-001 -1.9271240e-002
+v -5.5265350e-002 1.0216682e-001 -1.9897100e-002
+v -5.9042010e-002 9.9032210e-002 -1.9222950e-002
+v -5.7846760e-002 1.0433496e-001 -1.8525740e-002
+v -2.7113460e-002 1.7332156e-001 -1.8538890e-002
+v 2.2832000e-002 6.7082570e-002 -2.6297510e-002
+v 1.4519060e-002 6.4595540e-002 -2.9855690e-002
+v 1.1471330e-002 6.7581440e-002 -3.0901170e-002
+v -1.7739360e-002 6.6260830e-002 -3.7657310e-002
+v -6.5059750e-002 1.3452104e-001 -8.0899900e-003
+v -7.5829320e-002 1.4244605e-001 -5.8090000e-003
+v -4.1362350e-002 6.1637330e-002 -1.2813770e-002
+v -5.6147890e-002 6.1921550e-002 -5.7541100e-003
+v -6.2126110e-002 6.2845360e-002 -4.5202600e-003
+v -3.7292480e-002 1.6449057e-001 -1.3627050e-002
+v -1.9818920e-002 1.6509494e-001 -1.7608980e-002
+v 6.2881100e-003 6.5416350e-002 -3.2563040e-002
+v -5.9250500e-003 6.9515630e-002 -3.5933480e-002
+v -1.0538630e-002 6.7999180e-002 -3.6517060e-002
+v -3.5385700e-002 6.6817430e-002 -1.5434860e-002
+v -5.3994500e-002 6.4638700e-002 -9.3254900e-003
+v -6.3852310e-002 6.5572310e-002 -6.9393300e-003
+v -6.3920880e-002 1.2774242e-001 -8.5494600e-003
+v -2.6940700e-002 3.6184050e-002 5.3351850e-002
+v 1.9618650e-002 6.7007390e-002 -2.8356120e-002
+v 1.2275180e-002 6.9933940e-002 -3.1553160e-002
+v 5.4265100e-003 6.8247960e-002 -3.2730520e-002
+v -4.4084200e-003 6.6619200e-002 -3.4870250e-002
+v -2.1911350e-002 6.7144790e-002 -3.6535750e-002
+v -4.5643150e-002 1.5466949e-001 -7.2969400e-003
+v -5.1673460e-002 6.6850660e-002 -1.2120350e-002
+v -5.8105180e-002 6.6465950e-002 -1.0044340e-002
+v -5.6992260e-002 1.4311862e-001 -2.2403000e-003
+v -8.0651110e-002 1.3119854e-001 -4.4397800e-003
+v -5.6544310e-002 1.2850938e-001 -6.2014700e-003
+v 1.7758080e-002 7.0138540e-002 -2.9404680e-002
+v 6.4980500e-003 7.0791870e-002 -3.3525310e-002
+v 7.5831000e-004 7.0434460e-002 -3.4462560e-002
+v -1.3235950e-002 6.9292820e-002 -3.7917490e-002
+v -6.7390780e-002 1.1889688e-001 -8.7301400e-003
+v -3.8119520e-002 6.4162310e-002 -1.3829140e-002
+v 1.8527400e-003 1.1303356e-001 -1.9794270e-002
+v -7.5950810e-002 6.8170610e-002 1.8117970e-002
+v -1.0001990e-002 7.2671480e-002 -3.7661370e-002
+v -1.7976070e-002 7.0613770e-002 -3.8443880e-002
+v -2.3035990e-002 7.2778460e-002 -3.8072640e-002
+v -2.6120100e-002 7.1177480e-002 -3.5451530e-002
+v -6.8535420e-002 1.3929375e-001 -7.8046600e-003
+v -3.5263040e-002 7.1067650e-002 -1.8011860e-002
+v -4.1558180e-002 6.9774010e-002 -1.6774100e-002
+v -5.2831730e-002 7.0298920e-002 -1.4864960e-002
+v -6.6978850e-002 6.7638980e-002 -6.8094400e-003
+v -1.0244470e-002 1.7895826e-001 -2.9538870e-002
+v -7.5272650e-002 1.2680098e-001 -8.0241700e-003
+v -8.7359900e-002 1.1248315e-001 4.2049490e-002
+v 8.7503000e-003 7.4301560e-002 -3.3398210e-002
+v -6.4249520e-002 1.6045024e-001 -5.7041470e-002
+v -4.4354010e-002 7.3372220e-002 -1.7874430e-002
+v -4.5762580e-002 6.9445320e-002 -1.5928780e-002
+v -4.7957440e-002 7.2542990e-002 -1.6106990e-002
+v -5.7822630e-002 6.9538010e-002 -1.4416470e-002
+v -7.2071600e-002 7.1538150e-002 -7.4714400e-003
+v 2.5472930e-002 7.4094500e-002 -2.4938540e-002
+v 1.5719730e-002 7.3756350e-002 -2.9747770e-002
+v 4.8214000e-003 7.3763980e-002 -3.4552450e-002
+v -2.2528600e-003 7.3921320e-002 -3.5887190e-002
+v -7.3834900e-003 7.4799620e-002 -3.7223830e-002
+v -2.0225340e-002 7.7095190e-002 -3.9044290e-002
+v -3.4016180e-002 7.2101270e-002 -2.0823150e-002
+v -3.8493370e-002 7.2839870e-002 -1.7502230e-002
+v -6.4392550e-002 7.3116330e-002 -1.5335340e-002
+v -6.4480660e-002 7.0187350e-002 -1.2261750e-002
+v -2.3854330e-002 1.6164528e-001 -1.4504190e-002
+v 2.2104450e-002 7.2692600e-002 -2.6900140e-002
+v 1.5532370e-002 7.6586960e-002 -2.9606940e-002
+v 1.1574050e-002 7.4860570e-002 -3.1383860e-002
+v -1.4731560e-002 7.7640750e-002 -3.8490670e-002
+v -1.6018820e-002 7.4288800e-002 -3.8864420e-002
+v -5.1103620e-002 7.3071950e-002 -1.6243060e-002
+v -5.7989540e-002 7.4017880e-002 -1.7522320e-002
+v -6.9608380e-002 7.2322890e-002 -1.0934430e-002
+v -7.5996110e-002 1.1714132e-001 -6.5577200e-003
+v -3.7987660e-002 1.0751453e-001 -1.9975760e-002
+v 1.0696210e-002 7.9889200e-002 -3.2009580e-002
+v -5.3433400e-003 7.8264580e-002 -3.7476940e-002
+v -2.6081990e-002 7.6191290e-002 -3.6780200e-002
+v -3.9161040e-002 1.5718885e-001 -1.0580510e-002
+v -6.5609880e-002 7.5860010e-002 -1.6750060e-002
+v -7.0177600e-002 7.5663330e-002 -1.3839210e-002
+v -7.4291360e-002 7.4808360e-002 -9.3537900e-003
+v -6.3428890e-002 1.7185387e-001 -6.1412170e-002
+v 3.0684890e-002 7.5726870e-002 -2.0778090e-002
+v 1.9305010e-002 7.9017870e-002 -2.7743990e-002
+v -8.5992100e-003 7.9338730e-002 -3.7905180e-002
+v -2.3200110e-002 7.6568500e-002 -3.8386500e-002
+v -3.8117820e-002 7.6390120e-002 -1.8644360e-002
+v -4.4231130e-002 7.7664130e-002 -1.9026580e-002
+v -5.1025500e-002 7.5705070e-002 -1.8186900e-002
+v -7.0595130e-002 1.2994832e-001 -8.7629200e-003
+v 2.8147660e-002 7.8785370e-002 -2.2432450e-002
+v 7.6016000e-003 7.9435920e-002 -3.3714560e-002
+v 4.9502400e-003 7.8027250e-002 -3.4409750e-002
+v -1.5858350e-002 8.1165550e-002 -3.9185590e-002
+v -1.8502080e-002 8.3343870e-002 -3.9010720e-002
+v -7.9739350e-002 1.3606854e-001 -4.1482100e-003
+v -3.0980180e-002 1.6634656e-001 -1.6241160e-002
+v -3.5749800e-002 7.7248350e-002 -1.9374020e-002
+v -4.8944740e-002 7.9086360e-002 -1.9575700e-002
+v -5.5065860e-002 7.8089190e-002 -1.9755480e-002
+v 2.3706000e-002 8.0240410e-002 -2.5450120e-002
+v 1.2254110e-002 8.3456700e-002 -3.0771580e-002
+v 1.8549900e-003 8.4692790e-002 -3.4838500e-002
+v -2.0857000e-004 7.8941410e-002 -3.5782080e-002
+v -4.2710000e-004 8.2947370e-002 -3.6380660e-002
+v -4.4101600e-003 8.2794510e-002 -3.7467250e-002
+v -3.3202320e-002 1.0578320e-001 -2.0647590e-002
+v -3.9206970e-002 8.1536380e-002 -2.0571000e-002
+v -6.0355410e-002 7.9766610e-002 -1.9375540e-002
+v -4.1771830e-002 1.0396706e-001 -2.0832940e-002
+v -1.1204010e-002 8.2713320e-002 -3.8489610e-002
+v -2.3181500e-002 8.1686990e-002 -3.8329160e-002
+v -2.7233190e-002 8.0570950e-002 -3.6620670e-002
+v -3.5470180e-002 8.0196070e-002 -2.2325910e-002
+v -4.4864210e-002 8.1997900e-002 -2.0473520e-002
+v -5.0647890e-002 8.2309430e-002 -2.1365890e-002
+v -5.5522610e-002 8.1927600e-002 -2.1353790e-002
+v -8.8089610e-002 1.1135484e-001 1.8516150e-002
+v -7.2036080e-002 1.1107918e-001 4.5361400e-002
+v -3.3359780e-002 1.6986395e-001 -1.5448990e-002
+v -6.6839030e-002 6.2170510e-002 2.1576840e-002
+v 3.0730560e-002 8.1968990e-002 -2.0040460e-002
+v 1.6224320e-002 8.6480380e-002 -2.8952010e-002
+v -6.9855630e-002 1.0027892e-001 -1.4847830e-002
+v -6.3836170e-002 8.1704600e-002 -1.8908860e-002
+v -6.7914820e-002 8.0136290e-002 -1.7128200e-002
+v -4.5752080e-002 1.6340754e-001 -8.1780500e-003
+v 1.1727540e-002 8.8010780e-002 -3.0860110e-002
+v 7.3334800e-003 8.5270000e-002 -3.2829380e-002
+v -3.4356500e-003 8.7017890e-002 -3.6461000e-002
+v -2.6964110e-002 8.4512810e-002 -3.6361740e-002
+v -3.6553370e-002 8.5316190e-002 -2.2576200e-002
+v -3.8791090e-002 8.5232710e-002 -2.1917600e-002
+v -5.7676940e-002 8.6258340e-002 -2.1098320e-002
+v -6.2581810e-002 8.6394530e-002 -1.9169290e-002
+v -7.1395340e-002 1.2468846e-001 -8.5944200e-003
+v 1.4801570e-002 9.9040900e-002 -2.2842920e-002
+v -2.1162860e-002 1.7491852e-001 -2.1977110e-002
+v -1.4824250e-002 8.7288840e-002 -3.8317070e-002
+v -2.3285750e-002 8.9468030e-002 -3.6027250e-002
+v -5.1595650e-002 8.4422070e-002 -2.1600960e-002
+v -6.9481040e-002 8.5656460e-002 -1.7198420e-002
+v -7.0917210e-002 1.0754846e-001 -1.1496630e-002
+v 3.0145320e-002 8.6284000e-002 -2.0408140e-002
+v -5.5578110e-002 1.1567692e-001 -1.4645990e-002
+v -8.0981100e-003 8.9070080e-002 -3.6552200e-002
+v -8.1206310e-002 1.1205088e-001 -8.8299000e-004
+v -1.8772170e-002 8.9838040e-002 -3.6991710e-002
+v -2.1100420e-002 8.6587670e-002 -3.7849050e-002
+v -2.5809910e-002 8.8889590e-002 -3.5082250e-002
+v -4.8984800e-002 9.0731760e-002 -2.1817170e-002
+v -3.5874870e-002 3.4776000e-002 -3.0845200e-002
+v -3.3164390e-002 3.3606540e-002 -2.9721880e-002
+v -2.5964020e-002 3.3487000e-002 -2.6321120e-002
+v -1.6717530e-002 3.3611640e-002 -2.4625420e-002
+v -5.3486300e-003 3.3829010e-002 -2.2600430e-002
+v 6.4843500e-003 3.4293000e-002 -2.0854930e-002
+v 1.3950350e-002 3.4880000e-002 -1.8612870e-002
+v -4.2465980e-002 3.4189100e-002 -2.7260650e-002
+v -3.3241100e-002 3.3578760e-002 -2.6719450e-002
+v 6.2813500e-003 3.4165800e-002 -1.8764230e-002
+v -4.4265790e-002 3.3663660e-002 -2.1914420e-002
+v -2.3671460e-002 3.3630970e-002 -2.3217760e-002
+v -1.1558580e-002 3.3895430e-002 -2.1054260e-002
+v -2.0406400e-003 3.4053940e-002 -1.9331070e-002
+v 1.7323900e-003 3.4459660e-002 -1.6607870e-002
+v -2.7316070e-002 3.3910070e-002 -2.1353750e-002
+v -1.3371080e-002 3.4361580e-002 -1.9023720e-002
+v 9.5887300e-003 3.4207220e-002 -1.5424050e-002
+v -1.4981540e-002 3.5878180e-002 -1.7992380e-002
+v -2.3474300e-003 3.5903130e-002 -1.5929740e-002
+v 2.2544300e-003 3.6411540e-002 -1.4783970e-002
+v -3.5199130e-002 3.3835210e-002 -2.0508290e-002
+v -2.6075450e-002 3.5918600e-002 -1.9405170e-002
+v 8.2740600e-003 3.5645200e-002 -1.2648700e-002
+v 1.0473640e-002 3.4742600e-002 -1.1262870e-002
+v 1.4055380e-002 3.4483430e-002 -1.4495730e-002
+v -3.6970520e-002 3.5680360e-002 -1.5007790e-002
+v -2.4719500e-003 3.8408770e-002 -1.4159030e-002
+v -3.9481890e-002 3.3618220e-002 -2.3612470e-002
+v -4.1091510e-002 3.4006000e-002 -1.1997540e-002
+v -3.1589810e-002 3.5592330e-002 -1.9204150e-002
+v -2.0086310e-002 3.8064450e-002 -1.7220790e-002
+v -1.1113250e-002 3.8290290e-002 -1.5646360e-002
+v 4.4522600e-003 3.7705190e-002 -1.2957650e-002
+v 1.5870480e-002 3.4416230e-002 -2.9666500e-003
+v -4.7872000e-002 3.4136300e-002 -1.5418250e-002
+v -4.7521640e-002 3.3622720e-002 -1.2804590e-002
+v -3.3407340e-002 3.7577040e-002 -1.6158190e-002
+v -2.7851470e-002 3.8404330e-002 -1.7210420e-002
+v -8.5065300e-003 3.9028950e-002 -1.3000800e-002
+v 6.4552500e-003 3.8165190e-002 -1.0164860e-002
+v 7.4147100e-003 3.4659190e-002 -3.0116800e-003
+v 1.1966200e-002 3.4335400e-002 -5.9571300e-003
+v 2.0414820e-002 3.5567580e-002 -3.7806900e-003
+v -1.9288780e-002 3.8762570e-002 -1.4202620e-002
+v -1.1390100e-003 3.9176760e-002 -1.0381370e-002
+v 3.8149200e-003 3.9024470e-002 -8.0827300e-003
+v 7.5208200e-003 3.6733400e-002 -6.7614300e-003
+v 1.9968120e-002 3.4843990e-002 -1.8984900e-003
+v -4.5058400e-002 3.3600490e-002 -1.2527510e-002
+v -3.0754850e-002 3.8639810e-002 -1.4050770e-002
+v -5.1499810e-002 3.3729110e-002 -1.2082510e-002
+v -2.3756860e-002 3.8585750e-002 -1.1093270e-002
+v 3.9734700e-003 3.8208550e-002 -3.7963500e-003
+v 9.5485400e-003 3.4232620e-002 1.7162000e-003
+v 2.9086550e-002 3.5799990e-002 3.5630900e-003
+v -5.5965200e-002 3.3529910e-002 -9.1246200e-003
+v -1.9523510e-002 3.8505210e-002 -4.5434500e-003
+v 1.6363470e-002 3.4394790e-002 2.2948600e-003
+v 2.1324740e-002 3.4624040e-002 5.6444000e-003
+v -3.9670300e-002 3.6174000e-002 -7.3397700e-003
+v -1.4251730e-002 3.8648030e-002 -4.3030400e-003
+v 2.3262300e-003 3.5348200e-002 2.3246000e-003
+v 1.4014300e-002 3.5703800e-002 3.8878900e-003
+v 1.5322800e-002 3.6239700e-002 3.6628500e-003
+v 2.3753130e-002 3.4670710e-002 3.9885300e-003
+v 3.2369180e-002 3.5816010e-002 7.0246300e-003
+v -6.3715900e-002 3.3776930e-002 -8.0065600e-003
+v -6.4266880e-002 3.3562500e-002 -5.1253200e-003
+v -3.8066600e-002 3.8518600e-002 -7.3079600e-003
+v -9.4308800e-003 3.8887690e-002 -7.4848700e-003
+v 3.9677800e-003 3.4200210e-002 4.9754500e-003
+v 9.4292600e-003 3.6030400e-002 4.5275100e-003
+v 2.9859020e-002 3.4980130e-002 9.8349300e-003
+v -5.2730060e-002 3.3497900e-002 -1.8117500e-003
+v -4.1271000e-002 3.3855400e-002 -1.8800800e-003
+v -3.1105000e-003 3.8946190e-002 -2.7793900e-003
+v 6.2194100e-003 3.5134100e-002 6.5492800e-003
+v 2.0897900e-002 3.5937100e-002 8.7849000e-003
+v 3.5606010e-002 3.6526640e-002 9.8155300e-003
+v -6.7078340e-002 3.3840100e-002 -6.1688300e-003
+v -8.1140000e-004 3.7424170e-002 4.7721500e-003
+v 3.1492300e-003 3.4125310e-002 1.1762220e-002
+v 4.9172000e-003 3.3997100e-002 9.1666100e-003
+v 2.5130800e-002 3.4546910e-002 1.1012580e-002
+v 2.8248620e-002 3.5046370e-002 1.6016700e-002
+v -6.7032970e-002 6.5145960e-002 2.7292860e-002
+v -4.6380170e-002 3.3605230e-002 -8.9435000e-004
+v -3.3163400e-002 3.8195400e-002 -5.2520000e-004
+v -3.2074200e-002 3.8323400e-002 -4.2109000e-004
+v -2.1692690e-002 3.8266010e-002 4.5100800e-003
+v 2.3930750e-002 3.4816710e-002 1.7739160e-002
+v 4.2719120e-002 3.9977070e-002 8.9321600e-003
+v -5.8604080e-002 3.3462230e-002 -2.1667000e-004
+v -3.7314400e-002 3.3633000e-002 4.5724700e-003
+v -1.0423990e-002 3.8488570e-002 6.2292700e-003
+v -1.3896900e-003 3.8651360e-002 2.3966500e-003
+v -3.0845000e-004 3.5462480e-002 8.2607200e-003
+v -1.4089000e-003 3.6193080e-002 1.2944550e-002
+v 2.2252900e-002 3.6583300e-002 1.3979700e-002
+v -7.0961830e-002 3.4345730e-002 -7.8374000e-004
+v -6.9066180e-002 3.3717630e-002 -1.9761000e-004
+v -6.4825640e-002 3.3505860e-002 2.8222500e-003
+v -4.7059660e-002 3.3501860e-002 3.5646400e-003
+v -3.6953800e-003 3.8172780e-002 1.3046800e-002
+v 3.3475850e-002 3.6447340e-002 1.6266960e-002
+v 3.7249610e-002 3.7509920e-002 1.4815820e-002
+v -4.5675940e-002 3.3703640e-002 6.4300300e-003
+v -3.8639270e-002 3.3937310e-002 8.5506500e-003
+v -9.5064100e-003 3.8352640e-002 1.5570660e-002
+v 2.1499800e-002 3.5807100e-002 1.8169400e-002
+v 4.4876460e-002 4.1230990e-002 1.6008250e-002
+v -7.2474010e-002 3.6255930e-002 1.5532600e-003
+v -7.1498130e-002 3.4452970e-002 4.2026500e-003
+v -2.7790900e-002 3.8062900e-002 7.9376100e-003
+v -1.6556410e-002 3.8286470e-002 1.0215790e-002
+v 8.1043500e-003 3.4842900e-002 1.8134600e-002
+v 2.3589460e-002 3.5890600e-002 2.5337690e-002
+v 4.1261350e-002 4.0585070e-002 2.0751930e-002
+v -5.1350870e-002 3.3645700e-002 8.0329400e-003
+v -4.7104300e-002 3.5549500e-002 8.0803900e-003
+v -1.4103500e-003 3.6999940e-002 1.6982030e-002
+v 9.1714000e-004 3.4803380e-002 1.5634690e-002
+v 2.8887900e-003 3.4636250e-002 1.8849770e-002
+v 1.3279200e-002 3.4379500e-002 2.1423700e-002
+v 1.4322700e-002 3.4425500e-002 2.1593200e-002
+v 1.7490100e-002 3.4646300e-002 2.2040900e-002
+v 2.9868460e-002 3.6248820e-002 1.9872200e-002
+v -3.9222000e-002 3.6326200e-002 1.0789900e-002
+v -3.0307100e-002 3.3995400e-002 1.4706400e-002
+v 2.0081230e-002 3.5172700e-002 2.8018770e-002
+v 2.4989010e-002 3.8104580e-002 2.9429570e-002
+v 3.3584130e-002 3.8303930e-002 2.2928670e-002
+v 4.9015720e-002 4.4573630e-002 2.0659450e-002
+v -5.8225970e-002 6.6607310e-002 3.5050280e-002
+v -6.7330830e-002 3.3846440e-002 8.7266300e-003
+v -3.4692330e-002 3.3828710e-002 1.2438580e-002
+v -2.9803200e-002 3.4287000e-002 1.6353100e-002
+v 1.7023800e-003 3.6310890e-002 2.1179600e-002
+v 4.5137020e-002 4.4625440e-002 2.5516510e-002
+v -6.8876490e-002 1.1022176e-001 3.9004630e-002
+v -5.7680560e-002 3.3622690e-002 1.4040310e-002
+v -5.3210500e-002 3.3585300e-002 1.3987000e-002
+v -3.5711600e-002 3.5891600e-002 1.5502900e-002
+v -2.8861500e-002 3.5396700e-002 1.7350000e-002
+v -2.6580500e-002 3.7742600e-002 1.5705300e-002
+v -1.0974400e-003 3.8147840e-002 2.0427010e-002
+v 3.5047710e-002 4.0973940e-002 2.6970390e-002
+v -6.9685460e-002 3.4478780e-002 9.7984300e-003
+v -5.4019000e-002 3.3309900e-002 1.5848000e-002
+v 4.4816800e-003 3.7117830e-002 2.4755300e-002
+v 6.6605500e-003 3.5204730e-002 2.4315930e-002
+v 8.3833000e-003 3.4748700e-002 2.4057310e-002
+v 3.8883100e-002 4.1032980e-002 2.4976570e-002
+v -2.6441900e-003 3.8727070e-002 2.5131260e-002
+v 3.2222300e-003 3.8708440e-002 2.5898750e-002
+v 9.0016500e-003 3.6890930e-002 2.8482190e-002
+v 1.3196980e-002 3.4835790e-002 3.1630980e-002
+v 2.2291600e-002 3.7053310e-002 3.3101020e-002
+v 2.8948390e-002 3.9160020e-002 2.7234810e-002
+v -8.7773470e-002 1.1181412e-001 3.7144310e-002
+v -1.7870490e-002 3.8203890e-002 2.0243220e-002
+v 1.0087420e-002 3.7047690e-002 3.0822500e-002
+v 4.2296550e-002 4.5435770e-002 2.9040920e-002
+v -8.4341340e-002 1.1388013e-001 4.6513480e-002
+v -7.3795710e-002 1.0895629e-001 3.9217250e-002
+v -5.1243340e-002 6.4239200e-002 3.4258040e-002
+v -6.1777390e-002 3.4017860e-002 1.6900580e-002
+v -3.6665100e-002 3.5304200e-002 2.3032000e-002
+v -1.4930180e-002 3.8643510e-002 2.9378330e-002
+v -8.0894520e-002 1.0967225e-001 3.7910230e-002
+v -8.9822620e-002 1.1387199e-001 3.2845310e-002
+v -6.9655510e-002 6.8728370e-002 3.1127880e-002
+v -7.8449800e-002 1.0988832e-001 4.2517920e-002
+v -7.5824140e-002 1.0794900e-001 3.7128750e-002
+v -5.5740630e-002 3.4128050e-002 2.6674360e-002
+v -3.8279600e-002 3.5429000e-002 2.4380600e-002
+v -3.5283340e-002 3.4179780e-002 2.2744860e-002
+v -2.5798070e-002 3.7865000e-002 1.9981460e-002
+v 6.9064300e-003 3.9004270e-002 2.9548510e-002
+v 1.5448990e-002 3.4852440e-002 3.6984890e-002
+v 1.9128230e-002 3.5640640e-002 3.6642280e-002
+v -6.3664970e-002 6.6047840e-002 3.1828080e-002
+v 3.9604800e-002 4.4939530e-002 2.9992360e-002
+v -8.0294310e-002 7.1702430e-002 1.5995300e-002
+v -5.4185430e-002 6.7322700e-002 3.6935610e-002
+v -7.3110210e-002 1.4847168e-001 -2.8748470e-002
+v -5.8999980e-002 7.3751550e-002 4.1197080e-002
+v -5.9520730e-002 6.1040260e-002 -2.3753800e-003
+v -6.2791800e-002 3.4596760e-002 2.3505640e-002
+v -4.1895500e-002 3.3668300e-002 2.6940000e-002
+v 8.9808200e-003 3.7639400e-002 3.3900800e-002
+v 8.5287800e-003 3.4888000e-002 3.6265100e-002
+v -8.9803890e-002 1.1498106e-001 4.2771650e-002
+v -6.5545420e-002 7.4430370e-002 3.9168070e-002
+v -6.4644190e-002 6.1723230e-002 2.2552000e-004
+v 5.2496900e-003 3.9507100e-002 3.3271200e-002
+v 2.0250320e-002 3.7033170e-002 3.9327190e-002
+v -6.7006400e-002 6.3292870e-002 -1.7493900e-003
+v -6.4479770e-002 6.0651470e-002 4.2343200e-003
+v -5.7219630e-002 5.7000470e-002 4.9175800e-003
+v -7.4362810e-002 7.2437050e-002 3.1430040e-002
+v -6.2019000e-002 3.4343180e-002 3.1883280e-002
+v -4.6870820e-002 3.4444130e-002 3.0513130e-002
+v -2.0814280e-002 3.8400960e-002 2.7868430e-002
+v 1.6439350e-002 3.5635110e-002 4.1281040e-002
+v -6.9087160e-002 1.1205014e-001 4.5320060e-002
+v -7.1811570e-002 1.4861318e-001 -3.4639490e-002
+v -6.9538770e-002 6.3074750e-002 3.5758200e-003
+v -8.4863890e-002 7.8392100e-002 1.6462010e-002
+v -9.1188780e-002 1.1588893e-001 2.4705540e-002
+v -8.8827760e-002 1.1359169e-001 2.3873640e-002
+v -7.1302830e-002 1.1325363e-001 4.9444530e-002
+v -5.4876950e-002 7.0282330e-002 3.8828200e-002
+v -7.7208880e-002 1.0715887e-001 3.4738290e-002
+v -6.1241780e-002 5.9007440e-002 8.0916600e-003
+v -6.5885650e-002 3.5025080e-002 2.9416520e-002
+v -5.7889430e-002 3.4419570e-002 3.6265760e-002
+v -5.1847710e-002 3.4470270e-002 3.4635180e-002
+v -3.4834600e-002 3.4721400e-002 3.4578200e-002
+v -3.0984700e-002 3.8191900e-002 3.2390100e-002
+v -4.9613100e-003 3.9364900e-002 3.6702200e-002
+v 1.2224170e-002 3.5177480e-002 4.2620580e-002
+v -7.4898220e-002 1.1458863e-001 5.0776480e-002
+v -8.0469100e-002 1.1357963e-001 4.6643440e-002
+v -7.4107560e-002 6.9586030e-002 2.7264400e-002
+v -7.9002620e-002 7.6339320e-002 2.9248090e-002
+v -6.5297080e-002 3.4778970e-002 3.3744340e-002
+v -3.3656400e-002 3.4344100e-002 3.6914100e-002
+v 4.9318500e-003 3.4814800e-002 4.3462110e-002
+v 1.1347440e-002 3.6213020e-002 4.4652280e-002
+v -6.0569260e-002 7.1154540e-002 3.8653760e-002
+v -8.8979470e-002 1.1450869e-001 2.8446030e-002
+v -6.8543520e-002 6.1090480e-002 1.0557760e-002
+v -8.2710960e-002 1.1648975e-001 4.8518530e-002
+v -4.1913210e-002 3.4467720e-002 3.3200040e-002
+v -1.1289800e-002 3.9529200e-002 3.8844100e-002
+v -2.8261900e-003 3.4885340e-002 4.5611410e-002
+v -6.4561210e-002 5.9484140e-002 1.3061680e-002
+v -5.8581440e-002 5.7801460e-002 1.3429540e-002
+v -2.3320000e-002 3.9169500e-002 3.8473300e-002
+v -1.8159900e-002 3.9322300e-002 3.9402900e-002
+v -1.6471400e-002 3.4812800e-002 4.3684700e-002
+v 3.2906600e-003 3.5833470e-002 4.6024610e-002
+v -8.5229630e-002 1.1200712e-001 3.0416940e-002
+v -8.5644730e-002 1.1131719e-001 3.4234780e-002
+v -7.4530360e-002 6.6680690e-002 4.6953300e-003
+v -7.1112970e-002 6.2751470e-002 8.7995500e-003
+v -6.1149380e-002 5.8834410e-002 1.6539440e-002
+v -4.6912270e-002 3.4627180e-002 3.9739710e-002
+v -4.0760350e-002 3.4668230e-002 4.0492530e-002
+v -2.6323100e-002 3.4658000e-002 4.3473500e-002
+v -3.1836600e-003 3.6229910e-002 4.7873100e-002
+v -7.9940490e-002 1.0916678e-001 3.4119800e-002
+v -5.9712170e-002 6.3165280e-002 2.8789180e-002
+v -5.1176600e-002 6.8061880e-002 3.7398330e-002
+v -5.0126580e-002 7.0933150e-002 3.9481010e-002
+v -7.2790130e-002 6.4399880e-002 1.5205950e-002
+v -6.8511230e-002 6.1214650e-002 1.5354080e-002
+v -3.9343210e-002 3.5440180e-002 4.2492560e-002
+v -8.1305900e-003 3.5008350e-002 4.7502400e-002
+v -6.6080670e-002 7.0202740e-002 3.5552860e-002
+v -6.8602600e-002 1.4992277e-001 -4.0051350e-002
+v -7.1722100e-002 6.7023040e-002 2.4959750e-002
+v -7.5115010e-002 6.6557040e-002 1.0244090e-002
+v -6.5146650e-002 3.5945650e-002 3.9775080e-002
+v -3.6898600e-002 3.5924640e-002 4.4794170e-002
+v -9.4780400e-003 3.5977600e-002 4.9434210e-002
+v -8.5175960e-002 1.1706809e-001 4.8139420e-002
+v -6.3366400e-002 6.2790260e-002 2.5647610e-002
+v -6.6633330e-002 6.1001700e-002 1.8101240e-002
+v -5.8167590e-002 5.9985190e-002 2.2606060e-002
+v -6.4212210e-002 3.4992560e-002 3.9401920e-002
+v -5.3425790e-002 3.4560020e-002 4.2782420e-002
+v -1.8031490e-002 3.4859970e-002 4.9264760e-002
+v -1.1440410e-002 3.7640770e-002 5.0275730e-002
+v -7.5165320e-002 1.1154286e-001 4.6707180e-002
+v -7.7168390e-002 6.9826450e-002 5.0605600e-003
+v -7.2801360e-002 6.4382590e-002 1.2089080e-002
+v -7.8022000e-002 7.0995160e-002 2.1322150e-002
+v -6.1263370e-002 3.4690410e-002 4.1994900e-002
+v -5.4403750e-002 3.5007310e-002 4.4874590e-002
+v -4.5754280e-002 3.5206980e-002 4.3518120e-002
+v -3.3832440e-002 3.5168820e-002 4.6957890e-002
+v -2.8657630e-002 3.5083380e-002 5.0549440e-002
+v -1.5306440e-002 3.5246410e-002 5.0133810e-002
+v -6.5283650e-002 1.5592447e-001 -4.9865930e-002
+v -6.6467860e-002 1.4871539e-001 -3.1579300e-002
+v -6.2095980e-002 1.6388324e-001 -5.8385930e-002
+v -6.3274890e-002 1.5245731e-001 -3.2221730e-002
+v -4.3755720e-002 1.4773408e-001 -2.1433200e-003
+v -6.5696940e-002 1.4561631e-001 -1.8974710e-002
+v -6.6713650e-002 1.5358824e-001 -4.9097100e-002
+v -1.0482810e-002 1.6668287e-001 -2.1746090e-002
+v -6.2744510e-002 1.6397531e-001 -5.9398280e-002
+v -7.0413230e-002 1.4129200e-001 -8.4590800e-003
+v -6.1530380e-002 1.4037628e-001 -6.2734700e-003
+v -1.1452460e-002 1.7220633e-001 -2.6844980e-002
+v -6.3731140e-002 1.6577037e-001 -6.0103610e-002
+v -2.8218820e-002 1.5758144e-001 -1.0999490e-002
+v -1.8471270e-002 1.5967716e-001 -1.1169510e-002
+v -6.6700710e-002 1.5236775e-001 -4.5266390e-002
+v -4.9896410e-002 1.4670859e-001 -1.8614200e-003
+v -3.1449640e-002 1.5460463e-001 -7.6802300e-003
+v -6.7447660e-002 1.5507675e-001 -5.1594250e-002
+v -1.0906650e-002 1.7649301e-001 -2.9246300e-002
+v -7.2083600e-002 1.4965550e-001 -3.9265860e-002
+v -6.4230830e-002 1.4877806e-001 -2.5899710e-002
+v -6.3056640e-002 1.4341650e-001 -7.4907700e-003
+v -5.3043350e-002 1.4092550e-001 -4.7408000e-004
+v -3.9269410e-002 1.5205232e-001 -6.6203800e-003
+v -6.4796930e-002 1.5210615e-001 -3.6185520e-002
+v -6.4400320e-002 1.5834400e-001 -5.4256370e-002
+v -6.6178120e-002 1.4218350e-001 -9.3766300e-003
+v -6.7751430e-002 1.4605207e-001 -2.3333300e-002
+v -6.4731580e-002 1.5410067e-001 -4.0464820e-002
+v -2.4265590e-002 1.5687690e-001 -7.8509300e-003
+v -1.5723180e-002 1.6312344e-001 -1.6396570e-002
+v -7.0887660e-002 1.4404618e-001 -1.4908480e-002
+v -4.4341830e-002 1.5113809e-001 -5.6859800e-003
+v -6.2896810e-002 1.4694778e-001 -1.3098620e-002
+v -6.3755400e-002 1.4428875e-001 -1.1395730e-002
+v -6.8214560e-002 1.4390932e-001 -1.4984170e-002
+v -5.0271440e-002 1.4336563e-001 1.5153000e-003
+v -2.8535590e-002 1.6208479e-001 -1.4786030e-002
+v -6.5810700e-002 1.4359119e-001 -1.2585380e-002
+v -5.6179200e-002 1.3774406e-001 -4.0674300e-003
+v -6.8866880e-002 1.4723338e-001 -2.8739870e-002
+v -6.0965420e-002 1.7002113e-001 -6.0839390e-002
+v -1.3895490e-002 1.6787168e-001 -2.1897230e-002
+v -6.9413000e-002 1.5121847e-001 -4.4538540e-002
+v -5.5039800e-002 5.7309700e-002 1.6990900e-002
+f 1069 1647 1578
+f 1058 909 939
+f 421 1176 238
+f 1055 1101 1042
+f 238 1059 1126
+f 1254 30 1261
+f 1065 1071 1
+f 1037 1130 1120
+f 1570 2381 1585
+f 2434 2502 2473
+f 1632 1654 1646
+f 1144 1166 669
+f 1202 1440 305
+f 1071 1090 1
+f 1555 1570 1584
+f 1184 1174 404
+f 65 432 12
+f 1032 1085 574
+f 1789 2207 2223
+f 1154 1118 1184
+f 1141 1086 1154
+f 99 1117 342
+f 404 1174 419
+f 489 2000 1998
+f 1118 1174 1184
+f 1196 403 136
+f 1495 717 1490
+f 1804 402 1207
+f 2272 1398 891
+f 1100 1002 804
+f 1596 1595 2381
+f 208 420 1207
+f 402 208 1207
+f 1455 1935 1925
+f 1176 1059 238
+f 1150 1040 348
+f 1957 1537 2051
+f 1124 1189 939
+f 1804 1207 1823
+f 1381 1300 1109
+f 383 384 1182
+f 1085 1086 1141
+f 1040 1046 132
+f 220 1495 1188
+f 420 261 1207
+f 261 420 1065
+f 1055 1133 1101
+f 1054 421 403
+f 182 1109 2
+f 1181 1207 320
+f 545 1570 1561
+f 35 342 432
+f 1024 574 1141
+f 432 342 12
+f 1489 1081 1547
+f 1181 320 1805
+f 1516 1683 1507
+f 357 1117 1047
+f 1561 1570 1555
+f 1090 1196 1206
+f 1047 1203 1051
+f 1165 202 1121
+f 1099 341 301
+f 1174 240 419
+f 922 921 833
+f 1121 1080 385
+f 815 21 1183
+f 35 99 342
+f 1083 398 262
+f 106 94 1317
+f 94 292 1317
+f 292 95 1317
+f 940 1039 1033
+f 1300 1306 433
+f 21 212 471
+f 1120 1131 1037
+f 833 921 688
+f 1117 357 342
+f 106 271 94
+f 386 227 1375
+f 1130 1044 1053
+f 419 240 219
+f 1255 1244 32
+f 1557 1081 1489
+f 2062 2120 2109
+f 2034 2110 430
+f 23 315 1111
+f 291 94 271
+f 291 292 94
+f 50 386 95
+f 964 734 665
+f 1616 1585 1611
+f 445 1084 402
+f 574 1085 1141
+f 1654 341 1653
+f 220 1188 1640
+f 342 69 12
+f 417 261 328
+f 292 50 95
+f 204 227 386
+f 50 204 386
+f 1276 1471 1311
+f 1206 1196 136
+f 1033 1055 1042
+f 1037 1044 1130
+f 1180 320 417
+f 1121 202 1080
+f 325 203 271
+f 291 76 292
+f 292 237 50
+f 2159 1696 1767
+f 583 929 850
+f 1584 1585 1616
+f 1495 1490 1188
+f 1557 1489 1660
+f 1078 1069 1494
+f 1972 1992 1971
+f 183 1226 2000
+f 325 429 203
+f 292 76 237
+f 1152 227 1143
+f 1488 1412 1489
+f 1638 1646 1653
+f 1947 1869 2468
+f 203 306 291
+f 306 76 291
+f 237 248 50
+f 204 1143 227
+f 2395 14 429
+f 1502 881 2500
+f 1 1090 202
+f 1652 1653 1099
+f 2117 1863 2496
+f 50 248 204
+f 160 792 994
+f 884 888 857
+f 544 2117 2496
+f 1090 1206 202
+f 2463 879 2492
+f 429 306 203
+f 498 188 418
+f 865 884 857
+f 994 998 1014
+f 884 897 888
+f 1795 948 1802
+f 208 1035 1071
+f 1065 1 1066
+f 377 435 1377
+f 304 429 14
+f 304 306 429
+f 73 60 74
+f 248 592 204
+f 846 2264 829
+f 897 912 906
+f 1004 991 992
+f 1422 1421 1233
+f 980 10 303
+f 1058 922 909
+f 2436 2449 2418
+f 394 435 377
+f 435 475 446
+f 475 474 446
+f 336 337 361
+f 338 235 372
+f 624 148 129
+f 812 306 596
+f 1726 992 1019
+f 945 1514 1511
+f 1069 1627 1628
+f 1812 1823 1181
+f 1165 1121 169
+f 447 475 435
+f 2487 2458 901
+f 42 59 46
+f 401 7 187
+f 1010 970 797
+f 1513 220 1640
+f 2474 2491 2462
+f 594 307 1014
+f 398 1513 1640
+f 307 594 1026
+f 545 2381 1570
+f 403 421 238
+f 445 402 127
+f 1611 1631 1616
+f 1805 1180 1148
+f 394 447 435
+f 2341 2413 2376
+f 75 74 60
+f 541 47 42
+f 47 59 42
+f 541 42 28
+f 917 931 1103
+f 897 906 883
+f 2484 2068 779
+f 888 883 857
+f 261 1065 328
+f 363 1307 349
+f 377 363 394
+f 444 747 464
+f 323 338 362
+f 92 116 74
+f 592 634 97
+f 982 1027 1004
+f 1020 982 1004
+f 1084 1054 1035
+f 208 402 1084
+f 421 1119 1176
+f 1207 1181 1823
+f 1179 1187 1160
+f 263 296 1343
+f 1298 296 1307
+f 1307 296 349
+f 405 363 349
+f 405 394 363
+f 405 447 394
+f 362 372 384
+f 338 372 362
+f 983 1004 987
+f 122 134 139
+f 415 440 414
+f 75 92 74
+f 226 186 246
+f 796 787 700
+f 1119 1059 1176
+f 122 114 91
+f 624 129 116
+f 641 558 631
+f 1311 1318 1487
+f 100 1162 1170
+f 1653 341 1099
+f 1316 1983 273
+f 263 277 296
+f 296 358 349
+f 436 447 405
+f 109 554 570
+f 504 1385 2501
+f 115 122 91
+f 2068 2460 779
+f 43 777 163
+f 378 405 349
+f 358 378 349
+f 448 447 436
+f 448 476 447
+f 78 77 108
+f 75 60 47
+f 1764 2481 1795
+f 717 714 1512
+f 1490 717 1501
+f 238 1126 168
+f 1878 1866 826
+f 2025 2360 2367
+f 251 278 263
+f 278 277 263
+f 277 318 296
+f 296 318 358
+f 318 350 358
+f 378 436 405
+f 384 372 1182
+f 454 440 415
+f 987 1004 992
+f 493 476 448
+f 323 788 338
+f 403 238 136
+f 1565 1503 1474
+f 297 277 278
+f 297 318 277
+f 358 350 378
+f 378 388 436
+f 476 493 500
+f 73 105 60
+f 323 337 312
+f 953 1573 2358
+f 142 161 119
+f 454 443 440
+f 1862 1871 1405
+f 297 319 318
+f 560 47 541
+f 170 1323 111
+f 357 1047 1050
+f 1119 98 1059
+f 1838 1877 1900
+f 2359 230 251
+f 350 364 378
+f 449 448 436
+f 449 493 448
+f 185 186 226
+f 443 469 479
+f 874 165 2480
+f 463 444 464
+f 64 105 91
+f 1182 440 1129
+f 1958 1651 2502
+f 1238 2034 191
+f 251 279 278
+f 278 279 297
+f 364 388 378
+f 483 493 449
+f 134 148 139
+f 244 268 259
+f 910 942 930
+f 105 115 91
+f 24 30 18
+f 1132 487 1059
+f 1869 1947 2021
+f 2497 2494 2463
+f 2359 2385 230
+f 230 280 251
+f 251 280 279
+f 279 308 297
+f 297 308 319
+f 319 364 318
+f 364 350 318
+f 388 395 436
+f 436 395 449
+f 493 472 500
+f 122 129 134
+f 125 142 124
+f 373 400 393
+f 24 557 30
+f 2264 2278 2251
+f 1261 30 1269
+f 1730 1862 1877
+f 252 280 230
+f 343 364 319
+f 364 343 388
+f 63 64 91
+f 399 393 416
+f 416 444 463
+f 162 189 142
+f 768 373 326
+f 189 661 177
+f 189 199 661
+f 847 887 864
+f 533 747 444
+f 1744 1022 1418
+f 1170 524 729
+f 121 1342 128
+f 1236 1244 26
+f 280 281 279
+f 281 308 279
+f 343 319 308
+f 343 365 388
+f 388 365 395
+f 365 406 395
+f 406 449 395
+f 483 477 493
+f 477 491 472
+f 493 477 472
+f 78 109 77
+f 166 174 196
+f 481 150 814
+f 63 59 64
+f 326 373 393
+f 643 260 43
+f 230 253 252
+f 449 441 483
+f 441 477 483
+f 415 416 463
+f 226 246 245
+f 464 470 454
+f 323 362 337
+f 52 37 1283
+f 253 281 252
+f 281 280 252
+f 309 308 281
+f 330 343 308
+f 366 365 343
+f 441 449 406
+f 464 814 15
+f 883 906 887
+f 337 362 371
+f 479 498 290
+f 247 746 1003
+f 25 37 557
+f 640 930 669
+f 2486 2499 2459
+f 309 330 308
+f 343 330 366
+f 441 437 477
+f 290 498 418
+f 124 119 108
+f 77 124 108
+f 589 125 109
+f 570 589 109
+f 125 162 142
+f 1045 433 1034
+f 1207 261 320
+f 2004 2474 2495
+f 1215 1228 2285
+f 365 396 406
+f 396 422 406
+f 422 437 441
+f 406 422 441
+f 59 47 60
+f 51 78 66
+f 361 371 383
+f 196 215 214
+f 463 454 415
+f 27 41 535
+f 53 1283 37
+f 84 1299 1283
+f 1805 320 1180
+f 254 253 222
+f 254 281 253
+f 309 366 330
+f 396 365 366
+f 456 477 437
+f 484 491 477
+f 2480 2485 2493
+f 418 188 187
+f 53 85 1283
+f 85 84 1283
+f 420 1071 1065
+f 264 281 254
+f 298 309 281
+f 368 366 367
+f 368 396 366
+f 1639 1564 1139
+f 560 48 47
+f 82 471 212
+f 25 38 37
+f 202 1206 1080
+f 264 298 281
+f 298 331 309
+f 309 331 366
+f 331 367 366
+f 396 368 422
+f 422 456 437
+f 491 1192 313
+f 1699 2064 1710
+f 462 443 479
+f 371 362 384
+f 2502 2476 2464
+f 371 384 383
+f 21 732 212
+f 1571 1629 1627
+f 38 39 53
+f 37 38 53
+f 39 85 53
+f 1173 1184 404
+f 1006 2142 1674
+f 201 255 254
+f 255 264 254
+f 368 407 422
+f 450 456 422
+f 450 484 456
+f 456 484 477
+f 314 1192 491
+f 2027 2501 2489
+f 2475 2471 2488
+f 551 492 732
+f 464 481 814
+f 1081 1494 1547
+f 201 231 255
+f 407 450 422
+f 484 494 491
+f 494 327 491
+f 327 314 491
+f 876 797 995
+f 847 856 829
+f 125 143 162
+f 134 129 148
+f 1564 1571 1627
+f 417 320 261
+f 328 1065 1066
+f 170 156 201
+f 156 231 201
+f 231 282 255
+f 282 264 255
+f 450 485 484
+f 484 485 494
+f 2463 2486 2479
+f 159 185 167
+f 492 68 212
+f 732 492 212
+f 68 82 212
+f 1311 1471 1296
+f 101 156 111
+f 332 264 282
+f 332 298 264
+f 332 331 298
+f 331 332 367
+f 407 423 450
+f 450 423 485
+f 804 1002 1443
+f 2484 779 946
+f 689 443 462
+f 440 689 1129
+f 166 167 174
+f 38 31 39
+f 112 145 101
+f 101 145 156
+f 156 256 231
+f 332 423 368
+f 367 332 368
+f 368 423 407
+f 946 779 920
+f 1432 1261 1449
+f 461 478 453
+f 464 15 470
+f 31 54 39
+f 39 54 85
+f 86 101 85
+f 145 210 156
+f 282 283 332
+f 283 369 332
+f 369 423 332
+f 423 408 485
+f 854 876 965
+f 78 108 66
+f 440 443 689
+f 374 2465 961
+f 929 519 979
+f 54 86 85
+f 156 241 256
+f 256 282 231
+f 256 283 282
+f 389 423 369
+f 389 408 423
+f 408 457 485
+f 457 49 485
+f 485 49 494
+f 494 135 327
+f 175 83 314
+f 1167 1140 1483
+f 196 174 215
+f 697 16 68
+f 1038 82 16
+f 140 117 141
+f 1654 1653 1646
+f 1234 54 31
+f 86 112 101
+f 210 241 156
+f 923 917 911
+f 697 34 16
+f 145 193 210
+f 256 265 283
+f 265 310 283
+f 283 310 369
+f 310 344 369
+f 344 370 369
+f 370 389 369
+f 409 408 389
+f 409 466 408
+f 466 457 408
+f 466 49 457
+f 49 135 494
+f 174 225 215
+f 1014 766 602
+f 826 2220 2215
+f 1078 1494 1081
+f 1273 70 86
+f 120 112 86
+f 146 145 112
+f 146 193 145
+f 265 256 241
+f 223 265 241
+f 486 49 466
+f 175 327 135
+f 105 122 115
+f 480 15 681
+f 225 234 215
+f 731 34 697
+f 86 54 1273
+f 70 120 86
+f 193 241 210
+f 299 310 265
+f 310 333 344
+f 344 351 370
+f 424 466 409
+f 135 49 175
+f 214 215 234
+f 48 75 47
+f 34 9 1038
+f 16 34 1038
+f 203 291 271
+f 9 558 754
+f 1195 397 1120
+f 120 146 112
+f 146 194 193
+f 266 265 223
+f 266 299 265
+f 299 333 310
+f 333 351 344
+f 382 383 392
+f 399 416 415
+f 266 333 299
+f 351 352 370
+f 424 486 466
+f 487 175 49
+f 7 117 187
+f 1182 414 440
+f 41 42 46
+f 290 289 497
+f 2502 2464 2473
+f 372 399 414
+f 1570 1585 1584
+f 1066 1 1165
+f 1 202 1165
+f 120 70 102
+f 157 146 120
+f 194 223 193
+f 223 241 193
+f 352 379 370
+f 370 379 389
+f 410 409 389
+f 2478 1409 1958
+f 806 945 1002
+f 157 194 146
+f 267 266 223
+f 267 333 266
+f 379 410 389
+f 410 438 409
+f 438 424 409
+f 190 205 143
+f 337 371 361
+f 2215 830 826
+f 1631 1646 1638
+f 102 157 120
+f 157 195 194
+f 195 223 194
+f 195 211 223
+f 223 211 267
+f 267 300 333
+f 300 334 351
+f 333 300 351
+f 351 334 352
+f 410 411 438
+f 438 486 424
+f 487 49 486
+f 875 594 989
+f 108 581 66
+f 225 245 244
+f 312 336 335
+f 151 754 107
+f 274 1386 300
+f 352 334 379
+f 923 1729 1096
+f 244 245 268
+f 463 464 454
+f 414 399 415
+f 15 480 470
+f 1647 1069 1078
+f 909 922 833
+f 387 417 328
+f 133 157 102
+f 1314 133 102
+f 133 195 157
+f 1148 1179 1160
+f 1046 1167 182
+f 379 411 410
+f 792 339 229
+f 391 7 668
+f 185 226 174
+f 461 290 497
+f 2027 504 2501
+f 1196 1054 403
+f 728 1019 752
+f 2459 2483 2461
+f 1291 1264 55
+f 133 1356 195
+f 195 1356 211
+f 412 438 411
+f 4 486 438
+f 458 4 438
+f 4 487 486
+f 1720 1572 1771
+f 245 275 268
+f 1869 2021 2059
+f 235 399 372
+f 64 60 105
+f 836 2492 879
+f 1315 133 1314
+f 1331 1382 1356
+f 1310 926 1128
+f 7 1121 117
+f 119 161 611
+f 380 379 334
+f 379 380 411
+f 467 4 458
+f 495 487 4
+f 495 1126 487
+f 416 400 533
+f 479 469 498
+f 74 116 73
+f 478 461 497
+f 393 400 416
+f 61 1291 55
+f 505 1999 2474
+f 1999 2491 2474
+f 199 189 36
+f 1164 1165 169
+f 1179 387 249
+f 390 411 380
+f 411 390 412
+f 458 438 412
+f 495 168 1126
+f 480 469 470
+f 116 122 105
+f 418 187 140
+f 185 174 167
+f 166 148 167
+f 470 469 443
+f 40 55 32
+f 61 71 1291
+f 71 103 1291
+f 1184 1173 1154
+f 634 514 97
+f 425 458 412
+f 917 923 931
+f 2472 2489 853
+f 754 641 567
+f 44 567 1163
+f 454 470 443
+f 40 32 1249
+f 33 40 1249
+f 56 55 40
+f 56 61 55
+f 451 1265 439
+f 1180 417 1179
+f 1099 301 1077
+f 1189 1058 939
+f 1059 221 1132
+f 598 1074 1075
+f 412 426 425
+f 650 186 185
+f 234 244 259
+f 226 245 225
+f 1033 1042 1030
+f 2492 836 247
+f 7 169 1121
+f 1462 1322 1482
+f 425 467 458
+f 496 4 467
+f 1751 2468 2480
+f 290 418 140
+f 326 789 762
+f 142 177 161
+f 165 1751 2480
+f 87 103 71
+f 103 87 104
+f 1180 1179 1148
+f 417 387 1179
+f 2081 2060 2031
+f 1154 1173 1141
+f 181 131 197
+f 442 425 426
+f 614 144 143
+f 876 1010 797
+f 40 45 56
+f 56 45 61
+f 87 71 61
+f 1563 1437 1590
+f 1121 385 117
+f 1148 1160 1137
+f 1449 1459 1439
+f 1028 2462 929
+f 442 459 425
+f 459 467 425
+f 168 495 4
+f 496 168 4
+f 1763 1403 1444
+f 140 187 117
+f 244 234 225
+f 246 740 269
+f 372 414 1182
+f 40 547 45
+f 45 62 61
+f 62 87 61
+f 87 88 104
+f 1084 517 1054
+f 387 328 1064
+f 2467 2497 2485
+f 286 1363 302
+f 205 189 162
+f 290 140 289
+f 214 234 224
+f 393 399 809
+f 315 1131 397
+f 302 321 353
+f 1164 169 391
+f 427 459 442
+f 217 496 467
+f 217 168 496
+f 978 969 2074
+f 361 383 382
+f 269 276 245
+f 1440 11 305
+f 62 88 87
+f 328 1066 1064
+f 1066 1165 1164
+f 242 287 302
+f 1363 242 302
+f 287 321 302
+f 1179 249 1187
+f 983 1020 1004
+f 464 747 481
+f 788 323 276
+f 269 245 246
+f 88 89 1325
+f 171 172 242
+f 360 353 321
+f 360 1354 353
+f 1057 1064 1164
+f 2184 2188 2183
+f 460 459 451
+f 460 467 459
+f 149 168 217
+f 149 136 168
+f 116 129 122
+f 109 124 77
+f 159 167 148
+f 28 42 41
+f 57 88 62
+f 45 57 62
+f 1336 1325 89
+f 89 72 1336
+f 147 172 171
+f 172 258 242
+f 258 257 242
+f 257 287 242
+f 257 321 287
+f 345 360 321
+f 360 381 1354
+f 1069 938 1655
+f 387 473 249
+f 270 217 467
+f 130 136 149
+f 851 847 829
+f 983 987 975
+f 189 177 142
+f 88 72 89
+f 184 258 172
+f 257 288 321
+f 1265 451 459
+f 270 149 217
+f 226 225 174
+f 27 28 41
+f 109 125 124
+f 547 57 45
+f 57 58 88
+f 88 58 72
+f 2476 2484 2458
+f 147 184 172
+f 184 213 258
+f 258 243 257
+f 243 288 257
+f 345 321 288
+f 391 169 7
+f 468 460 451
+f 468 488 460
+f 270 467 460
+f 488 270 460
+f 1206 136 130
+f 481 793 150
+f 143 205 162
+f 142 119 124
+f 58 90 72
+f 90 128 72
+f 147 173 184
+f 173 213 184
+f 213 233 258
+f 258 233 243
+f 354 360 345
+f 354 381 360
+f 1026 991 307
+f 268 312 259
+f 1206 130 1080
+f 116 105 73
+f 139 148 166
+f 275 312 268
+f 188 401 187
+f 2479 2459 2461
+f 58 63 90
+f 1064 1066 1164
+f 1064 473 387
+f 288 311 345
+f 311 354 345
+f 996 994 307
+f 452 468 439
+f 452 478 468
+f 478 488 468
+f 141 130 149
+f 1564 1639 1563
+f 547 41 57
+f 2081 2107 2060
+f 382 381 354
+f 497 270 488
+f 289 149 270
+f 289 141 149
+f 114 122 139
+f 59 60 64
+f 275 323 312
+f 401 668 7
+f 41 46 57
+f 57 46 58
+f 1459 1345 1269
+f 1342 121 158
+f 166 173 158
+f 213 224 233
+f 233 259 243
+f 243 322 288
+f 322 311 288
+f 453 478 452
+f 497 289 270
+f 912 911 906
+f 276 323 275
+f 276 275 245
+f 46 63 58
+f 90 121 128
+f 173 214 213
+f 213 214 224
+f 259 322 243
+f 336 311 322
+f 336 354 311
+f 361 382 354
+f 1043 439 1290
+f 497 488 478
+f 385 130 141
+f 385 1080 130
+f 144 190 143
+f 535 41 547
+f 121 166 158
+f 335 336 322
+f 354 336 361
+f 2004 2481 1764
+f 698 439 1043
+f 289 140 141
+f 923 1096 931
+f 650 185 159
+f 46 59 63
+f 63 91 90
+f 90 114 121
+f 121 139 166
+f 173 196 214
+f 259 335 322
+f 2478 2502 2434
+f 312 337 336
+f 90 91 114
+f 114 139 121
+f 166 196 173
+f 224 234 233
+f 234 259 233
+f 259 312 335
+f 1124 916 1189
+f 542 541 530
+f 462 479 290
+f 269 783 276
+f 813 567 641
+f 276 783 788
+f 82 1038 1333
+f 816 701 703
+f 672 137 603
+f 625 635 624
+f 2457 2439 1973
+f 767 533 529
+f 2468 1869 2480
+f 662 190 639
+f 711 720 719
+f 630 639 614
+f 161 654 638
+f 781 991 982
+f 1227 31 516
+f 648 639 630
+f 630 614 590
+f 2098 544 1899
+f 578 579 586
+f 697 492 551
+f 529 533 400
+f 869 859 870
+f 1732 924 914
+f 1004 1027 991
+f 801 591 603
+f 636 676 651
+f 876 949 965
+f 2207 1789 1859
+f 76 739 237
+f 188 681 15
+f 578 604 599
+f 797 616 995
+f 510 2035 1365
+f 76 812 617
+f 617 739 76
+f 1468 93 1765
+f 596 546 812
+f 1457 1305 1477
+f 760 197 150
+f 671 773 765
+f 586 609 604
+f 591 700 632
+f 476 2312 474
+f 2084 2027 2489
+f 582 590 571
+f 1555 2449 1996
+f 674 546 596
+f 812 655 617
+f 161 177 661
+f 599 604 636
+f 700 787 576
+f 776 675 572
+f 776 674 675
+f 617 634 739
+f 591 632 649
+f 612 546 674
+f 617 655 634
+f 728 752 706
+f 571 2311 2305
+f 775 674 776
+f 775 612 674
+f 612 628 546
+f 546 628 812
+f 812 628 655
+f 620 630 615
+f 620 648 630
+f 667 653 646
+f 810 782 785
+f 150 197 814
+f 534 1517 2000
+f 702 572 2378
+f 748 776 572
+f 655 613 634
+f 911 917 905
+f 648 679 662
+f 727 771 713
+f 750 807 799
+f 639 190 144
+f 662 679 200
+f 702 748 572
+f 775 776 748
+f 628 718 655
+f 626 658 645
+f 791 778 790
+f 612 811 628
+f 613 514 634
+f 1380 1756 1673
+f 570 590 614
+f 720 741 719
+f 1074 795 835
+f 614 639 144
+f 612 775 811
+f 718 735 655
+f 655 735 613
+f 798 338 788
+f 636 652 676
+f 571 590 555
+f 528 730 687
+f 690 702 2312
+f 476 690 2312
+f 811 718 628
+f 721 778 727
+f 748 702 690
+f 735 686 613
+f 1517 2002 2127
+f 654 685 667
+f 569 588 606
+f 513 531 538
+f 538 549 548
+f 549 553 548
+f 550 588 549
+f 1903 869 870
+f 691 775 748
+f 691 600 775
+f 600 811 775
+f 811 563 718
+f 563 736 718
+f 718 736 735
+f 736 647 735
+f 735 647 686
+f 686 745 613
+f 745 514 613
+f 569 606 605
+f 654 667 638
+f 851 857 847
+f 588 569 549
+f 690 691 748
+f 680 514 745
+f 2127 2002 2094
+f 747 701 481
+f 400 373 529
+f 600 536 811
+f 536 563 811
+f 1306 227 1152
+f 522 24 18
+f 523 24 522
+f 865 857 851
+f 2031 2060 1540
+f 767 701 747
+f 618 652 609
+f 652 636 609
+f 573 22 710
+f 642 699 730
+f 1522 1518 2476
+f 500 629 691
+f 690 500 691
+f 691 629 600
+f 780 644 641
+f 579 578 561
+f 131 668 197
+f 197 668 814
+f 789 809 798
+f 622 760 150
+f 621 563 536
+f 673 745 686
+f 673 818 745
+f 818 680 745
+f 680 96 514
+f 2495 2462 1028
+f 1028 583 575
+f 663 794 664
+f 629 761 600
+f 761 757 600
+f 600 757 536
+f 621 696 563
+f 755 736 563
+f 696 755 563
+f 633 736 755
+f 633 647 736
+f 623 686 647
+f 633 623 647
+f 686 623 673
+f 819 680 818
+f 680 819 96
+f 1729 1677 1096
+f 2482 1899 2471
+f 537 536 757
+f 536 537 621
+f 673 819 818
+f 2428 222 230
+f 25 24 523
+f 25 557 24
+f 38 25 19
+f 710 22 272
+f 663 759 794
+f 1120 878 1195
+f 537 696 621
+f 696 633 755
+f 822 2215 2220
+f 97 96 1053
+f 750 784 743
+f 887 905 864
+f 768 784 373
+f 512 513 548
+f 573 664 22
+f 696 715 633
+f 673 521 819
+f 2454 2453 2445
+f 883 887 847
+f 306 812 76
+f 642 528 759
+f 798 809 235
+f 994 792 998
+f 587 626 586
+f 1900 1918 1937
+f 645 652 618
+f 537 786 696
+f 521 593 819
+f 515 19 523
+f 741 749 719
+f 789 326 809
+f 539 581 550
+f 657 777 723
+f 684 713 660
+f 692 712 720
+f 652 666 692
+f 507 761 629
+f 472 507 629
+f 507 757 761
+f 623 633 673
+f 724 521 673
+f 515 516 19
+f 304 675 674
+f 178 778 721
+f 947 1447 2358
+f 626 645 618
+f 586 626 618
+f 784 768 742
+f 753 537 757
+f 537 753 786
+f 724 981 521
+f 521 981 593
+f 979 559 850
+f 637 660 677
+f 787 631 576
+f 141 117 385
+f 809 399 235
+f 641 754 558
+f 542 553 561
+f 742 768 762
+f 444 416 533
+f 528 687 796
+f 813 598 566
+f 1490 1501 1557
+f 753 757 507
+f 786 715 696
+f 633 724 673
+f 2090 2062 2109
+f 646 653 660
+f 660 694 683
+f 677 660 683
+f 1872 839 838
+f 1224 18 30
+f 326 393 809
+f 799 529 373
+f 313 507 472
+f 715 774 633
+f 974 699 841
+f 703 820 816
+f 692 711 676
+f 1014 355 766
+f 875 752 1019
+f 627 646 660
+f 711 692 720
+f 652 692 676
+f 799 373 784
+f 813 566 567
+f 2462 2482 2475
+f 764 644 780
+f 1479 1924 1916
+f 753 738 786
+f 738 607 786
+f 786 607 715
+f 715 524 774
+f 633 774 724
+f 559 979 672
+f 758 798 783
+f 683 694 705
+f 820 703 562
+f 764 687 644
+f 744 743 725
+f 313 753 507
+f 607 524 715
+f 664 801 22
+f 646 627 610
+f 800 820 562
+f 750 769 807
+f 767 747 533
+f 578 586 604
+f 862 593 981
+f 688 2382 1083
+f 306 304 674
+f 738 584 607
+f 168 136 238
+f 773 552 765
+f 2473 2464 2458
+f 773 793 552
+f 626 619 658
+f 1007 1139 1013
+f 562 529 799
+f 744 750 743
+f 659 683 693
+f 677 683 659
+f 313 737 753
+f 753 737 738
+f 607 729 524
+f 27 518 28
+f 553 569 580
+f 657 163 777
+f 580 569 605
+f 789 798 758
+f 769 562 807
+f 820 671 816
+f 638 646 611
+f 1074 598 644
+f 750 799 784
+f 1931 907 898
+f 2483 2487 2461
+f 737 584 738
+f 1439 1438 1431
+f 2098 1213 544
+f 48 578 75
+f 796 631 787
+f 815 732 21
+f 581 588 550
+f 625 636 651
+f 778 1011 810
+f 693 705 725
+f 693 683 705
+f 236 1921 1966
+f 584 729 607
+f 2237 1866 2227
+f 530 541 28
+f 237 739 248
+f 512 530 28
+f 727 778 771
+f 684 727 713
+f 2237 2220 826
+f 542 561 560
+f 528 796 700
+f 808 785 671
+f 739 592 248
+f 895 905 896
+f 740 246 186
+f 272 137 979
+f 770 769 744
+f 712 742 720
+f 1213 2026 544
+f 1888 1235 2438
+f 555 554 2311
+f 737 313 1192
+f 1585 1612 1611
+f 695 721 685
+f 518 17 28
+f 769 770 562
+f 719 749 740
+f 648 669 679
+f 773 657 723
+f 606 637 619
+f 2072 2062 2042
+f 606 619 626
+f 549 569 553
+f 161 638 611
+f 910 917 942
+f 917 1103 942
+f 991 1026 992
+f 979 137 672
+f 785 163 657
+f 710 2488 2472
+f 611 581 119
+f 808 671 820
+f 1820 1900 1870
+f 759 700 591
+f 637 677 619
+f 2494 2490 2463
+f 671 765 816
+f 687 764 780
+f 1019 992 1026
+f 1726 1719 987
+f 713 771 694
+f 51 2355 78
+f 510 526 525
+f 525 526 1249
+f 526 33 1249
+f 2311 554 2335
+f 827 848 840
+f 603 591 649
+f 758 269 740
+f 1595 1612 1586
+f 1694 1048 1699
+f 682 740 186
+f 22 801 603
+f 555 570 554
+f 1053 110 97
+f 615 582 601
+f 814 668 188
+f 725 705 744
+f 528 700 759
+f 640 648 620
+f 703 701 562
+f 886 892 582
+f 631 731 576
+f 1087 1835 1747
+f 882 864 895
+f 956 950 1103
+f 1502 2500 2470
+f 205 190 200
+f 815 878 616
+f 616 878 995
+f 1183 878 815
+f 1601 1827 881
+f 527 535 526
+f 2184 2183 2175
+f 1142 1125 1133
+f 235 338 798
+f 160 339 792
+f 599 92 75
+f 598 1116 566
+f 631 558 731
+f 771 770 744
+f 730 528 642
+f 841 699 642
+f 668 401 188
+f 510 527 526
+f 749 758 740
+f 706 721 695
+f 694 726 705
+f 694 744 726
+f 906 911 905
+f 661 695 161
+f 708 815 616
+f 535 547 33
+f 794 759 591
+f 778 808 790
+f 269 758 783
+f 771 744 694
+f 800 808 820
+f 571 886 582
+f 854 948 1010
+f 906 905 887
+f 625 651 635
+f 2000 1226 534
+f 2140 1504 2016
+f 601 620 615
+f 620 601 640
+f 648 640 669
+f 698 452 439
+f 671 785 657
+f 1561 2356 545
+f 685 653 667
+f 685 727 684
+f 568 616 797
+f 708 732 815
+f 93 229 339
+f 865 851 839
+f 942 1103 950
+f 589 614 125
+f 606 610 627
+f 951 834 873
+f 92 599 625
+f 1878 830 1902
+f 2482 2098 1899
+f 568 708 616
+f 708 551 732
+f 2434 2487 2483
+f 160 964 665
+f 2316 2391 2309
+f 762 758 749
+f 570 614 589
+f 888 897 883
+f 2000 1517 1388
+f 685 721 727
+f 588 610 606
+f 653 685 684
+f 651 650 635
+f 760 1151 6
+f 793 622 150
+f 651 676 650
+f 744 769 750
+f 541 542 560
+f 476 500 690
+f 473 1064 1057
+f 561 578 560
+f 636 625 599
+f 876 995 949
+f 829 856 846
+f 682 704 740
+f 791 790 770
+f 2466 2500 2460
+f 579 587 586
+f 1352 1208 1095
+f 1684 1479 1916
+f 604 609 636
+f 751 721 706
+f 810 608 782
+f 672 603 649
+f 475 447 476
+f 794 591 801
+f 682 186 650
+f 808 800 790
+f 644 598 813
+f 704 719 740
+f 1011 608 810
+f 1192 584 737
+f 687 780 796
+f 2337 474 2312
+f 638 667 646
+f 706 1186 728
+f 733 575 568
+f 595 551 708
+f 595 540 551
+f 1308 501 1852
+f 665 339 160
+f 527 2447 535
+f 558 9 731
+f 723 793 773
+f 660 713 694
+f 693 725 666
+f 562 767 529
+f 550 538 531
+f 2267 2287 2233
+f 996 964 160
+f 2068 2470 2466
+f 704 711 719
+f 741 762 749
+f 605 606 626
+f 548 542 530
+f 995 878 709
+f 1898 1684 1916
+f 778 791 771
+f 782 163 785
+f 789 758 762
+f 857 883 847
+f 733 970 1028
+f 838 829 825
+f 2447 511 535
+f 22 603 137
+f 705 726 744
+f 605 587 580
+f 512 548 530
+f 743 784 742
+f 790 800 770
+f 778 810 808
+f 1014 998 355
+f 708 568 595
+f 656 697 551
+f 540 656 551
+f 143 125 614
+f 1000 1020 983
+f 778 178 1011
+f 676 704 682
+f 637 627 660
+f 606 627 637
+f 701 552 481
+f 808 810 785
+f 590 570 555
+f 716 595 568
+f 2355 2335 554
+f 912 1729 911
+f 1076 1456 1546
+f 697 68 492
+f 676 711 704
+f 839 851 838
+f 1028 575 733
+f 1020 844 982
+f 716 568 575
+f 844 781 982
+f 1238 2156 2034
+f 553 580 561
+f 580 579 561
+f 452 461 453
+f 560 578 48
+f 564 540 595
+f 632 656 540
+f 564 632 540
+f 75 578 599
+f 518 27 535
+f 511 518 535
+f 783 798 788
+f 642 759 663
+f 720 742 741
+f 605 626 587
+f 580 587 579
+f 725 712 666
+f 562 701 767
+f 1729 923 911
+f 712 743 742
+f 619 677 658
+f 161 695 654
+f 770 800 562
+f 2084 2489 2472
+f 575 559 716
+f 716 564 595
+f 654 695 685
+f 843 855 2064
+f 34 731 9
+f 527 510 1973
+f 723 622 793
+f 992 1726 987
+f 693 666 652
+f 2472 853 573
+f 624 159 148
+f 671 657 773
+f 681 188 498
+f 797 970 733
+f 565 656 632
+f 565 697 656
+f 565 731 697
+f 1949 951 920
+f 85 111 84
+f 662 200 190
+f 44 324 754
+f 33 547 40
+f 658 693 652
+f 658 652 645
+f 664 794 801
+f 666 712 692
+f 639 648 662
+f 611 646 610
+f 850 559 575
+f 1447 2490 1106
+f 1972 1955 1935
+f 582 615 590
+f 66 581 539
+f 780 641 631
+f 796 780 631
+f 1049 1192 83
+f 1348 13 1519
+f 799 807 562
+f 581 611 588
+f 687 795 644
+f 663 8 642
+f 1936 1972 1935
+f 650 676 682
+f 615 630 590
+f 730 795 687
+f 742 762 741
+f 548 553 542
+f 1048 1692 1074
+f 658 659 693
+f 37 52 30
+f 611 610 588
+f 649 632 564
+f 565 576 731
+f 2138 922 1058
+f 1204 854 965
+f 725 743 712
+f 644 813 641
+f 660 653 684
+f 771 791 770
+f 644 795 1074
+f 469 480 681
+f 559 672 564
+f 716 559 564
+f 672 649 564
+f 2161 1378 2171
+f 474 475 476
+f 816 765 701
+f 765 552 701
+f 513 538 548
+f 754 324 107
+f 609 586 618
+f 25 523 19
+f 677 659 658
+f 689 452 698
+f 1334 1115 1353
+f 700 565 632
+f 700 576 565
+f 481 552 793
+f 763 901 2458
+f 550 549 538
+f 781 964 996
+f 1596 1634 1595
+f 198 916 1124
+f 198 1124 341
+f 842 973 1025
+f 842 1025 836
+f 1009 1024 934
+f 573 710 2472
+f 1100 971 1002
+f 1501 1081 1557
+f 1225 1219 955
+f 413 2138 284
+f 955 1630 522
+f 341 1124 301
+f 2333 2376 2350
+f 1107 218 284
+f 398 925 1513
+f 1513 1442 1495
+f 1935 1455 1744
+f 1723 1935 1744
+f 825 1872 838
+f 1495 1442 1496
+f 963 1024 1009
+f 1511 1514 966
+f 1775 1729 912
+f 688 262 1067
+f 714 1007 1512
+f 919 1732 914
+f 2319 2331 2304
+f 2400 2407 2391
+f 1674 2164 1780
+f 843 927 899
+f 1660 988 1188
+f 1067 262 1640
+f 1381 1109 1483
+f 1437 1381 1483
+f 2495 1010 948
+f 1514 1289 1313
+f 899 374 961
+f 1438 1430 1422
+f 1634 1095 1632
+f 2487 973 2461
+f 1003 499 874
+f 849 848 827
+f 1430 1462 1453
+f 2496 2084 2471
+f 909 10 980
+f 730 927 835
+f 2031 1540 1536
+f 831 849 2178
+f 881 834 951
+f 1841 1722 1803
+f 1005 670 1020
+f 1021 670 1005
+f 1869 2059 2467
+f 903 902 1939
+f 2476 2502 1651
+f 853 8 573
+f 1850 831 2178
+f 934 746 247
+f 934 65 746
+f 301 285 1077
+f 968 944 977
+f 970 2495 1028
+f 974 2465 374
+f 899 927 374
+f 1882 1898 1916
+f 1613 1634 1596
+f 909 833 1396
+f 2492 247 1003
+f 919 914 1931
+f 1459 1299 1458
+f 1634 1632 1633
+f 844 670 228
+f 2494 2497 2467
+f 901 973 2487
+f 228 1772 734
+f 1701 1709 1666
+f 963 574 1024
+f 847 864 856
+f 1730 1736 2239
+f 870 859 848
+f 2074 2111 2103
+f 1140 1590 1483
+f 927 730 974
+f 2103 978 2074
+f 756 1745 1718
+f 848 859 840
+f 1296 1482 1320
+f 2331 51 66
+f 1067 988 962
+f 1396 833 1445
+f 1001 1005 1000
+f 901 1009 973
+f 1099 1077 817
+f 933 944 936
+f 952 958 1828
+f 988 1660 986
+f 833 1067 1445
+f 1067 1640 988
+f 218 413 284
+f 1843 180 347
+f 1846 1708 1798
+f 2469 2477 855
+f 1006 1021 1005
+f 381 382 250
+f 2369 828 531
+f 968 977 1001
+f 2460 1949 779
+f 1194 1441 1115
+f 1001 1000 968
+f 756 678 1745
+f 963 1009 901
+f 2471 2084 2472
+f 841 642 8
+f 982 991 1027
+f 670 844 1020
+f 1289 1514 945
+f 869 904 890
+f 1161 1115 1639
+f 823 2178 849
+f 746 12 499
+f 263 428 2366
+f 1685 1075 1692
+f 1002 926 806
+f 1799 1755 216
+f 944 968 993
+f 943 944 993
+f 31 38 19
+f 531 828 550
+f 1501 1078 1081
+f 1921 1149 431
+f 936 943 932
+f 1660 1489 1412
+f 301 980 285
+f 903 918 902
+f 869 890 868
+f 890 903 867
+f 1003 746 499
+f 951 1949 2500
+f 990 841 853
+f 1595 1634 1611
+f 374 927 974
+f 836 1025 247
+f 1653 1652 1638
+f 1303 1545 1142
+f 1616 1631 1638
+f 1629 1546 1628
+f 936 932 913
+f 513 506 531
+f 868 890 867
+f 2330 2369 2353
+f 924 918 914
+f 907 914 904
+f 1258 1421 1267
+f 301 939 980
+f 1472 1482 1296
+f 868 867 859
+f 472 491 313
+f 272 519 2488
+f 1471 1472 1296
+f 1025 934 247
+f 1634 1633 1611
+f 2176 1847 2177
+f 1310 1289 806
+f 924 933 918
+f 1969 1968 902
+f 2107 2128 2118
+f 1428 1436 1287
+f 1139 1564 1617
+f 2378 572 2384
+f 853 841 8
+f 2501 961 2465
+f 1221 1240 1408
+f 1069 1578 1627
+f 1006 1005 1001
+f 1617 1564 1578
+f 828 539 550
+f 1791 2168 2160
+f 1829 1718 1739
+f 1968 1939 902
+f 756 1718 665
+f 1998 2000 1388
+f 2451 545 2356
+f 178 997 1011
+f 1275 325 1270
+f 1709 872 1666
+f 2176 1959 1847
+f 944 943 936
+f 2424 518 511
+f 1445 1067 962
+f 2007 952 1828
+f 2052 2061 2081
+f 828 2303 539
+f 835 1699 1048
+f 1709 1706 872
+f 885 574 963
+f 1318 1296 1320
+f 859 867 1902
+f 1452 1448 1421
+f 943 993 976
+f 993 1000 983
+f 854 1010 876
+f 988 986 962
+f 2031 2052 2081
+f 924 1732 1828
+f 965 949 1060
+f 781 228 734
+f 1718 1765 665
+f 943 976 932
+f 1680 1794 1783
+f 1448 1471 1276
+f 1276 1267 1421
+f 1931 914 907
+f 991 781 996
+f 1276 1421 1448
+f 10 909 1396
+f 831 860 849
+f 1523 1762 1774
+f 924 1828 937
+f 307 994 1014
+f 946 963 901
+f 978 2103 977
+f 977 1006 1001
+f 1007 1161 1639
+f 1639 1294 1437
+f 885 1032 574
+f 1294 1381 1437
+f 733 568 797
+f 792 229 1112
+f 119 581 108
+f 843 835 927
+f 1889 860 831
+f 2211 2216 2204
+f 2400 2431 2422
+f 2103 1006 977
+f 840 1902 830
+f 827 840 830
+f 827 830 822
+f 1003 874 2492
+f 1432 1439 1431
+f 781 734 964
+f 1937 1936 1723
+f 918 913 902
+f 958 977 944
+f 1850 2178 2177
+f 1005 1020 1000
+f 991 996 307
+f 1396 1445 340
+f 2179 1763 889
+f 939 909 980
+f 1828 958 937
+f 978 977 958
+f 1590 1571 1563
+f 779 1949 920
+f 1551 1362 1573
+f 2103 2142 1006
+f 920 885 963
+f 946 920 963
+f 1584 1616 1583
+f 1453 1472 1452
+f 1647 1617 1578
+f 1578 1564 1627
+f 1628 938 1069
+f 869 868 859
+f 993 983 976
+f 912 1762 1775
+f 752 751 706
+f 1628 1546 938
+f 844 228 781
+f 840 859 1902
+f 898 907 904
+f 1025 973 1009
+f 663 664 573
+f 763 946 901
+f 898 904 869
+f 2172 889 1763
+f 1128 926 971
+f 860 848 849
+f 904 903 890
+f 2486 2459 2479
+f 577 782 608
+f 933 936 918
+f 2177 1847 1851
+f 665 1765 339
+f 937 958 944
+f 894 981 724
+f 968 1000 993
+f 2192 2195 2205
+f 1652 1099 817
+f 997 608 1011
+f 997 577 608
+f 577 163 782
+f 1112 998 792
+f 2177 1851 1850
+f 1257 1421 1258
+f 951 873 920
+f 822 830 2215
+f 1899 2496 2471
+f 1773 1668 1558
+f 904 914 903
+f 932 1671 913
+f 873 885 920
+f 1013 1617 1647
+f 873 1032 885
+f 894 862 981
+f 2469 855 961
+f 913 1671 1969
+f 2477 2064 855
+f 918 936 913
+f 860 870 848
+f 937 944 933
+f 1501 1013 1647
+f 824 178 751
+f 824 997 178
+f 824 577 997
+f 643 163 577
+f 863 856 882
+f 2128 2153 2134
+f 722 774 880
+f 722 894 774
+f 864 905 895
+f 850 575 583
+f 914 918 903
+f 924 937 933
+f 1501 717 1013
+f 1587 1324 928
+f 717 1512 1013
+f 602 577 824
+f 766 643 577
+f 894 709 862
+f 709 878 862
+f 976 975 932
+f 1324 1596 928
+f 880 524 1060
+f 2434 2459 2499
+f 1324 1613 1596
+f 752 824 751
+f 602 766 577
+f 1014 602 594
+f 1387 1226 2152
+f 2153 1387 2152
+f 669 930 950
+f 1710 1694 1699
+f 768 326 762
+f 582 892 601
+f 974 990 2465
+f 624 116 625
+f 835 795 730
+f 2458 2484 763
+f 989 602 824
+f 2064 2477 1710
+f 976 983 975
+f 949 722 880
+f 996 160 994
+f 2305 863 556
+f 556 863 886
+f 601 910 640
+f 2264 825 829
+f 989 824 752
+f 856 864 882
+f 1595 1586 2381
+f 1627 1629 1628
+f 2174 2180 2173
+f 2128 2134 2118
+f 137 272 22
+f 949 880 1060
+f 995 894 722
+f 894 995 709
+f 894 724 774
+f 886 895 892
+f 640 910 930
+f 871 870 860
+f 846 856 863
+f 1026 875 1019
+f 838 851 829
+f 1024 1171 934
+f 36 189 205
+f 863 882 886
+f 886 882 895
+f 875 1026 594
+f 52 1459 1269
+f 896 917 910
+f 1025 1009 934
+f 949 995 722
+f 2152 1226 1636
+f 895 896 892
+f 892 910 601
+f 942 950 930
+f 875 989 752
+f 594 602 989
+f 766 355 643
+f 355 260 643
+f 905 917 896
+f 965 1060 1162
+f 892 896 910
+f 1101 1052 1042
+f 1029 1031 834
+f 1101 1133 1118
+f 342 357 376
+f 516 515 2454
+f 1656 2494 2467
+f 1056 1303 1133
+f 1120 1130 862
+f 69 342 376
+f 1055 1056 1133
+f 499 69 165
+f 85 101 111
+f 1031 1032 834
+f 200 679 1166
+f 1031 1042 1032
+f 1171 65 934
+f 1822 1204 1177
+f 1096 956 1103
+f 514 96 97
+f 956 1145 1144
+f 1185 1166 1144
+f 1145 1185 1144
+f 1185 200 1166
+f 375 132 1041
+f 1153 1202 305
+f 32 1244 1249
+f 1096 1087 956
+f 554 78 2355
+f 1191 138 110
+f 65 35 432
+f 1087 1110 956
+f 1110 1146 956
+f 956 1146 1145
+f 1146 1156 1145
+f 1145 1156 1185
+f 950 956 1144
+f 2481 2495 948
+f 1156 1193 1185
+f 1050 1047 1051
+f 239 151 107
+f 1185 1193 36
+f 1747 1110 1087
+f 1134 1146 1110
+f 1146 1157 1156
+f 1156 1157 1193
+f 1041 1045 1034
+f 1397 1134 1110
+f 1157 1146 1134
+f 1157 1175 1193
+f 1193 199 36
+f 1090 1035 1196
+f 1456 1150 1051
+f 1175 199 1193
+f 1186 695 199
+f 1186 199 1175
+f 1175 1157 1134
+f 728 1186 1175
+f 197 760 6
+f 1130 593 862
+f 1167 1109 182
+f 1194 1115 1161
+f 2140 1928 1504
+f 921 922 2138
+f 1147 1134 1397
+f 1719 1147 1397
+f 1147 1175 1134
+f 1175 1147 728
+f 341 1654 1208
+f 754 151 9
+f 284 2138 1058
+f 1188 1557 1660
+f 1191 110 1053
+f 916 284 1189
+f 284 1058 1189
+f 2094 1465 2127
+f 1726 1019 1147
+f 1147 1019 728
+f 593 1130 96
+f 239 305 1038
+f 1036 1131 315
+f 397 1131 1120
+f 1053 96 1130
+f 2467 2485 1869
+f 517 1089 421
+f 834 1827 1029
+f 419 1047 1117
+f 1034 433 1306
+f 2239 1862 1730
+f 1453 1462 1472
+f 1408 1422 1399
+f 471 23 1111
+f 1205 1150 1456
+f 1205 1040 1150
+f 1131 1036 293
+f 293 1068 1044
+f 375 1041 138
+f 1205 1140 1046
+f 1040 1205 1046
+f 1140 1167 1046
+f 1104 1049 83
+f 1052 1085 1032
+f 1044 1068 1191
+f 1167 1483 1109
+f 208 1084 1035
+f 1040 132 375
+f 1834 20 3
+f 1050 1051 1070
+f 1133 1125 1174
+f 11 1440 1401
+f 420 208 1071
+f 1135 1079 1094
+f 1086 1101 1118
+f 1029 1030 1031
+f 1200 1061 294
+f 1191 1068 138
+f 1171 1141 65
+f 1141 1172 65
+f 1172 35 65
+f 1172 404 35
+f 404 99 35
+f 221 1104 1063
+f 802 398 1083
+f 20 1089 3
+f 2064 1699 835
+f 1042 1052 1032
+f 1433 1261 1432
+f 1323 2338 155
+f 1076 1205 1456
+f 1088 1402 1056
+f 1150 348 1070
+f 1200 1089 20
+f 1097 1162 100
+f 1032 873 834
+f 21 471 1111
+f 294 1097 1104
+f 1072 100 584
+f 1151 760 622
+f 132 1045 1041
+f 1050 1070 1135
+f 1088 1039 940
+f 650 159 635
+f 100 1170 729
+f 729 584 100
+f 1103 931 1096
+f 925 1443 1513
+f 138 1102 110
+f 1034 1306 1152
+f 1071 1035 1090
+f 100 1072 1097
+f 23 1158 315
+f 1068 375 138
+f 1586 1612 1585
+f 1819 1030 1029
+f 1041 1034 1102
+f 232 375 1068
+f 348 1079 1070
+f 1061 1097 294
+f 1513 1443 1442
+f 1200 294 1119
+f 376 1050 1062
+f 1094 1036 315
+f 1200 1119 1089
+f 1111 1183 21
+f 1044 1191 1053
+f 698 295 689
+f 1079 232 1036
+f 404 1117 99
+f 1495 1496 717
+f 1119 294 98
+f 3 1089 517
+f 1132 1063 83
+f 1132 83 175
+f 132 1046 182
+f 1111 1195 1183
+f 1131 1044 1037
+f 127 402 1804
+f 219 1272 1047
+f 1697 1135 1094
+f 2140 1854 2117
+f 1111 397 1195
+f 1177 1162 1097
+f 1061 1177 1097
+f 717 1509 714
+f 2 1300 433
+f 462 290 461
+f 98 294 221
+f 294 1104 221
+f 714 1161 1007
+f 1073 1152 1143
+f 1697 1094 1360
+f 1223 1423 1218
+f 836 2479 842
+f 1097 1072 1049
+f 348 1040 375
+f 3 517 316
+f 180 1061 1201
+f 348 375 232
+f 1432 1431 1415
+f 220 1513 1495
+f 1104 1097 1049
+f 306 674 596
+f 777 455 723
+f 2170 2151 1641
+f 1047 419 219
+f 1102 1034 1073
+f 1073 1034 1152
+f 1035 1054 1196
+f 1177 1204 1162
+f 746 65 12
+f 751 178 721
+f 1054 517 421
+f 1051 1150 1070
+f 1102 1073 110
+f 998 1136 355
+f 567 566 1163
+f 1111 315 397
+f 1048 1074 835
+f 1158 1094 315
+f 1374 1107 1252
+f 1112 1136 998
+f 472 629 500
+f 355 1136 260
+f 260 118 43
+f 1104 83 1063
+f 376 357 1050
+f 1463 1142 1545
+f 1036 232 293
+f 1030 1042 1031
+f 1079 348 232
+f 221 1063 1132
+f 1094 1079 1036
+f 1076 1629 1205
+f 1136 1197 260
+f 260 1197 118
+f 1204 965 1162
+f 293 232 1068
+f 1590 1205 1629
+f 1205 1590 1140
+f 250 382 392
+f 1296 1318 1311
+f 347 1201 20
+f 1201 1200 20
+f 132 182 1045
+f 1101 1086 1052
+f 1033 1039 1055
+f 138 1041 1102
+f 970 1010 2495
+f 455 777 43
+f 1992 1948 2023
+f 20 1834 347
+f 1072 584 1049
+f 584 1192 1049
+f 182 2 1045
+f 1163 324 44
+f 1360 1094 1158
+f 1450 1360 1158
+f 1091 1112 229
+f 509 723 455
+f 207 509 455
+f 1251 1257 1266
+f 1488 1489 1547
+f 2157 1541 1875
+f 305 107 324
+f 1045 2 433
+f 1070 1079 1135
+f 1136 1168 1197
+f 1197 359 118
+f 118 359 43
+f 359 356 43
+f 356 455 43
+f 356 207 455
+f 1240 1422 1408
+f 1163 1153 324
+f 1201 1061 1200
+f 1052 1086 1085
+f 1024 1141 1171
+f 1112 1105 1136
+f 1050 1135 1062
+f 1105 1168 1136
+f 1168 1178 1197
+f 1197 1178 359
+f 1173 404 1172
+f 465 356 359
+f 1174 1125 240
+f 1240 1431 1422
+f 1098 1113 1105
+f 1112 1098 1105
+f 1105 1178 1168
+f 1178 465 359
+f 1091 1098 1112
+f 1133 1174 1118
+f 98 221 1059
+f 487 1132 175
+f 980 1017 285
+f 465 207 356
+f 180 1201 347
+f 1060 524 1170
+f 445 127 316
+f 1431 1438 1422
+f 498 469 681
+f 940 1807 1759
+f 381 250 1290
+f 1113 1122 1105
+f 1105 1122 1178
+f 1151 509 207
+f 1236 2035 525
+f 1131 293 1044
+f 346 207 465
+f 346 1151 207
+f 1822 1796 1204
+f 1143 204 97
+f 123 1128 971
+f 2153 2152 2134
+f 126 1151 346
+f 517 445 316
+f 1450 1158 23
+f 1458 1462 1430
+f 1129 152 1182
+f 1122 1159 1178
+f 1178 1198 465
+f 79 346 465
+f 126 1155 1151
+f 1151 1155 6
+f 295 1129 689
+f 1073 1143 97
+f 1098 1123 1113
+f 1113 1123 1122
+f 1123 1169 1122
+f 1178 1159 1198
+f 1198 79 465
+f 392 383 152
+f 1822 1061 180
+f 116 92 625
+f 421 1089 1119
+f 1129 295 152
+f 110 1073 97
+f 1173 1172 1141
+f 1122 1169 1159
+f 79 126 346
+f 1155 181 6
+f 971 926 1002
+f 295 1043 152
+f 1039 1088 1056
+f 1428 1266 1436
+f 404 419 1117
+f 836 879 2479
+f 2464 2476 2458
+f 1198 317 79
+f 1124 939 301
+f 44 754 567
+f 1039 1056 1055
+f 1439 1459 1458
+f 1660 1412 986
+f 1169 1160 1159
+f 179 1155 126
+f 1155 131 181
+f 1061 1822 1177
+f 1153 305 324
+f 175 314 327
+f 1160 1187 1159
+f 1159 1187 1198
+f 1198 1187 317
+f 79 179 126
+f 1043 250 392
+f 152 1043 392
+f 96 819 593
+f 1123 1127 1169
+f 317 179 79
+f 1057 1155 179
+f 1155 391 131
+f 131 391 668
+f 2381 1586 1585
+f 12 69 499
+f 262 398 1640
+f 2107 2118 2060
+f 2130 2094 2002
+f 1187 249 317
+f 1155 1057 391
+f 1290 439 1265
+f 305 239 107
+f 1127 1160 1169
+f 317 473 179
+f 473 1057 179
+f 83 1192 314
+f 1043 1290 250
+f 1807 940 1030
+f 517 1084 445
+f 1057 1164 391
+f 2492 2480 2493
+f 163 643 43
+f 1056 1545 1303
+f 1069 1655 1023
+f 249 473 317
+f 1162 1060 1170
+f 1086 1118 1154
+f 82 68 16
+f 1989 1990 1536
+f 1633 1632 1611
+f 1487 2372 1305
+f 1494 1069 1023
+f 1137 1160 1127
+f 669 1166 679
+f 390 1285 426
+f 1955 1972 1971
+f 1219 1223 2437
+f 1254 1261 1223
+f 1319 1545 1056
+f 1320 1328 2443
+f 1261 1433 1223
+f 1219 1254 1223
+f 254 222 2428
+f 1237 1290 1265
+f 1284 1273 1263
+f 1277 1291 1301
+f 1314 102 1301
+f 1280 363 377
+f 1313 1353 1514
+f 468 451 439
+f 1918 1964 1956
+f 2026 29 2140
+f 1354 381 1279
+f 1224 30 1254
+f 147 158 173
+f 1247 1253 274
+f 1271 380 334
+f 2043 2072 2042
+f 274 300 267
+f 1356 1392 211
+f 13 240 1142
+f 1382 1330 1392
+f 1312 1323 155
+f 240 1125 1142
+f 2358 1573 1362
+f 1236 1249 1244
+f 1272 219 1348
+f 1271 1274 380
+f 191 2034 1982
+f 1992 2052 1990
+f 462 452 689
+f 2262 2286 2261
+f 183 489 1642
+f 2485 2480 1869
+f 84 111 1323
+f 1190 353 1354
+f 446 434 435
+f 1336 171 1341
+f 2021 430 2059
+f 862 878 1120
+f 1263 1273 1248
+f 1966 1921 2144
+f 1312 84 1323
+f 240 13 1348
+f 1359 1274 1271
+f 1392 1330 1247
+f 1520 1333 11
+f 1368 1253 1247
+f 1279 1285 1190
+f 2465 990 2489
+f 1272 1519 805
+f 1369 1272 805
+f 1317 95 1344
+f 1242 1248 1234
+f 1368 242 1363
+f 274 1262 1386
+f 532 597 1886
+f 2117 2026 2140
+f 1392 1247 274
+f 2162 508 985
+f 1964 1469 1965
+f 1315 104 1331
+f 1392 1356 1382
+f 128 1342 1336
+f 1285 427 426
+f 1219 1224 1254
+f 1320 1322 1321
+f 1320 1321 1328
+f 153 2443 1328
+f 1321 153 1328
+f 1235 1244 1243
+f 1225 1224 1219
+f 1359 353 1190
+f 1312 1473 1458
+f 1336 1342 147
+f 305 1333 1038
+f 1336 147 171
+f 516 31 19
+f 2479 2461 842
+f 1237 1265 427
+f 1263 1278 1284
+f 881 1827 834
+f 1237 427 1285
+f 1299 1312 1458
+f 1190 1285 1274
+f 1363 286 1253
+f 2330 2303 828
+f 427 442 426
+f 2493 2463 2492
+f 1285 380 1274
+f 522 18 1225
+f 2471 2472 2488
+f 2338 154 1321
+f 1423 1415 1218
+f 1225 18 1224
+f 1253 286 1262
+f 286 353 1359
+f 171 1368 1383
+f 1273 54 1234
+f 1973 2447 527
+f 1322 155 1321
+f 1203 1369 1413
+f 1307 363 1298
+f 1364 1375 1329
+f 1329 227 1306
+f 296 1298 1343
+f 947 2499 1447
+f 1203 1047 1272
+f 1098 1748 1123
+f 1519 1272 1348
+f 1277 70 1273
+f 1282 1337 1361
+f 286 302 353
+f 103 104 1315
+f 1377 435 434
+f 1449 1261 1345
+f 926 1310 806
+f 1263 1248 1242
+f 985 508 597
+f 1415 1222 1218
+f 88 1325 104
+f 170 111 156
+f 1384 1282 1361
+f 274 1253 1262
+f 1371 1317 1344
+f 1371 1366 1337
+f 1345 1459 1449
+f 171 1383 1341
+f 2438 1235 1227
+f 2134 1582 2118
+f 428 1260 1379
+f 1336 1341 1325
+f 1235 1242 1227
+f 1228 1687 2284
+f 1854 2140 2016
+f 1866 1887 1873
+f 1343 1298 1370
+f 1384 1361 2440
+f 171 242 1368
+f 1344 1309 1366
+f 1371 1344 1366
+f 1280 1377 1293
+f 200 1185 205
+f 1330 1383 1368
+f 1255 1264 1263
+f 543 1367 1876
+f 1343 1370 1260
+f 1293 1326 1370
+f 2440 1361 1302
+f 1282 1384 2406
+f 271 1337 1282
+f 170 2338 1323
+f 1528 1503 2470
+f 515 1347 2453
+f 1997 1705 1998
+f 2285 1228 2284
+f 1229 1250 1228
+f 1330 1368 1247
+f 1919 1619 2045
+f 1344 1364 1335
+f 1222 1240 1221
+f 1212 858 1741
+f 2388 1222 1221
+f 1528 2470 2068
+f 501 1308 2171
+f 1295 1311 1487
+f 2116 1619 1655
+f 1220 1229 1228
+f 8 663 573
+f 1343 1260 428
+f 1337 1366 1361
+f 1298 1280 1293
+f 1269 1345 1261
+f 1279 381 1290
+f 1230 1229 1220
+f 1230 1245 1229
+f 1245 1250 1229
+f 1227 1234 31
+f 1302 1361 1350
+f 1245 1266 1428
+f 1992 2023 2052
+f 2482 2471 2475
+f 452 462 461
+f 271 1282 1275
+f 1991 1989 1934
+f 1366 1309 1350
+f 1344 1335 1309
+f 730 699 974
+f 1374 1252 1208
+f 597 508 1912
+f 1363 1253 1368
+f 1386 1271 300
+f 1211 1218 1222
+f 1376 1377 434
+f 2399 2437 1211
+f 1284 1291 1277
+f 1230 1251 1245
+f 1251 1266 1245
+f 1317 1371 1337
+f 1288 1286 1095
+f 1095 1286 1352
+f 1241 1208 1352
+f 1241 1374 1208
+f 1284 1278 1291
+f 211 1392 267
+f 1344 1375 1364
+f 929 583 1028
+f 1361 1366 1350
+f 1115 1294 1639
+f 1291 103 1301
+f 1220 1231 1230
+f 1231 1251 1230
+f 1234 1248 1273
+f 1255 55 1264
+f 1360 1450 1702
+f 363 1280 1298
+f 1369 1203 1272
+f 1415 1240 1222
+f 1216 1231 1220
+f 1243 1263 1235
+f 1375 227 1329
+f 1264 1278 1263
+f 855 899 961
+f 1286 1241 1352
+f 2081 2128 2107
+f 1223 1433 1423
+f 1473 1312 155
+f 154 153 1321
+f 1377 1376 1293
+f 1392 274 267
+f 334 300 1271
+f 1955 1991 1934
+f 1613 1327 1288
+f 1327 1286 1288
+f 1349 1374 1241
+f 2370 2025 2367
+f 1315 1331 133
+f 434 446 1256
+f 1232 1251 1231
+f 1243 1244 1255
+f 1286 1304 1241
+f 1349 1107 1374
+f 1359 1271 1386
+f 1227 516 2431
+f 219 240 1348
+f 1270 271 1275
+f 1255 1263 1243
+f 2026 1926 29
+f 1683 2157 1212
+f 1326 1293 1376
+f 1255 32 55
+f 104 1325 1341
+f 519 2462 2475
+f 2154 2161 2137
+f 1376 434 1246
+f 1246 434 1256
+f 1257 1251 1232
+f 1262 1359 1386
+f 2195 2192 2186
+f 1308 534 1226
+f 2026 2117 544
+f 1327 1613 1324
+f 1327 1326 1286
+f 1286 1326 1304
+f 104 1341 1331
+f 774 524 880
+f 837 1517 534
+f 1127 1123 1567
+f 1279 1237 1285
+f 1297 1381 1294
+f 1217 1232 1216
+f 1142 1519 13
+f 1436 1267 1287
+f 1324 1372 1327
+f 1304 1246 1241
+f 1246 1349 1241
+f 1246 1373 1349
+f 286 1359 1262
+f 1382 1383 1330
+f 1284 1277 1273
+f 489 1998 1799
+f 1675 1116 1075
+f 106 1317 1337
+f 1311 1295 1281
+f 1292 1364 1329
+f 1335 1364 1292
+f 1334 1294 1115
+f 1334 1297 1294
+f 1300 1381 1297
+f 973 842 2461
+f 1217 1239 1232
+f 1232 1239 1257
+f 1258 1267 1436
+f 1359 1190 1274
+f 1862 1405 1877
+f 1372 1339 1327
+f 1339 1326 1327
+f 1373 1351 1349
+f 1276 1311 1281
+f 1256 2386 1351
+f 2 1109 1300
+f 482 1731 520
+f 803 1604 2022
+f 1223 1218 1211
+f 1341 1383 1382
+f 1298 1293 1370
+f 1190 1354 1279
+f 1324 2398 1372
+f 1714 1700 2173
+f 183 2000 489
+f 1701 1666 192
+f 1227 1242 1234
+f 1332 1289 1310
+f 1517 2005 2130
+f 1331 1341 1382
+f 525 1249 1236
+f 23 1268 1450
+f 1264 1291 1278
+f 1281 1287 1267
+f 1295 1305 1287
+f 1281 1295 1287
+f 1487 1305 1295
+f 1605 2097 2058
+f 1326 1376 1304
+f 1304 1376 1246
+f 1316 1919 1984
+f 2500 1949 2460
+f 1332 1313 1289
+f 2189 2181 2177
+f 1335 1334 1353
+f 1292 1297 1334
+f 1428 1250 1245
+f 969 958 952
+f 1217 1233 1239
+f 1233 1257 1239
+f 1876 1367 1338
+f 1379 1260 1372
+f 1372 1260 1339
+f 1128 1302 1310
+f 1310 1302 1332
+f 1335 1353 1313
+f 1292 1334 1335
+f 1297 1329 1300
+f 1279 1290 1237
+f 1301 103 1314
+f 70 1301 102
+f 23 1333 1268
+f 380 1285 390
+f 772 325 1275
+f 1314 103 1315
+f 2473 2458 2487
+f 1276 1281 1267
+f 1344 95 1375
+f 2053 1771 1572
+f 1246 1256 1373
+f 1373 1256 1351
+f 1340 1302 1128
+f 1350 1313 1332
+f 1329 1297 1292
+f 2434 2473 2487
+f 106 1337 271
+f 23 471 1333
+f 622 723 509
+f 1388 1517 2127
+f 1991 1990 1989
+f 183 1636 1226
+f 2133 1605 2151
+f 1260 1370 1339
+f 1339 1370 1326
+f 867 1894 1902
+f 390 426 412
+f 1235 1263 1242
+f 1399 1422 1233
+f 305 11 1333
+f 1300 1329 1306
+f 1302 1350 1332
+f 1350 1309 1313
+f 1309 1335 1313
+f 2470 2102 1502
+f 1787 1531 1599
+f 1724 1725 1691
+f 1827 1601 1927
+f 1678 1358 1476
+f 1823 1812 1846
+f 1805 1824 1708
+f 1746 1676 1797
+f 325 2395 429
+f 1835 1677 1826
+f 1507 1790 1722
+f 1526 1672 858
+f 158 147 1342
+f 1462 1473 1322
+f 1474 1414 1565
+f 1761 1900 1877
+f 940 1759 1008
+f 1565 1015 1008
+f 1924 1533 1933
+f 1878 826 830
+f 1565 1414 1015
+f 1402 1088 1008
+f 1538 1532 1651
+f 1015 1552 1008
+f 1538 1591 1474
+f 1532 1538 1474
+f 1474 1591 1414
+f 1484 1402 1008
+f 1552 1484 1008
+f 1414 1460 1015
+f 1015 1460 1552
+f 806 1289 945
+f 1597 1538 1659
+f 1484 1319 1402
+f 1056 1402 1319
+f 1538 1597 1591
+f 1591 960 1414
+f 1414 960 1460
+f 1925 1466 1455
+f 1552 1400 1484
+f 1484 1400 1319
+f 1400 113 1319
+f 1597 1580 1591
+f 1460 1400 1552
+f 1514 1441 966
+f 1597 1659 1409
+f 1657 113 1400
+f 1460 1657 1400
+f 1288 1095 1634
+f 1551 1597 1409
+f 1580 1598 1591
+f 1591 1598 960
+f 1536 1990 2031
+f 960 1657 1460
+f 1809 1746 1797
+f 1423 1433 1432
+f 2478 1362 1409
+f 1463 1545 113
+f 1657 1463 113
+f 1457 1287 1305
+f 1682 1716 1746
+f 1434 1761 1885
+f 1013 1139 1617
+f 2379 1362 2478
+f 1420 1597 1551
+f 1420 1580 1597
+f 1664 1808 1712
+f 2256 2250 2231
+f 1362 1551 1409
+f 2196 2214 2213
+f 1691 1725 1777
+f 1626 192 1666
+f 1534 1574 2058
+f 1574 1600 1605
+f 1600 1606 1605
+f 1606 1641 1605
+f 1573 1420 1551
+f 1657 1485 1463
+f 678 1806 1742
+f 1534 1553 1574
+f 1574 1575 1600
+f 1810 2170 585
+f 1623 1641 1606
+f 1407 1657 960
+f 1598 1407 960
+f 1485 1142 1463
+f 1716 1581 1676
+f 1738 1743 1733
+f 843 2064 835
+f 1539 1575 1574
+f 1553 1539 1574
+f 1575 1592 1600
+f 1592 1624 1606
+f 1600 1592 1606
+f 1642 585 1641
+f 1623 1642 1641
+f 1485 164 1142
+f 1738 1516 1743
+f 1809 1720 1798
+f 1533 1535 1534
+f 1592 1607 1624
+f 1624 1623 1606
+f 1163 566 1116
+f 1407 1485 1657
+f 1432 1449 1439
+f 1100 802 2382
+f 1743 1516 1722
+f 1746 1716 1676
+f 1535 1539 1534
+f 1534 1539 1553
+f 1642 1623 1624
+f 1095 1208 1654
+f 967 1407 1598
+f 1580 967 1598
+f 1809 1797 1720
+f 1924 1524 1535
+f 1533 1924 1535
+f 1539 1576 1575
+f 1642 216 585
+f 1407 1529 1485
+f 1485 1529 164
+f 1472 1462 1482
+f 1415 1431 1240
+f 966 1194 714
+f 383 1182 152
+f 474 2337 446
+f 1743 1841 1757
+f 1486 1524 1924
+f 1535 1525 1539
+f 1575 1576 1592
+f 1420 967 1580
+f 1288 1634 1613
+f 459 427 1265
+f 1404 2179 1393
+f 1404 1403 1800
+f 1404 1410 1403
+f 1410 1749 1403
+f 1349 1351 218
+f 1486 1498 1524
+f 1535 1524 1525
+f 1607 1636 1624
+f 183 1642 1624
+f 1636 183 1624
+f 1107 1349 218
+f 1351 845 218
+f 164 1519 1142
+f 845 413 218
+f 1525 1576 1539
+f 1576 1582 1592
+f 1592 2134 1607
+f 2134 1636 1607
+f 2147 1491 1401
+f 1407 1589 1529
+f 1529 1519 164
+f 1693 1763 1444
+f 1924 1479 1486
+f 1592 1582 2134
+f 499 165 874
+f 2176 1857 1959
+f 2327 2368 2326
+f 2358 821 953
+f 953 821 1573
+f 1824 1704 1464
+f 1731 1358 1678
+f 1394 1410 1404
+f 1394 1418 1410
+f 1466 1479 1839
+f 1486 1479 1498
+f 1498 1525 1524
+f 1576 2080 1582
+f 1785 1684 1898
+f 804 398 802
+f 804 925 398
+f 1447 1562 2358
+f 2358 1562 821
+f 821 1620 1573
+f 1620 1420 1573
+f 1420 1556 967
+f 1393 1394 1404
+f 1525 2080 1576
+f 1621 1420 1620
+f 1621 1556 1420
+f 967 1589 1407
+f 1505 5 1357
+f 1266 1258 1436
+f 1393 1395 1394
+f 2176 2175 1848
+f 1455 1466 1839
+f 1525 1540 2080
+f 1582 2080 2118
+f 1100 804 802
+f 1556 1589 967
+f 1589 1082 1529
+f 1093 1685 1357
+f 1504 1093 1357
+f 1425 1418 1394
+f 1475 1479 1466
+f 1479 1506 1498
+f 1789 1784 1730
+f 2501 2465 2489
+f 1438 1458 1430
+f 1462 1458 1473
+f 1454 805 1529
+f 1082 1454 1529
+f 1529 805 1519
+f 1425 1394 1395
+f 1425 1744 1418
+f 1479 1475 1506
+f 1540 2060 2080
+f 1556 1082 1589
+f 1443 945 1511
+f 1506 1536 1498
+f 1498 1536 1525
+f 1525 1536 1540
+f 1670 852 1672
+f 1998 1388 1389
+f 1511 966 1509
+f 1509 966 714
+f 1442 1443 1496
+f 1562 1635 821
+f 155 1322 1473
+f 1439 1458 1438
+f 1426 1425 1395
+f 1475 1499 1506
+f 1735 1588 1776
+f 2422 2454 2421
+f 1423 1432 1415
+f 1559 2101 2073
+f 845 866 413
+f 1429 1620 821
+f 1620 1429 1621
+f 1228 1250 1687
+f 1002 945 1443
+f 2382 802 1083
+f 1859 1411 1395
+f 1411 1426 1395
+f 1426 1744 1425
+f 1590 1437 1483
+f 1480 1475 1466
+f 1480 1499 1475
+f 1510 1733 1743
+f 1663 1696 1658
+f 1430 1453 1452
+f 1452 1472 1471
+f 1452 1471 1448
+f 1430 1452 1421
+f 1430 1421 1422
+f 1429 1082 1556
+f 1621 1429 1556
+f 1351 2386 845
+f 1126 1059 487
+f 1639 1437 1563
+f 1504 1928 1093
+f 1499 1536 1506
+f 1588 1770 1727
+f 1110 1747 1397
+f 1776 1588 1531
+f 1322 1320 1482
+f 1590 1629 1571
+f 1730 1877 1838
+f 1429 935 1082
+f 1082 935 1454
+f 804 1443 925
+f 1139 1007 1639
+f 1925 1480 1466
+f 1934 1989 1480
+f 1499 1989 1536
+f 1727 1526 1531
+f 1593 1614 502
+f 2455 2431 2400
+f 1755 1680 908
+f 1563 1571 1564
+f 1647 1078 1501
+f 2490 1635 1106
+f 1496 1511 717
+f 2454 2431 516
+f 1478 1153 1093
+f 1870 1426 1411
+f 1426 1723 1744
+f 962 986 1412
+f 717 1511 1509
+f 1825 1704 1824
+f 2225 2234 2253
+f 1490 1557 1188
+f 1635 80 821
+f 805 1454 935
+f 1186 706 695
+f 1194 1161 714
+f 1512 1007 1013
+f 592 97 204
+f 1258 1266 1257
+f 82 1333 471
+f 1694 1710 1505
+f 1643 490 1661
+f 1661 490 1114
+f 1518 2068 2484
+f 1750 1808 1664
+f 1656 1635 2490
+f 935 1521 805
+f 1546 1629 1076
+f 1301 70 1277
+f 966 1441 1194
+f 1148 1825 1824
+f 1614 1609 1643
+f 1114 1092 1921
+f 1770 1739 1670
+f 1631 1632 1646
+f 821 1016 1429
+f 1429 1016 935
+f 1632 1095 1654
+f 1083 262 688
+f 1724 1686 1725
+f 1644 490 1643
+f 1092 1149 1921
+f 3 893 1832
+f 988 1640 1188
+f 916 1107 284
+f 1656 80 1635
+f 1016 821 80
+f 1016 1521 935
+f 1478 1202 1153
+f 1401 1928 29
+f 1440 1478 1928
+f 1849 1700 1865
+f 1595 1611 1612
+f 1208 198 341
+f 1464 1704 1746
+f 2143 984 1721
+f 1848 1849 1868
+f 1662 1114 490
+f 1669 1787 1682
+f 1656 1618 80
+f 198 1208 916
+f 1440 1928 1401
+f 1521 1369 805
+f 1252 1107 916
+f 1745 678 1672
+f 1703 1779 1721
+f 1750 1465 1808
+f 1609 1644 1643
+f 1092 1114 1662
+f 1826 1523 1793
+f 2262 2261 2224
+f 1696 2166 1767
+f 1016 1648 1521
+f 1208 1252 916
+f 833 688 1067
+f 1794 1803 1558
+f 28 17 512
+f 1750 861 1566
+f 1594 1644 1609
+f 1644 1645 490
+f 490 1645 1662
+f 2229 2262 2224
+f 1602 861 1760
+f 1530 1777 1760
+f 872 1706 1673
+f 1696 1668 2166
+f 1708 1809 1798
+f 1581 1716 1814
+f 1709 1794 1680
+f 1233 1421 1257
+f 1724 1476 1686
+f 1469 1481 1965
+f 1965 1481 1492
+f 2073 1549 1559
+f 1594 1615 1644
+f 1799 1706 1755
+f 1725 1686 1837
+f 1720 1797 1572
+f 1618 2467 2022
+f 1618 1579 80
+f 1648 1016 80
+f 2134 2152 1636
+f 1611 1632 1631
+f 1761 1434 1470
+f 1559 1577 1594
+f 1603 1615 1594
+f 1615 1645 1644
+f 1637 1662 1645
+f 1662 1199 1092
+f 1199 1149 1092
+f 1451 1108 1149
+f 665 734 756
+f 1865 1700 1714
+f 1709 1841 1794
+f 1618 2022 1579
+f 1648 1413 1369
+f 1521 1648 1369
+f 1520 11 1401
+f 1446 1470 1434
+f 1798 1691 1754
+f 2063 1544 2073
+f 2073 1544 1549
+f 1594 1577 1603
+f 1615 1637 1645
+f 1637 1199 1662
+f 1427 1149 1199
+f 2167 1108 1451
+f 1997 1673 1705
+f 1706 1799 1705
+f 1841 1709 1757
+f 1604 1579 2022
+f 1579 707 80
+f 80 707 1648
+f 1520 1401 1491
+f 1649 1520 1491
+f 1435 1434 1885
+f 1470 1469 1461
+f 1481 1508 2024
+f 2370 1544 2063
+f 1549 1568 1559
+f 1559 1568 1577
+f 1603 1610 1615
+f 1615 1610 1637
+f 999 1199 1637
+f 1451 1149 1427
+f 1137 1825 1148
+f 1706 1705 1673
+f 1138 1604 2116
+f 1138 1579 1604
+f 1413 1648 707
+f 2360 2024 1508
+f 598 1075 1116
+f 229 93 1468
+f 1839 1479 1684
+f 2216 2229 2224
+f 1610 1625 1637
+f 329 999 1637
+f 1199 1017 1427
+f 1017 303 1427
+f 303 1451 1427
+f 1792 1754 1777
+f 2309 2391 2301
+f 1655 1138 2116
+f 1138 707 1579
+f 1649 1491 206
+f 1406 1885 1398
+f 1406 1419 1885
+f 1419 1435 1885
+f 1434 1435 1446
+f 1470 1481 1469
+f 1577 1583 1603
+f 999 1017 1199
+f 81 67 941
+f 67 1650 941
+f 1259 1815 2164
+f 1619 2116 2045
+f 1424 707 1138
+f 1702 1649 206
+f 1687 1406 1398
+f 1477 1481 1470
+f 1568 1569 1577
+f 1577 1569 1583
+f 1603 1583 1610
+f 1625 329 1637
+f 2167 340 273
+f 81 273 340
+f 81 962 67
+f 1547 1619 1488
+f 1830 1739 1770
+f 938 1424 1138
+f 1424 1413 707
+f 1527 1649 1702
+f 1527 1520 1649
+f 1527 1268 1520
+f 1250 1406 1687
+f 1441 1353 1115
+f 1203 1413 1051
+f 1250 1419 1406
+f 1477 2372 1481
+f 1481 2372 1508
+f 2449 1560 1568
+f 1549 2449 1568
+f 1568 1560 1569
+f 1569 1584 1583
+f 1652 329 1625
+f 329 817 999
+f 285 1017 999
+f 303 10 1451
+f 10 2167 1451
+f 1412 1650 67
+f 1412 1488 1650
+f 1547 1023 1619
+f 1023 1655 1619
+f 1655 938 1138
+f 1456 1413 1424
+f 1457 1470 1446
+f 1457 1477 1470
+f 329 1652 817
+f 10 340 2167
+f 938 1546 1424
+f 1546 1456 1424
+f 1259 1548 1779
+f 2052 2031 1990
+f 1440 1202 1478
+f 1428 1419 1250
+f 1428 1435 1419
+f 1428 1446 1435
+f 1934 1935 1955
+f 1560 1584 1569
+f 1610 1638 1625
+f 1638 1652 1625
+f 817 1077 999
+f 1077 285 999
+f 980 303 1017
+f 962 1412 67
+f 1494 1023 1547
+f 325 271 1270
+f 1443 1511 1496
+f 1450 1268 1527
+f 1514 1353 1441
+f 1287 1446 1428
+f 1446 1287 1457
+f 1305 2372 1477
+f 1992 1990 1991
+f 1992 1991 1971
+f 1971 1991 1955
+f 2449 1549 2418
+f 1583 1616 1610
+f 1610 1616 1638
+f 10 1396 340
+f 340 1445 81
+f 1445 962 81
+f 1790 984 1753
+f 984 2148 1753
+f 1588 1713 1770
+f 969 978 958
+f 1741 1779 1703
+f 1758 1846 1754
+f 1827 1819 1029
+f 1818 1530 1712
+f 1750 1566 2127
+f 2459 2434 2483
+f 1798 1720 1771
+f 1794 1841 1803
+f 216 1755 1810
+f 1098 1735 1748
+f 1735 1497 1748
+f 1502 2102 1601
+f 881 1502 1601
+f 1455 1839 1744
+f 1706 1709 1680
+f 1212 1741 1703
+f 1788 1969 1671
+f 1075 1074 1692
+f 951 2500 881
+f 2490 2486 2463
+f 1748 1497 1781
+f 1721 984 1840
+f 1815 1259 1741
+f 1626 1756 1837
+f 975 987 1542
+f 2230 2236 2235
+f 1772 678 734
+f 1542 1671 975
+f 1806 1772 1780
+f 678 1772 1806
+f 2218 2225 2268
+f 1828 1732 2007
+f 1526 1688 1531
+f 1752 1526 1554
+f 1844 1818 1712
+f 1823 1846 1804
+f 1781 1669 1704
+f 1721 1779 2143
+f 1770 1670 1526
+f 1497 1669 1781
+f 1098 1713 1735
+f 1742 1815 1741
+f 1526 858 1875
+f 1599 1531 1688
+f 1803 1790 1558
+f 1703 1721 1683
+f 1832 1766 957
+f 1542 1679 1671
+f 1679 1788 1671
+f 1927 1819 1827
+f 1718 1745 1739
+f 1684 1022 1839
+f 1459 1283 1299
+f 1022 1410 1418
+f 2368 2393 2326
+f 1669 1497 1776
+f 1875 858 1212
+f 1739 1745 852
+f 1964 1918 1461
+f 1356 133 1331
+f 1765 1829 1468
+f 858 1742 1741
+f 1006 1674 1021
+f 1723 1936 1935
+f 1468 1713 1098
+f 1724 1678 1476
+f 1680 1783 908
+f 1731 1543 520
+f 1683 1721 1840
+f 1467 1679 1542
+f 1812 1708 1846
+f 1679 1975 1788
+f 1713 1830 1770
+f 1803 1722 1790
+f 2301 2391 2349
+f 1713 1588 1735
+f 1836 1530 1818
+f 1837 1756 861
+f 886 571 556
+f 1181 1805 1812
+f 1706 1680 1755
+f 1677 1729 1775
+f 1776 1787 1669
+f 1526 1670 1672
+f 1727 1770 1526
+f 987 1467 1542
+f 1567 1704 1137
+f 1693 1865 1714
+f 897 1762 912
+f 1135 1697 1062
+f 1697 376 1062
+f 1543 1731 1678
+f 1793 1679 1467
+f 1777 1602 1760
+f 1846 1798 1754
+f 1835 1096 1677
+f 1033 1030 940
+f 1450 1527 1702
+f 1717 376 1697
+f 1711 1717 1697
+f 1717 165 376
+f 1840 984 1790
+f 1669 1746 1704
+f 1669 1682 1746
+f 2301 2349 2308
+f 1882 1444 1898
+f 1820 1789 1730
+f 861 1380 1566
+f 2301 2308 2266
+f 1771 1543 1691
+f 1958 1659 1651
+f 1697 1360 1711
+f 1711 1737 1717
+f 1717 1737 165
+f 1790 1753 1558
+f 1668 1696 1663
+f 1360 1702 1711
+f 1702 1707 1711
+f 1707 1737 1711
+f 1737 1751 165
+f 1444 1782 1693
+f 1716 1787 1599
+f 1744 1839 1022
+f 1898 1444 1785
+f 206 1707 1702
+f 1764 2468 1751
+f 316 1844 893
+f 893 1844 915
+f 1845 1804 1758
+f 1380 861 1756
+f 1780 670 1021
+f 1714 2172 1763
+f 1783 1558 1663
+f 1750 2127 1465
+f 1798 1771 1691
+f 1691 1543 1724
+f 1872 1910 839
+f 1737 2044 1751
+f 1751 2044 1764
+f 1757 1701 482
+f 1725 1602 1777
+f 1836 1845 1530
+f 2102 2470 1503
+f 2496 1899 544
+f 763 2484 946
+f 987 1719 1467
+f 1845 1758 1792
+f 1725 1837 1602
+f 1872 1866 1873
+f 1712 1530 1760
+f 489 1799 216
+f 1760 861 1750
+f 2068 2466 2460
+f 1696 2159 2168
+f 377 1377 1280
+f 1797 1676 1572
+f 1581 2053 1572
+f 1676 1581 1572
+f 1764 2498 2468
+f 2468 2498 1994
+f 1861 1695 1860
+f 2481 2004 2495
+f 1826 1677 1523
+f 1670 1739 852
+f 2234 2269 2253
+f 1724 1543 1678
+f 1658 2168 1791
+f 1397 1747 1719
+f 1696 2168 1658
+f 979 519 272
+f 1774 1975 1679
+f 975 1671 932
+f 1787 1716 1682
+f 1835 1826 1747
+f 2501 2469 961
+f 1810 908 1791
+f 1982 1768 191
+f 1137 1704 1825
+f 1804 1846 1758
+f 2004 2044 1737
+f 913 1969 902
+f 2498 1795 1801
+f 915 1844 1712
+f 1689 915 1712
+f 1740 1752 1541
+f 695 661 199
+f 1865 1693 1782
+f 1824 1464 1809
+f 1829 1765 1718
+f 1816 1768 1982
+f 1816 1622 1768
+f 1622 2165 1681
+f 1768 1622 1681
+f 670 1772 228
+f 1283 1459 52
+f 1785 1444 1749
+f 1675 1075 1685
+f 1567 1781 1704
+f 1858 1857 1848
+f 1526 1752 1688
+f 1791 2160 1810
+f 908 1658 1791
+f 1813 1773 1558
+f 1845 1792 1530
+f 69 376 165
+f 3 1832 1834
+f 1722 1516 1507
+f 1801 1821 1994
+f 1833 1982 2046
+f 1821 1833 2046
+f 1833 1816 1982
+f 1022 1785 1749
+f 2160 2170 1810
+f 1147 1719 1726
+f 1683 1840 1507
+f 1467 1719 1793
+f 1795 1802 1801
+f 1802 1811 1801
+f 1801 1811 1821
+f 1690 2165 1622
+f 1934 1480 1925
+f 229 1468 1091
+f 1780 2164 1742
+f 1672 1742 858
+f 1833 1417 1816
+f 1417 1622 1816
+f 1831 2165 1690
+f 1668 1663 1558
+f 1719 1747 1826
+f 1760 1750 1664
+f 1817 1690 1622
+f 1530 1792 1777
+f 948 1796 1802
+f 1796 1811 1802
+f 1515 1817 1622
+f 1695 1861 1831
+f 1783 1663 1658
+f 1749 1410 1022
+f 854 1796 948
+f 1811 1842 1833
+f 1821 1811 1833
+f 1833 1842 1417
+f 1622 1417 1515
+f 127 1804 1845
+f 1686 1626 1837
+f 1608 1690 1817
+f 1523 1775 1762
+f 127 1845 1836
+f 1812 1805 1708
+f 1523 1677 1775
+f 1780 1772 670
+f 1758 1754 1792
+f 1204 1796 854
+f 1822 1842 1811
+f 1608 1831 1690
+f 1822 1811 1796
+f 1842 1416 1417
+f 1417 1416 1515
+f 1515 1608 1817
+f 1728 1831 1608
+f 908 1783 1658
+f 127 1836 316
+f 1805 1148 1824
+f 852 1745 1672
+f 1478 1093 1928
+f 1822 1843 1842
+f 1843 959 1842
+f 1842 959 1416
+f 1728 1695 1831
+f 1728 1860 1695
+f 2346 446 2337
+f 1602 1837 861
+f 1087 1096 1835
+f 1708 1824 1809
+f 2004 1737 505
+f 1567 1748 1781
+f 520 1543 1883
+f 1760 1664 1712
+f 128 1336 72
+f 2053 1883 1543
+f 1822 180 1843
+f 1786 1608 1515
+f 929 2462 519
+f 512 2402 506
+f 1212 1703 1683
+f 1830 1829 1739
+f 2053 1543 1771
+f 1416 1769 1515
+f 1769 1786 1515
+f 1786 1728 1608
+f 1712 1808 1689
+f 1794 1558 1783
+f 1497 1735 1776
+f 1127 1567 1137
+f 1123 1748 1567
+f 36 205 1185
+f 959 1734 1416
+f 1738 1733 1541
+f 1774 1762 1974
+f 1752 1554 1541
+f 1752 1740 1688
+f 1526 1875 1554
+f 1468 1829 1830
+f 1755 908 1810
+f 1716 1599 1814
+f 1806 1780 1742
+f 2308 2349 2340
+f 1832 915 1689
+f 1713 1468 1830
+f 1814 1599 1346
+f 1832 1689 1766
+f 1022 1684 1785
+f 1093 1153 1116
+f 1672 678 1742
+f 1675 1685 1093
+f 1841 1743 1722
+f 1814 2053 1581
+f 1464 1746 1809
+f 2485 2497 2493
+f 1416 1734 1769
+f 1665 1728 1786
+f 1665 1951 1728
+f 1951 1860 1728
+f 1951 2094 1860
+f 1844 1836 1818
+f 316 1836 1844
+f 1776 1531 1787
+f 1719 1826 1793
+f 2147 1401 29
+f 2111 2121 1548
+f 1741 1259 1779
+f 1843 347 1834
+f 1843 1734 959
+f 1766 1769 1734
+f 957 1766 1734
+f 1766 1786 1769
+f 1766 1689 1786
+f 1689 1665 1786
+f 1754 1691 1777
+f 1507 1840 1790
+f 1761 1470 1461
+f 1523 1679 1793
+f 1091 1468 1098
+f 1820 1730 1838
+f 1843 1834 1734
+f 1808 1951 1665
+f 1588 1727 1531
+f 893 915 1832
+f 1523 1774 1679
+f 272 2488 710
+f 1093 1116 1675
+f 2340 2349 2348
+f 1832 1734 1834
+f 1832 957 1734
+f 1951 1808 2094
+f 1685 1692 1505
+f 1043 295 698
+f 2143 1779 2121
+f 1689 1808 1665
+f 1693 1714 1763
+f 1738 2157 1516
+f 1114 1921 236
+f 1268 1333 1520
+f 1149 1108 431
+f 508 2144 1912
+f 1957 1108 1537
+f 431 1108 1957
+f 1018 1108 2167
+f 1338 1957 1681
+f 2163 1957 1338
+f 1983 1390 2093
+f 30 557 37
+f 1714 2173 2172
+f 1983 1984 1390
+f 1984 2065 1390
+f 884 1762 897
+f 2065 1984 1214
+f 1950 1974 1762
+f 884 1950 1762
+f 2012 1698 1861
+f 1214 2116 803
+f 1950 1938 1974
+f 1938 1967 1974
+f 1900 1761 1461
+f 865 1929 884
+f 884 1929 1950
+f 2062 2071 2042
+f 919 1985 1732
+f 1593 502 2146
+f 1995 1213 2098
+f 1522 2476 1651
+f 2174 1849 2175
+f 1480 1989 1499
+f 1929 1938 1950
+f 1605 2058 1574
+f 2097 1605 2133
+f 1912 2014 1886
+f 2092 2082 2083
+f 206 1930 505
+f 2101 2100 2092
+f 2073 2101 2092
+f 839 1910 865
+f 1910 1901 1929
+f 865 1910 1929
+f 1967 1788 1975
+f 2073 2092 2063
+f 2101 1593 2100
+f 2015 1876 1698
+f 1853 1884 2014
+f 1831 1698 2165
+f 1316 273 81
+f 1901 1920 1929
+f 1929 1920 1938
+f 1920 1968 1967
+f 1938 1920 1967
+f 1849 2174 1700
+f 2173 1700 2174
+f 2062 2072 2091
+f 803 2467 2059
+f 2239 1736 2240
+f 1505 1357 1685
+f 1358 1686 1476
+f 1967 1968 1788
+f 1968 1969 1788
+f 2065 2110 2156
+f 2065 1214 2110
+f 2110 1214 503
+f 273 2093 1018
+f 273 1983 2093
+f 532 1886 2155
+f 2034 2021 1947
+f 216 1810 585
+f 1912 543 2014
+f 1390 2051 1537
+f 1872 1873 1910
+f 1984 2045 1214
+f 597 1912 1886
+f 1593 2146 2100
+f 2071 2062 2090
+f 2034 2046 1982
+f 2034 1947 2046
+f 1214 2045 2116
+f 1873 1887 1910
+f 1887 1901 1910
+f 1562 1447 1106
+f 2163 431 1957
+f 1948 1972 1936
+f 1972 1948 1992
+f 2014 2015 2013
+f 1853 2014 2013
+f 1550 1884 1853
+f 1947 2468 1994
+f 1355 1550 2154
+f 1355 1884 1550
+f 2081 2108 2128
+f 2024 1965 1492
+f 2024 2032 1965
+f 2116 1604 803
+f 1901 1911 1920
+f 1939 1968 1920
+f 1911 1939 1920
+f 872 1626 1666
+f 2062 2091 2120
+f 1819 1927 1759
+f 1021 1674 1780
+f 872 1673 1756
+f 1550 501 2171
+f 1378 1550 2171
+f 2146 2162 2145
+f 1358 482 192
+f 2109 2120 2119
+f 1866 1872 2227
+f 1391 2012 1860
+f 2136 2137 2161
+f 2162 1661 236
+f 1887 1894 1901
+f 1901 1894 1911
+f 505 1707 206
+f 2120 2137 2136
+f 2142 2164 1674
+f 1860 2012 1861
+f 1894 1939 1911
+f 2080 2060 2118
+f 2162 236 508
+f 2164 1815 1742
+f 1018 2093 1537
+f 2154 1378 2161
+f 2041 2098 2491
+f 2043 2042 2032
+f 1108 1018 1537
+f 1465 2094 1808
+f 502 1643 1661
+f 2467 1618 1656
+f 2119 2136 2135
+f 2119 2108 2071
+f 878 1183 1195
+f 2101 1594 1593
+f 2033 2370 2063
+f 2482 2491 2098
+f 1282 2406 1275
+f 2003 1948 1956
+f 2043 2032 2024
+f 2025 2043 2024
+f 2154 1550 1378
+f 1795 2498 1764
+f 2142 1548 2164
+f 2431 2454 2422
+f 1981 2011 1993
+f 2349 2391 2362
+f 502 2162 2146
+f 2025 2024 2360
+f 2129 2120 2091
+f 1732 1985 2007
+f 2171 1308 209
+f 1930 1995 2041
+f 1390 1238 2051
+f 1866 1878 1887
+f 1878 1894 1887
+f 1965 2032 2011
+f 874 2480 2492
+f 2071 2108 2069
+f 1358 1731 482
+f 430 2021 2034
+f 1965 2003 1964
+f 1855 1889 831
+f 1668 1773 2150
+f 1390 2156 1238
+f 898 869 1903
+f 2391 2407 2362
+f 2121 2111 2074
+f 1548 1259 2164
+f 2099 2129 2091
+f 1550 1853 501
+f 1853 1852 501
+f 952 2017 969
+f 2085 2121 2074
+f 2130 2006 1391
+f 2144 1367 543
+f 2100 2146 2099
+f 1545 1319 113
+f 1903 1922 898
+f 1922 1931 898
+f 585 2170 1641
+f 2007 2017 952
+f 2017 2074 969
+f 1558 1753 1813
+f 837 2005 1517
+f 2005 2006 2130
+f 1532 1474 1528
+f 2003 1981 1948
+f 2070 2071 2069
+f 1922 919 1931
+f 2017 2085 2074
+f 2085 2104 2121
+f 2100 2099 2082
+f 2156 2110 2034
+f 505 2474 2004
+f 1903 871 1922
+f 1922 1952 919
+f 919 1952 1985
+f 1985 2001 2007
+f 2001 2036 2017
+f 2007 2001 2017
+f 2017 2036 2085
+f 2036 2047 2085
+f 2047 2075 2085
+f 2075 2104 2085
+f 1948 1993 2023
+f 2400 2422 2407
+f 2011 2070 1993
+f 2033 2043 2025
+f 2012 2015 1698
+f 1876 1338 2165
+f 871 1940 1922
+f 1985 1976 2001
+f 2121 2104 2143
+f 1051 1413 1456
+f 2358 1362 2379
+f 1859 1789 1870
+f 2090 2109 2071
+f 1405 1398 1885
+f 1886 1884 1355
+f 1922 1960 1952
+f 1952 1960 1985
+f 1960 1976 1985
+f 1956 1948 1936
+f 2135 209 2128
+f 2157 1875 1212
+f 2160 2168 2169
+f 1900 1461 1918
+f 2001 2018 2036
+f 2075 2086 2104
+f 2111 2142 2103
+f 1937 1956 1936
+f 2023 2070 2061
+f 2135 2128 2108
+f 2042 2071 2011
+f 2138 413 2383
+f 2033 2072 2043
+f 1922 1940 1960
+f 2070 2069 2061
+f 2069 2108 2061
+f 2108 2119 2135
+f 1855 1904 1889
+f 1889 1904 871
+f 871 1904 1940
+f 1976 2018 2001
+f 2036 2018 2047
+f 2122 2143 2104
+f 216 1642 489
+f 2148 984 2143
+f 1975 1974 1967
+f 2157 1683 1516
+f 1614 1593 1594
+f 2269 2270 2276
+f 1926 2147 29
+f 2082 2091 2072
+f 430 503 2059
+f 1904 1905 1940
+f 1940 1961 1960
+f 1961 1976 1960
+f 2087 2086 2075
+f 2065 2156 1390
+f 1820 1838 1900
+f 534 1308 837
+f 2167 273 1018
+f 831 1850 1855
+f 2019 2037 2018
+f 2018 2037 2047
+f 2037 2075 2047
+f 2086 2095 2104
+f 2095 2122 2104
+f 2122 2148 2143
+f 1926 1213 1995
+f 1405 1885 1761
+f 2006 2013 2012
+f 2211 2233 2216
+f 1855 1890 1904
+f 1904 1895 1905
+f 1905 1932 1940
+f 1961 1977 1976
+f 1976 1986 2018
+f 2484 2476 1518
+f 1870 1411 1859
+f 1548 2142 2111
+f 1904 1890 1895
+f 1895 1932 1905
+f 1940 1932 1961
+f 1976 1977 1986
+f 1986 2008 2018
+f 2018 2008 2019
+f 2087 2075 2037
+f 2087 2095 2086
+f 2094 1391 1860
+f 1852 1853 2006
+f 1853 2013 2006
+f 929 979 850
+f 1855 1874 1890
+f 2008 2028 2019
+f 1993 2070 2023
+f 1705 1799 1998
+f 1491 2147 206
+f 1851 1856 1855
+f 1895 1890 1874
+f 2038 2019 2028
+f 2038 2048 2037
+f 2019 2038 2037
+f 2048 2067 2087
+f 2037 2048 2087
+f 2087 2067 2095
+f 2095 2149 2122
+f 2149 2148 2122
+f 1308 2005 837
+f 209 1308 1387
+f 1601 2102 1927
+f 254 170 201
+f 1800 1403 1763
+f 1510 1346 1740
+f 870 871 1903
+f 1919 1650 1619
+f 2148 1667 1753
+f 1932 1923 1961
+f 1977 1953 1986
+f 2067 2112 2095
+f 2112 2149 2095
+f 2148 2149 1667
+f 2422 2421 2407
+f 1926 2026 1213
+f 1912 2144 543
+f 2128 1387 2153
+f 1733 1510 1740
+f 990 853 2489
+f 503 1214 803
+f 1921 431 2163
+f 2146 2145 2129
+f 2144 1921 2163
+f 1855 1856 1874
+f 1895 1923 1932
+f 1923 1941 1961
+f 1961 1941 1977
+f 2048 2076 2067
+f 2076 2113 2067
+f 2067 2113 2112
+f 1723 1900 1937
+f 1870 1900 1723
+f 1367 2163 1338
+f 520 1346 1510
+f 1698 1831 1861
+f 1984 1919 2045
+f 1895 1891 1923
+f 2008 1986 2028
+f 1948 1981 1993
+f 1883 1346 520
+f 1883 1814 1346
+f 1930 206 2147
+f 2499 2486 1447
+f 1891 1906 1923
+f 1923 1953 1941
+f 1953 1977 1941
+f 1953 1987 1986
+f 2113 2123 2112
+f 2123 2149 2112
+f 1387 1308 1226
+f 1599 1688 1346
+f 2093 1390 1537
+f 2003 2011 1981
+f 1987 2028 1986
+f 2038 2049 2048
+f 2048 2049 2076
+f 1813 1667 2149
+f 2123 1813 2149
+f 1461 1469 1964
+f 1757 1510 1743
+f 505 1930 1999
+f 2223 1784 1789
+f 1532 1522 1651
+f 1906 1913 1923
+f 1913 1943 1923
+f 1943 1942 1923
+f 1923 1942 1953
+f 1942 1987 1953
+f 1308 1852 2005
+f 2053 1814 1883
+f 1733 1740 1541
+f 2154 1886 1355
+f 1503 1528 1474
+f 1874 1879 1895
+f 1895 1879 1891
+f 2076 2124 2113
+f 2113 2124 2123
+f 1896 1891 1879
+f 1891 1896 1906
+f 1942 1962 1987
+f 1962 2009 2028
+f 1987 1962 2028
+f 2009 2038 2028
+f 2109 2119 2071
+f 1918 1956 1937
+f 1851 1864 1856
+f 1896 1897 1906
+f 1906 1897 1913
+f 1943 1962 1942
+f 2049 2077 2076
+f 2124 2125 2123
+f 1930 2147 1926
+f 1902 1894 1878
+f 482 1510 1757
+f 2129 2137 2120
+f 503 803 2059
+f 1847 1857 1851
+f 1851 1857 1864
+f 2039 2038 2009
+f 2038 2039 2049
+f 2076 2077 2124
+f 2150 1813 2123
+f 482 520 1510
+f 1994 1821 2046
+f 2044 2004 1764
+f 1864 1867 1856
+f 1867 1874 1856
+f 1897 1944 1913
+f 1943 1944 1962
+f 2124 2126 2125
+f 2150 2123 2125
+f 2099 2146 2129
+f 2041 1995 2098
+f 1605 1641 2151
+f 1847 1959 1857
+f 1874 1867 1879
+f 1913 1944 1943
+f 1944 1963 1962
+f 2077 2096 2124
+f 2096 2126 2124
+f 2126 2150 2125
+f 941 1650 1919
+f 2135 2136 209
+f 1884 1886 2014
+f 2049 2029 2077
+f 1388 2127 1389
+f 1389 2127 1566
+f 1930 1926 1995
+f 941 1919 1316
+f 2110 503 430
+f 1867 1880 1879
+f 1879 1880 1896
+f 1897 1907 1944
+f 1963 1978 1962
+f 1962 1978 2009
+f 2039 2029 2049
+f 2077 2078 2096
+f 822 823 827
+f 2166 1668 2150
+f 81 941 1316
+f 2204 2216 2203
+f 2011 2071 2070
+f 1880 1892 1896
+f 1892 1907 1897
+f 1896 1892 1897
+f 1907 1914 1944
+f 1978 2010 2009
+f 2010 2039 2009
+f 1688 1740 1346
+f 1789 1820 1870
+f 2130 1391 2094
+f 1944 1945 1963
+f 2029 2078 2077
+f 1767 2150 2126
+f 1767 2166 2150
+f 803 2022 2467
+f 1503 1927 2102
+f 1914 1954 1944
+f 1944 1954 1945
+f 1963 1970 1978
+f 2078 2105 2096
+f 2105 2126 2096
+f 1965 2011 2003
+f 192 1626 1358
+f 2101 1559 1594
+f 1930 2041 1999
+f 1698 1876 2165
+f 1398 1871 891
+f 2165 1338 1681
+f 1970 2010 1978
+f 2010 2030 2029
+f 2039 2010 2029
+f 2030 2055 2078
+f 2029 2030 2078
+f 1849 1848 2175
+f 1871 1862 891
+f 543 2015 2014
+f 1857 1858 1864
+f 1864 1858 1867
+f 1963 1945 1970
+f 2055 2088 2078
+f 2078 2088 2105
+f 2105 2131 2126
+f 2126 2131 1767
+f 2063 2083 2033
+f 2161 2171 209
+f 2032 2042 2011
+f 1813 2150 1773
+f 1914 1908 1954
+f 1970 1979 2010
+f 2088 2131 2105
+f 2015 543 1876
+f 1694 1692 1048
+f 1395 2207 1859
+f 1395 1393 2207
+f 1730 1784 1736
+f 2500 2466 2470
+f 1709 1701 1757
+f 1945 1979 1970
+f 2030 2050 2055
+f 2350 2317 2286
+f 2154 2155 1886
+f 871 860 1889
+f 2161 209 2136
+f 2497 2463 2493
+f 2190 2204 2203
+f 1800 2179 1404
+f 2477 2469 1385
+f 1385 1715 2477
+f 2128 209 1387
+f 1858 1868 1867
+f 1867 1881 1880
+f 1893 1892 1880
+f 1881 1893 1880
+f 1893 1907 1892
+f 1907 1908 1914
+f 1954 1979 1945
+f 1979 1980 2010
+f 2131 2159 1767
+f 1765 93 339
+f 1761 1877 1405
+f 523 1347 515
+f 1541 2157 1738
+f 2144 2163 1367
+f 1380 1389 1566
+f 2317 2392 2316
+f 1994 2498 1801
+f 1867 1868 1881
+f 1980 2050 2030
+f 2010 1980 2030
+f 2050 2089 2055
+f 2055 2089 2088
+f 2088 2114 2131
+f 1538 1651 1659
+f 2145 2155 2129
+f 2140 29 1928
+f 2370 2033 2025
+f 2252 2239 2240
+f 2239 2252 1862
+f 2392 2391 2316
+f 2469 2501 1385
+f 2477 1715 1710
+f 502 1614 1643
+f 2438 1227 2431
+f 1915 1907 1893
+f 1915 1908 1907
+f 1954 1908 1979
+f 1908 1988 1979
+f 1979 1988 1980
+f 2114 2159 2131
+f 2155 2154 2129
+f 508 1966 2144
+f 872 1756 1626
+f 1710 1715 1505
+f 236 1966 508
+f 2272 2284 1398
+f 2325 2355 2319
+f 1548 2121 1779
+f 1532 1528 1522
+f 1980 2056 2050
+f 2050 2056 2089
+f 2013 2015 2012
+f 1964 2003 1956
+f 2006 2012 1391
+f 1565 1927 1503
+f 2244 2243 2226
+f 5 1715 1385
+f 1858 1848 1868
+f 1915 1946 1908
+f 1946 1988 1908
+f 1980 2020 2056
+f 2115 2159 2114
+f 2092 2083 2063
+f 1398 2284 1687
+f 2162 2155 2145
+f 519 2475 2488
+f 2158 5 1385
+f 5 1505 1715
+f 1692 1694 1505
+f 1988 2020 1980
+f 2115 2169 2159
+f 2169 2168 2159
+f 2083 2082 2072
+f 1316 1984 1983
+f 1488 1619 1650
+f 2083 2072 2033
+f 2361 1210 1233
+f 1933 1946 1915
+f 2056 2079 2089
+f 2088 2115 2114
+f 2099 2091 2082
+f 2162 532 2155
+f 1852 2006 2005
+f 2023 2061 2052
+f 2176 2184 2175
+f 2162 985 532
+f 1909 1893 1881
+f 1909 1915 1893
+f 1988 2040 2020
+f 2040 2056 2020
+f 2089 2079 2088
+f 2088 2079 2115
+f 1782 1444 1882
+f 1216 1215 2320
+f 867 1939 1894
+f 867 903 1939
+f 1372 2398 1379
+f 1863 504 2027
+f 2158 1385 504
+f 1868 1782 1881
+f 1909 1933 1915
+f 2040 1988 1946
+f 1481 2024 1492
+f 2120 2136 2119
+f 1522 1528 1518
+f 1871 1398 1405
+f 1221 1408 1399
+f 1357 5 2158
+f 2179 1800 1763
+f 1868 1865 1782
+f 1882 1881 1782
+f 1882 1909 1881
+f 2040 2057 2056
+f 2106 2079 2056
+f 2057 2106 2056
+f 2106 2132 2079
+f 2132 2115 2079
+f 2115 2132 2169
+f 532 985 597
+f 2092 2100 2082
+f 1210 1221 1399
+f 1399 1233 1210
+f 2130 2002 1517
+f 1849 1865 1868
+f 1933 2040 1946
+f 52 1269 30
+f 1667 1813 1753
+f 1997 1380 1673
+f 940 1008 1088
+f 1947 1994 2046
+f 1882 1916 1909
+f 1924 1933 1909
+f 1533 2040 1933
+f 1533 1534 2040
+f 2058 2040 1534
+f 2058 2057 2040
+f 1238 191 1768
+f 1997 1389 1380
+f 1875 1541 1554
+f 1854 504 1863
+f 1854 2158 504
+f 2396 1275 2406
+f 2426 2443 153
+f 1916 1924 1909
+f 1925 1935 1934
+f 1870 1723 1426
+f 2058 2097 2057
+f 2097 2106 2057
+f 2132 2151 2169
+f 2151 2160 2169
+f 1106 1635 1562
+f 1957 1768 1681
+f 1957 2051 1768
+f 526 535 33
+f 1614 1594 1609
+f 2233 2229 2216
+f 2496 2027 2084
+f 2496 1863 2027
+f 2117 1854 1863
+f 2016 2158 1854
+f 2016 1504 1357
+f 2158 2016 1357
+f 1114 236 1661
+f 2129 2154 2137
+f 2133 2106 2097
+f 2491 1999 2041
+f 2051 1238 1768
+f 2061 2108 2081
+f 2189 2195 2186
+f 2348 2349 2362
+f 1701 192 482
+f 505 1737 1707
+f 2133 2132 2106
+f 2132 2133 2151
+f 2151 2170 2160
+f 502 1661 2162
+f 1998 1389 1997
+f 2297 2352 2329
+f 2352 2364 2329
+f 2394 2414 2364
+f 2352 2394 2364
+f 2402 512 2415
+f 2255 2254 2243
+f 2446 1365 2456
+f 2271 2282 2298
+f 846 2283 2264
+f 2293 2310 2318
+f 2254 2295 2294
+f 2283 2290 2278
+f 2270 2294 2293
+f 2423 2455 2400
+f 2281 2287 2267
+f 2190 2191 2204
+f 2271 2263 2282
+f 2334 2329 2364
+f 2424 2432 2409
+f 2282 2263 2298
+f 1409 1659 1958
+f 2263 2302 2298
+f 2297 2329 2296
+f 1256 446 2346
+f 1958 2502 2478
+f 2437 2399 2444
+f 263 2366 2359
+f 849 827 823
+f 2311 2325 2290
+f 2499 2379 2434
+f 2446 2456 2423
+f 947 2358 2379
+f 2499 947 2379
+f 2205 2195 2212
+f 2245 2237 2227
+f 2245 2256 2237
+f 2256 2263 2271
+f 556 571 2305
+f 1528 2068 1518
+f 2424 2439 2432
+f 2302 2352 2297
+f 1866 2237 826
+f 2248 2242 2211
+f 2334 2364 2363
+f 2235 2244 2226
+f 2255 2295 2254
+f 2329 2324 2296
+f 2439 2447 1973
+f 2329 2334 2324
+f 2409 2432 2414
+f 2293 2318 2276
+f 866 2425 2416
+f 1487 1493 2372
+f 2237 2231 2230
+f 2415 512 17
+f 2035 1236 26
+f 921 2138 688
+f 2491 2482 2462
+f 6 181 197
+f 2481 948 1795
+f 2138 2383 2382
+f 2377 2394 2352
+f 2377 506 2394
+f 2394 506 2402
+f 2401 2402 2415
+f 2394 2402 2401
+f 2318 2326 2276
+f 2439 2457 2432
+f 2298 2302 2297
+f 2244 2249 2243
+f 2404 1100 2382
+f 2238 2245 2227
+f 2245 2257 2256
+f 2257 2263 2256
+f 2324 2334 2328
+f 2257 2289 2263
+f 2289 2302 2263
+f 2236 2231 2250
+f 2138 2382 688
+f 2383 2404 2382
+f 1100 2404 2343
+f 2353 2352 2302
+f 2353 2377 2352
+f 2237 2230 2220
+f 2335 2355 2325
+f 2308 2340 2315
+f 2253 2269 2276
+f 2311 2335 2325
+f 2439 2424 511
+f 2268 2267 2248
+f 2383 413 2404
+f 123 971 832
+f 2234 2243 2269
+f 2225 2213 2234
+f 2219 2213 2225
+f 2195 2196 2212
+f 1544 2418 1549
+f 413 866 2404
+f 2404 866 2416
+f 2416 2417 2404
+f 2404 2417 2343
+f 2415 2409 2401
+f 2196 2219 2212
+f 2268 2248 2218
+f 2206 2214 2197
+f 2417 2332 2343
+f 2343 2332 832
+f 2330 2302 2289
+f 2330 2353 2302
+f 2453 2454 515
+f 2218 2248 2217
+f 2218 2217 2205
+f 2276 2281 2268
+f 2178 2197 2177
+f 2197 2189 2177
+f 2332 2066 832
+f 832 2066 123
+f 2231 2236 2230
+f 669 950 1144
+f 2217 2211 2199
+f 1216 1209 1217
+f 2066 2365 123
+f 2230 2226 2214
+f 2290 2325 2304
+f 2325 2319 2304
+f 2217 2248 2211
+f 2191 2192 2199
+f 510 525 2035
+f 2417 1917 2332
+f 2332 1917 2066
+f 2408 2413 2341
+f 2248 2267 2242
+f 2326 2333 2281
+f 1340 2365 2066
+f 2440 1302 1340
+f 2226 2230 2235
+f 1153 1163 1116
+f 2431 2455 2438
+f 2416 2425 2417
+f 2495 2474 2462
+f 2290 2304 2277
+f 825 2227 1872
+f 151 239 1038
+f 9 151 1038
+f 545 928 2381
+f 2440 2406 1384
+f 928 1596 2381
+f 2186 2188 2185
+f 2456 26 1888
+f 2287 2333 2262
+f 2425 2342 2417
+f 2342 1917 2417
+f 1917 877 2066
+f 2336 1340 2066
+f 2336 2440 1340
+f 2328 2351 2327
+f 825 2238 2227
+f 2351 2368 2327
+f 1222 2388 1211
+f 678 756 734
+f 428 263 1343
+f 2188 2191 2190
+f 2341 2376 2333
+f 2066 877 2336
+f 2290 2277 2278
+f 739 634 592
+f 675 304 14
+f 2384 675 14
+f 2199 2211 2204
+f 2191 2199 2204
+f 2322 2318 2310
+f 2287 2262 2233
+f 2185 2188 2184
+f 2386 2425 845
+f 2384 572 675
+f 1128 123 2365
+f 832 971 2343
+f 2188 2186 2191
+f 2185 2184 2176
+f 2345 1917 2342
+f 2345 877 1917
+f 2336 2406 2440
+f 971 1100 2343
+f 2299 2289 2257
+f 2299 2303 2289
+f 2249 2255 2243
+f 506 513 512
+f 2437 955 1219
+f 1587 2398 1324
+f 877 2396 2336
+f 2336 2396 2406
+f 2463 2479 879
+f 2376 2412 2350
+f 2281 2267 2268
+f 2303 2330 2289
+f 624 635 159
+f 1996 2356 1561
+f 2449 2436 1996
+f 2356 2054 2451
+f 928 2398 1587
+f 2333 2350 2262
+f 2035 26 2456
+f 2346 2342 2425
+f 2346 2345 2342
+f 1544 2380 2418
+f 2412 2392 2350
+f 622 509 1151
+f 2436 2054 1996
+f 545 2451 928
+f 2326 2341 2333
+f 2346 2425 2386
+f 1365 2035 2456
+f 2369 2377 2353
+f 2369 506 2377
+f 2451 900 928
+f 900 2398 928
+f 1235 1888 1244
+f 2337 2345 2346
+f 877 772 2396
+f 772 1275 2396
+f 2432 2446 2414
+f 2294 2295 2310
+f 2369 2330 828
+f 2418 2419 2436
+f 2450 2429 2436
+f 2436 2429 2054
+f 2490 2494 1656
+f 1321 155 2338
+f 1256 2346 2386
+f 2448 877 2345
+f 877 2448 772
+f 2446 2423 2414
+f 2351 2334 2363
+f 2243 2254 2269
+f 2380 2419 2418
+f 2419 2450 2436
+f 2283 2278 2264
+f 822 2197 823
+f 1008 1759 1565
+f 2448 2345 2337
+f 2270 2293 2276
+f 2323 2324 2328
+f 2429 1012 2054
+f 2226 2243 2213
+f 2395 325 772
+f 2370 2367 2380
+f 2054 2435 2451
+f 2435 2397 2451
+f 2451 2397 900
+f 1774 1974 1975
+f 2305 2290 2283
+f 846 2305 2283
+f 2320 1215 2285
+f 2139 2448 2337
+f 2448 2395 772
+f 1232 1231 1216
+f 2272 2285 2284
+f 2367 2371 2380
+f 2371 2405 2380
+f 2380 2405 2419
+f 2419 2429 2450
+f 2429 176 1012
+f 2397 2373 900
+f 2373 2398 900
+f 2373 1379 2398
+f 2372 1500 1508
+f 1133 1303 1142
+f 2252 2273 2272
+f 891 2252 2272
+f 2419 2405 2429
+f 2405 2430 2429
+f 2429 2430 176
+f 2189 2186 2181
+f 2212 2219 2218
+f 2312 2139 2337
+f 2139 2384 2448
+f 2448 2384 2395
+f 899 855 843
+f 2272 2273 2285
+f 2331 2303 2299
+f 176 2435 2054
+f 1012 176 2054
+f 2177 2185 2176
+f 2218 2219 2225
+f 1216 1220 1215
+f 2378 2139 2312
+f 2384 14 2395
+f 2324 2295 2255
+f 2240 2273 2252
+f 2371 2387 2405
+f 2410 2430 2405
+f 2430 2442 176
+f 2435 2344 2397
+f 2397 2344 2373
+f 2456 1888 2455
+f 2242 2267 2233
+f 2233 2262 2229
+f 2378 2384 2139
+f 2323 2310 2295
+f 2323 2322 2310
+f 2240 2274 2273
+f 974 841 990
+f 2490 1447 2486
+f 2387 2410 2405
+f 2442 2141 176
+f 2344 1778 2373
+f 972 1379 2373
+f 1778 972 2373
+f 1379 972 428
+f 1211 2437 1223
+f 1228 1215 1220
+f 702 2378 2312
+f 17 518 2415
+f 1888 26 1244
+f 2324 2323 2295
+f 2305 2311 2290
+f 2307 2285 2273
+f 2274 2307 2273
+f 2307 2320 2285
+f 2369 531 506
+f 2435 2258 2344
+f 2296 2324 2288
+f 1233 1217 2361
+f 2360 2371 2367
+f 2410 2442 2430
+f 176 2141 2258
+f 176 2258 2435
+f 539 2331 66
+f 2350 2392 2317
+f 2268 2225 2253
+f 1508 1500 2371
+f 2360 1508 2371
+f 2371 1500 2387
+f 972 2366 428
+f 1626 1686 1358
+f 1759 1807 1819
+f 2277 2257 2245
+f 2277 2299 2257
+f 1784 2228 1736
+f 2265 2240 1736
+f 2228 2265 1736
+f 2265 2274 2240
+f 1209 2320 2307
+f 2320 1209 1216
+f 1555 1584 1560
+f 2387 1500 2372
+f 2410 2420 2442
+f 2433 972 1778
+f 2433 2366 972
+f 955 522 1225
+f 2339 2307 2274
+f 2372 1493 2387
+f 2411 2420 2410
+f 2420 954 2442
+f 2442 954 2141
+f 2344 2433 1778
+f 2205 2212 2218
+f 2328 2334 2351
+f 2394 2401 2414
+f 2250 2256 2271
+f 2339 1209 2307
+f 2328 2322 2323
+f 866 845 2425
+f 3 316 893
+f 2387 2411 2410
+f 2441 2141 954
+f 2141 2441 2258
+f 2354 2433 2344
+f 2254 2294 2270
+f 2269 2254 2270
+f 863 2305 846
+f 2441 2354 2258
+f 2258 2354 2344
+f 2319 2355 51
+f 2223 2228 1784
+f 1493 2411 2387
+f 1560 2449 1555
+f 2288 2324 2255
+f 825 2251 2238
+f 2251 2245 2238
+f 1299 84 1312
+f 2246 2265 2228
+f 2313 2274 2265
+f 2313 2339 2274
+f 2251 2277 2245
+f 2319 51 2331
+f 891 1862 2252
+f 2443 954 2420
+f 2443 2441 954
+f 511 2447 2439
+f 2242 2233 2211
+f 188 15 814
+f 2443 2426 2441
+f 2426 2354 2441
+f 2306 2403 2433
+f 2433 2403 2366
+f 539 2303 2331
+f 2246 2228 2223
+f 1030 1819 1807
+f 2354 2306 2433
+f 2413 2412 2376
+f 2438 2455 1888
+f 1848 1857 2176
+f 2207 2208 2223
+f 2208 2246 2223
+f 1209 2339 1217
+f 2339 2361 1217
+f 1221 1210 2388
+f 554 109 78
+f 386 1375 95
+f 2327 2326 2318
+f 2179 2182 1393
+f 2182 2208 1393
+f 1393 2208 2207
+f 2361 2399 2388
+f 2388 2399 1211
+f 2306 2354 2426
+f 2403 2359 2366
+f 2214 2226 2213
+f 2268 2253 2276
+f 889 2200 2179
+f 2200 2182 2179
+f 2200 2221 2182
+f 2221 2208 2182
+f 2314 2265 2246
+f 2314 2313 2265
+f 2339 2374 2361
+f 2478 2434 2379
+f 2205 2217 2199
+f 2208 2259 2246
+f 2259 2275 2246
+f 2314 2321 2313
+f 2313 2347 2339
+f 2347 2374 2339
+f 2374 2399 2361
+f 153 154 2426
+f 154 2306 2426
+f 2385 2359 2403
+f 2221 2259 2208
+f 2306 2357 2403
+f 2357 2385 2403
+f 2237 2256 2231
+f 2172 2180 889
+f 2180 2200 889
+f 2200 2201 2221
+f 2246 2291 2314
+f 2374 2444 2399
+f 571 555 2311
+f 2192 2205 2199
+f 2173 2180 2172
+f 2279 2246 2275
+f 2279 2291 2246
+f 2292 2314 2291
+f 2321 2362 2313
+f 2362 2347 2313
+f 2347 2389 2374
+f 2444 955 2437
+f 2292 2291 2279
+f 2452 2444 2374
+f 2054 2356 1996
+f 2338 2306 154
+f 2186 2192 2191
+f 2193 2201 2200
+f 2259 2221 2201
+f 2247 2259 2201
+f 2452 955 2444
+f 2278 2277 2251
+f 2338 2357 2306
+f 2181 2186 2185
+f 2276 2326 2281
+f 2432 2457 2446
+f 2198 2201 2193
+f 2198 2232 2201
+f 2232 2247 2201
+f 2389 2452 2374
+f 2452 1630 955
+f 1403 1749 1444
+f 1555 1996 1561
+f 2357 2427 2385
+f 2385 2428 230
+f 2409 2415 2424
+f 2304 2331 2299
+f 2193 2200 2180
+f 2445 2452 2389
+f 1565 1759 1927
+f 2380 1544 2370
+f 2338 2427 2357
+f 2427 2428 2385
+f 230 222 253
+f 2202 2198 2193
+f 2202 2209 2198
+f 2209 2241 2198
+f 2241 2232 2198
+f 2266 2275 2259
+f 2365 1340 1128
+f 2415 518 2424
+f 2338 170 2427
+f 170 2428 2427
+f 2181 2185 2177
+f 2196 2195 2189
+f 2183 2193 2180
+f 2453 1630 2452
+f 2197 2214 2189
+f 2401 2409 2414
+f 822 2220 2197
+f 1210 2361 2388
+f 2187 2193 2183
+f 2187 2202 2193
+f 2266 2279 2275
+f 2279 2300 2292
+f 2375 2347 2362
+f 2375 2390 2347
+f 2390 2389 2347
+f 2453 2452 2445
+f 1347 1630 2453
+f 1630 1347 522
+f 2220 2206 2197
+f 2262 2350 2286
+f 170 254 2428
+f 2457 1973 2446
+f 1973 1365 2446
+f 2174 2183 2180
+f 2194 2202 2187
+f 2222 2241 2209
+f 2222 2260 2241
+f 2266 2259 2247
+f 2390 2445 2389
+f 2264 2251 825
+f 2363 2368 2351
+f 2326 2393 2341
+f 1855 1850 1851
+f 2210 2209 2202
+f 2210 2222 2209
+f 2261 2260 2222
+f 2280 2279 2266
+f 2280 2300 2279
+f 251 263 2359
+f 2277 2304 2299
+f 2220 2230 2206
+f 2202 2194 2210
+f 2213 2243 2234
+f 2328 2327 2322
+f 2294 2310 2293
+f 2214 2196 2189
+f 2196 2213 2219
+f 2224 2222 2210
+f 2421 2390 2375
+f 2206 2230 2214
+f 2194 2203 2210
+f 2224 2261 2222
+f 2421 2445 2390
+f 2322 2327 2318
+f 2393 2408 2341
+f 1365 1973 510
+f 2216 2210 2203
+f 2216 2224 2210
+f 2266 2308 2280
+f 2280 2308 2300
+f 2407 2421 2375
+f 2175 2183 2174
+f 2194 2190 2203
+f 2454 2445 2421
+f 522 1347 523
+f 2456 2455 2423
+f 823 2197 2178
+f 2281 2333 2287
+f 2188 2187 2183
+f 2188 2190 2194
+f 2187 2188 2194
+f 2308 2315 2300
+f 2407 2375 2362
+f 2443 2420 2503
+f 2420 2411 2503
+f 2411 1493 2503
+f 1493 1487 2503
+f 1487 1318 2503
+f 1318 1320 2503
+f 1320 2443 2503
diff --git a/demo/dataset/files/cantina.wav b/demo/dataset/files/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/dataset/files/cantina.wav differ
diff --git a/demo/dataset/files/cheetah1.jpg b/demo/dataset/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/dataset/files/cheetah1.jpg differ
diff --git a/demo/dataset/files/time.csv b/demo/dataset/files/time.csv
new file mode 100644
index 0000000000000000000000000000000000000000..ddb2035c4ed0377f54ee1602fff9f05ba5daa2db
--- /dev/null
+++ b/demo/dataset/files/time.csv
@@ -0,0 +1,8 @@
+time,value,price
+1,1,4
+2,3,8
+3,6,12
+4,10,16
+5,15,20
+6,21,24
+7,28,28
\ No newline at end of file
diff --git a/demo/dataset/files/titanic.csv b/demo/dataset/files/titanic.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5cc466e97cf12f155d19b9f717425214075d0b7a
--- /dev/null
+++ b/demo/dataset/files/titanic.csv
@@ -0,0 +1,892 @@
+PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
+1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
+2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
+3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
+4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
+5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
+6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
+7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
+8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
+9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
+10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
+11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
+12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
+13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
+14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S
+15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S
+16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S
+17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q
+18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S
+19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S
+20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C
+21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S
+22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S
+23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q
+24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S
+25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S
+26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S
+27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C
+28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S
+29,1,3,"O'Dwyer, Miss. Ellen ""Nellie""",female,,0,0,330959,7.8792,,Q
+30,0,3,"Todoroff, Mr. Lalio",male,,0,0,349216,7.8958,,S
+31,0,1,"Uruchurtu, Don. Manuel E",male,40,0,0,PC 17601,27.7208,,C
+32,1,1,"Spencer, Mrs. William Augustus (Marie Eugenie)",female,,1,0,PC 17569,146.5208,B78,C
+33,1,3,"Glynn, Miss. Mary Agatha",female,,0,0,335677,7.75,,Q
+34,0,2,"Wheadon, Mr. Edward H",male,66,0,0,C.A. 24579,10.5,,S
+35,0,1,"Meyer, Mr. Edgar Joseph",male,28,1,0,PC 17604,82.1708,,C
+36,0,1,"Holverson, Mr. Alexander Oskar",male,42,1,0,113789,52,,S
+37,1,3,"Mamee, Mr. Hanna",male,,0,0,2677,7.2292,,C
+38,0,3,"Cann, Mr. Ernest Charles",male,21,0,0,A./5. 2152,8.05,,S
+39,0,3,"Vander Planke, Miss. Augusta Maria",female,18,2,0,345764,18,,S
+40,1,3,"Nicola-Yarred, Miss. Jamila",female,14,1,0,2651,11.2417,,C
+41,0,3,"Ahlin, Mrs. Johan (Johanna Persdotter Larsson)",female,40,1,0,7546,9.475,,S
+42,0,2,"Turpin, Mrs. William John Robert (Dorothy Ann Wonnacott)",female,27,1,0,11668,21,,S
+43,0,3,"Kraeff, Mr. Theodor",male,,0,0,349253,7.8958,,C
+44,1,2,"Laroche, Miss. Simonne Marie Anne Andree",female,3,1,2,SC/Paris 2123,41.5792,,C
+45,1,3,"Devaney, Miss. Margaret Delia",female,19,0,0,330958,7.8792,,Q
+46,0,3,"Rogers, Mr. William John",male,,0,0,S.C./A.4. 23567,8.05,,S
+47,0,3,"Lennon, Mr. Denis",male,,1,0,370371,15.5,,Q
+48,1,3,"O'Driscoll, Miss. Bridget",female,,0,0,14311,7.75,,Q
+49,0,3,"Samaan, Mr. Youssef",male,,2,0,2662,21.6792,,C
+50,0,3,"Arnold-Franchi, Mrs. Josef (Josefine Franchi)",female,18,1,0,349237,17.8,,S
+51,0,3,"Panula, Master. Juha Niilo",male,7,4,1,3101295,39.6875,,S
+52,0,3,"Nosworthy, Mr. Richard Cater",male,21,0,0,A/4. 39886,7.8,,S
+53,1,1,"Harper, Mrs. Henry Sleeper (Myna Haxtun)",female,49,1,0,PC 17572,76.7292,D33,C
+54,1,2,"Faunthorpe, Mrs. Lizzie (Elizabeth Anne Wilkinson)",female,29,1,0,2926,26,,S
+55,0,1,"Ostby, Mr. Engelhart Cornelius",male,65,0,1,113509,61.9792,B30,C
+56,1,1,"Woolner, Mr. Hugh",male,,0,0,19947,35.5,C52,S
+57,1,2,"Rugg, Miss. Emily",female,21,0,0,C.A. 31026,10.5,,S
+58,0,3,"Novel, Mr. Mansouer",male,28.5,0,0,2697,7.2292,,C
+59,1,2,"West, Miss. Constance Mirium",female,5,1,2,C.A. 34651,27.75,,S
+60,0,3,"Goodwin, Master. William Frederick",male,11,5,2,CA 2144,46.9,,S
+61,0,3,"Sirayanian, Mr. Orsen",male,22,0,0,2669,7.2292,,C
+62,1,1,"Icard, Miss. Amelie",female,38,0,0,113572,80,B28,
+63,0,1,"Harris, Mr. Henry Birkhardt",male,45,1,0,36973,83.475,C83,S
+64,0,3,"Skoog, Master. Harald",male,4,3,2,347088,27.9,,S
+65,0,1,"Stewart, Mr. Albert A",male,,0,0,PC 17605,27.7208,,C
+66,1,3,"Moubarek, Master. Gerios",male,,1,1,2661,15.2458,,C
+67,1,2,"Nye, Mrs. (Elizabeth Ramell)",female,29,0,0,C.A. 29395,10.5,F33,S
+68,0,3,"Crease, Mr. Ernest James",male,19,0,0,S.P. 3464,8.1583,,S
+69,1,3,"Andersson, Miss. Erna Alexandra",female,17,4,2,3101281,7.925,,S
+70,0,3,"Kink, Mr. Vincenz",male,26,2,0,315151,8.6625,,S
+71,0,2,"Jenkin, Mr. Stephen Curnow",male,32,0,0,C.A. 33111,10.5,,S
+72,0,3,"Goodwin, Miss. Lillian Amy",female,16,5,2,CA 2144,46.9,,S
+73,0,2,"Hood, Mr. Ambrose Jr",male,21,0,0,S.O.C. 14879,73.5,,S
+74,0,3,"Chronopoulos, Mr. Apostolos",male,26,1,0,2680,14.4542,,C
+75,1,3,"Bing, Mr. Lee",male,32,0,0,1601,56.4958,,S
+76,0,3,"Moen, Mr. Sigurd Hansen",male,25,0,0,348123,7.65,F G73,S
+77,0,3,"Staneff, Mr. Ivan",male,,0,0,349208,7.8958,,S
+78,0,3,"Moutal, Mr. Rahamin Haim",male,,0,0,374746,8.05,,S
+79,1,2,"Caldwell, Master. Alden Gates",male,0.83,0,2,248738,29,,S
+80,1,3,"Dowdell, Miss. Elizabeth",female,30,0,0,364516,12.475,,S
+81,0,3,"Waelens, Mr. Achille",male,22,0,0,345767,9,,S
+82,1,3,"Sheerlinck, Mr. Jan Baptist",male,29,0,0,345779,9.5,,S
+83,1,3,"McDermott, Miss. Brigdet Delia",female,,0,0,330932,7.7875,,Q
+84,0,1,"Carrau, Mr. Francisco M",male,28,0,0,113059,47.1,,S
+85,1,2,"Ilett, Miss. Bertha",female,17,0,0,SO/C 14885,10.5,,S
+86,1,3,"Backstrom, Mrs. Karl Alfred (Maria Mathilda Gustafsson)",female,33,3,0,3101278,15.85,,S
+87,0,3,"Ford, Mr. William Neal",male,16,1,3,W./C. 6608,34.375,,S
+88,0,3,"Slocovski, Mr. Selman Francis",male,,0,0,SOTON/OQ 392086,8.05,,S
+89,1,1,"Fortune, Miss. Mabel Helen",female,23,3,2,19950,263,C23 C25 C27,S
+90,0,3,"Celotti, Mr. Francesco",male,24,0,0,343275,8.05,,S
+91,0,3,"Christmann, Mr. Emil",male,29,0,0,343276,8.05,,S
+92,0,3,"Andreasson, Mr. Paul Edvin",male,20,0,0,347466,7.8542,,S
+93,0,1,"Chaffee, Mr. Herbert Fuller",male,46,1,0,W.E.P. 5734,61.175,E31,S
+94,0,3,"Dean, Mr. Bertram Frank",male,26,1,2,C.A. 2315,20.575,,S
+95,0,3,"Coxon, Mr. Daniel",male,59,0,0,364500,7.25,,S
+96,0,3,"Shorney, Mr. Charles Joseph",male,,0,0,374910,8.05,,S
+97,0,1,"Goldschmidt, Mr. George B",male,71,0,0,PC 17754,34.6542,A5,C
+98,1,1,"Greenfield, Mr. William Bertram",male,23,0,1,PC 17759,63.3583,D10 D12,C
+99,1,2,"Doling, Mrs. John T (Ada Julia Bone)",female,34,0,1,231919,23,,S
+100,0,2,"Kantor, Mr. Sinai",male,34,1,0,244367,26,,S
+101,0,3,"Petranec, Miss. Matilda",female,28,0,0,349245,7.8958,,S
+102,0,3,"Petroff, Mr. Pastcho (""Pentcho"")",male,,0,0,349215,7.8958,,S
+103,0,1,"White, Mr. Richard Frasar",male,21,0,1,35281,77.2875,D26,S
+104,0,3,"Johansson, Mr. Gustaf Joel",male,33,0,0,7540,8.6542,,S
+105,0,3,"Gustafsson, Mr. Anders Vilhelm",male,37,2,0,3101276,7.925,,S
+106,0,3,"Mionoff, Mr. Stoytcho",male,28,0,0,349207,7.8958,,S
+107,1,3,"Salkjelsvik, Miss. Anna Kristine",female,21,0,0,343120,7.65,,S
+108,1,3,"Moss, Mr. Albert Johan",male,,0,0,312991,7.775,,S
+109,0,3,"Rekic, Mr. Tido",male,38,0,0,349249,7.8958,,S
+110,1,3,"Moran, Miss. Bertha",female,,1,0,371110,24.15,,Q
+111,0,1,"Porter, Mr. Walter Chamberlain",male,47,0,0,110465,52,C110,S
+112,0,3,"Zabour, Miss. Hileni",female,14.5,1,0,2665,14.4542,,C
+113,0,3,"Barton, Mr. David John",male,22,0,0,324669,8.05,,S
+114,0,3,"Jussila, Miss. Katriina",female,20,1,0,4136,9.825,,S
+115,0,3,"Attalah, Miss. Malake",female,17,0,0,2627,14.4583,,C
+116,0,3,"Pekoniemi, Mr. Edvard",male,21,0,0,STON/O 2. 3101294,7.925,,S
+117,0,3,"Connors, Mr. Patrick",male,70.5,0,0,370369,7.75,,Q
+118,0,2,"Turpin, Mr. William John Robert",male,29,1,0,11668,21,,S
+119,0,1,"Baxter, Mr. Quigg Edmond",male,24,0,1,PC 17558,247.5208,B58 B60,C
+120,0,3,"Andersson, Miss. Ellis Anna Maria",female,2,4,2,347082,31.275,,S
+121,0,2,"Hickman, Mr. Stanley George",male,21,2,0,S.O.C. 14879,73.5,,S
+122,0,3,"Moore, Mr. Leonard Charles",male,,0,0,A4. 54510,8.05,,S
+123,0,2,"Nasser, Mr. Nicholas",male,32.5,1,0,237736,30.0708,,C
+124,1,2,"Webber, Miss. Susan",female,32.5,0,0,27267,13,E101,S
+125,0,1,"White, Mr. Percival Wayland",male,54,0,1,35281,77.2875,D26,S
+126,1,3,"Nicola-Yarred, Master. Elias",male,12,1,0,2651,11.2417,,C
+127,0,3,"McMahon, Mr. Martin",male,,0,0,370372,7.75,,Q
+128,1,3,"Madsen, Mr. Fridtjof Arne",male,24,0,0,C 17369,7.1417,,S
+129,1,3,"Peter, Miss. Anna",female,,1,1,2668,22.3583,F E69,C
+130,0,3,"Ekstrom, Mr. Johan",male,45,0,0,347061,6.975,,S
+131,0,3,"Drazenoic, Mr. Jozef",male,33,0,0,349241,7.8958,,C
+132,0,3,"Coelho, Mr. Domingos Fernandeo",male,20,0,0,SOTON/O.Q. 3101307,7.05,,S
+133,0,3,"Robins, Mrs. Alexander A (Grace Charity Laury)",female,47,1,0,A/5. 3337,14.5,,S
+134,1,2,"Weisz, Mrs. Leopold (Mathilde Francoise Pede)",female,29,1,0,228414,26,,S
+135,0,2,"Sobey, Mr. Samuel James Hayden",male,25,0,0,C.A. 29178,13,,S
+136,0,2,"Richard, Mr. Emile",male,23,0,0,SC/PARIS 2133,15.0458,,C
+137,1,1,"Newsom, Miss. Helen Monypeny",female,19,0,2,11752,26.2833,D47,S
+138,0,1,"Futrelle, Mr. Jacques Heath",male,37,1,0,113803,53.1,C123,S
+139,0,3,"Osen, Mr. Olaf Elon",male,16,0,0,7534,9.2167,,S
+140,0,1,"Giglio, Mr. Victor",male,24,0,0,PC 17593,79.2,B86,C
+141,0,3,"Boulos, Mrs. Joseph (Sultana)",female,,0,2,2678,15.2458,,C
+142,1,3,"Nysten, Miss. Anna Sofia",female,22,0,0,347081,7.75,,S
+143,1,3,"Hakkarainen, Mrs. Pekka Pietari (Elin Matilda Dolck)",female,24,1,0,STON/O2. 3101279,15.85,,S
+144,0,3,"Burke, Mr. Jeremiah",male,19,0,0,365222,6.75,,Q
+145,0,2,"Andrew, Mr. Edgardo Samuel",male,18,0,0,231945,11.5,,S
+146,0,2,"Nicholls, Mr. Joseph Charles",male,19,1,1,C.A. 33112,36.75,,S
+147,1,3,"Andersson, Mr. August Edvard (""Wennerstrom"")",male,27,0,0,350043,7.7958,,S
+148,0,3,"Ford, Miss. Robina Maggie ""Ruby""",female,9,2,2,W./C. 6608,34.375,,S
+149,0,2,"Navratil, Mr. Michel (""Louis M Hoffman"")",male,36.5,0,2,230080,26,F2,S
+150,0,2,"Byles, Rev. Thomas Roussel Davids",male,42,0,0,244310,13,,S
+151,0,2,"Bateman, Rev. Robert James",male,51,0,0,S.O.P. 1166,12.525,,S
+152,1,1,"Pears, Mrs. Thomas (Edith Wearne)",female,22,1,0,113776,66.6,C2,S
+153,0,3,"Meo, Mr. Alfonzo",male,55.5,0,0,A.5. 11206,8.05,,S
+154,0,3,"van Billiard, Mr. Austin Blyler",male,40.5,0,2,A/5. 851,14.5,,S
+155,0,3,"Olsen, Mr. Ole Martin",male,,0,0,Fa 265302,7.3125,,S
+156,0,1,"Williams, Mr. Charles Duane",male,51,0,1,PC 17597,61.3792,,C
+157,1,3,"Gilnagh, Miss. Katherine ""Katie""",female,16,0,0,35851,7.7333,,Q
+158,0,3,"Corn, Mr. Harry",male,30,0,0,SOTON/OQ 392090,8.05,,S
+159,0,3,"Smiljanic, Mr. Mile",male,,0,0,315037,8.6625,,S
+160,0,3,"Sage, Master. Thomas Henry",male,,8,2,CA. 2343,69.55,,S
+161,0,3,"Cribb, Mr. John Hatfield",male,44,0,1,371362,16.1,,S
+162,1,2,"Watt, Mrs. James (Elizabeth ""Bessie"" Inglis Milne)",female,40,0,0,C.A. 33595,15.75,,S
+163,0,3,"Bengtsson, Mr. John Viktor",male,26,0,0,347068,7.775,,S
+164,0,3,"Calic, Mr. Jovo",male,17,0,0,315093,8.6625,,S
+165,0,3,"Panula, Master. Eino Viljami",male,1,4,1,3101295,39.6875,,S
+166,1,3,"Goldsmith, Master. Frank John William ""Frankie""",male,9,0,2,363291,20.525,,S
+167,1,1,"Chibnall, Mrs. (Edith Martha Bowerman)",female,,0,1,113505,55,E33,S
+168,0,3,"Skoog, Mrs. William (Anna Bernhardina Karlsson)",female,45,1,4,347088,27.9,,S
+169,0,1,"Baumann, Mr. John D",male,,0,0,PC 17318,25.925,,S
+170,0,3,"Ling, Mr. Lee",male,28,0,0,1601,56.4958,,S
+171,0,1,"Van der hoef, Mr. Wyckoff",male,61,0,0,111240,33.5,B19,S
+172,0,3,"Rice, Master. Arthur",male,4,4,1,382652,29.125,,Q
+173,1,3,"Johnson, Miss. Eleanor Ileen",female,1,1,1,347742,11.1333,,S
+174,0,3,"Sivola, Mr. Antti Wilhelm",male,21,0,0,STON/O 2. 3101280,7.925,,S
+175,0,1,"Smith, Mr. James Clinch",male,56,0,0,17764,30.6958,A7,C
+176,0,3,"Klasen, Mr. Klas Albin",male,18,1,1,350404,7.8542,,S
+177,0,3,"Lefebre, Master. Henry Forbes",male,,3,1,4133,25.4667,,S
+178,0,1,"Isham, Miss. Ann Elizabeth",female,50,0,0,PC 17595,28.7125,C49,C
+179,0,2,"Hale, Mr. Reginald",male,30,0,0,250653,13,,S
+180,0,3,"Leonard, Mr. Lionel",male,36,0,0,LINE,0,,S
+181,0,3,"Sage, Miss. Constance Gladys",female,,8,2,CA. 2343,69.55,,S
+182,0,2,"Pernot, Mr. Rene",male,,0,0,SC/PARIS 2131,15.05,,C
+183,0,3,"Asplund, Master. Clarence Gustaf Hugo",male,9,4,2,347077,31.3875,,S
+184,1,2,"Becker, Master. Richard F",male,1,2,1,230136,39,F4,S
+185,1,3,"Kink-Heilmann, Miss. Luise Gretchen",female,4,0,2,315153,22.025,,S
+186,0,1,"Rood, Mr. Hugh Roscoe",male,,0,0,113767,50,A32,S
+187,1,3,"O'Brien, Mrs. Thomas (Johanna ""Hannah"" Godfrey)",female,,1,0,370365,15.5,,Q
+188,1,1,"Romaine, Mr. Charles Hallace (""Mr C Rolmane"")",male,45,0,0,111428,26.55,,S
+189,0,3,"Bourke, Mr. John",male,40,1,1,364849,15.5,,Q
+190,0,3,"Turcin, Mr. Stjepan",male,36,0,0,349247,7.8958,,S
+191,1,2,"Pinsky, Mrs. (Rosa)",female,32,0,0,234604,13,,S
+192,0,2,"Carbines, Mr. William",male,19,0,0,28424,13,,S
+193,1,3,"Andersen-Jensen, Miss. Carla Christine Nielsine",female,19,1,0,350046,7.8542,,S
+194,1,2,"Navratil, Master. Michel M",male,3,1,1,230080,26,F2,S
+195,1,1,"Brown, Mrs. James Joseph (Margaret Tobin)",female,44,0,0,PC 17610,27.7208,B4,C
+196,1,1,"Lurette, Miss. Elise",female,58,0,0,PC 17569,146.5208,B80,C
+197,0,3,"Mernagh, Mr. Robert",male,,0,0,368703,7.75,,Q
+198,0,3,"Olsen, Mr. Karl Siegwart Andreas",male,42,0,1,4579,8.4042,,S
+199,1,3,"Madigan, Miss. Margaret ""Maggie""",female,,0,0,370370,7.75,,Q
+200,0,2,"Yrois, Miss. Henriette (""Mrs Harbeck"")",female,24,0,0,248747,13,,S
+201,0,3,"Vande Walle, Mr. Nestor Cyriel",male,28,0,0,345770,9.5,,S
+202,0,3,"Sage, Mr. Frederick",male,,8,2,CA. 2343,69.55,,S
+203,0,3,"Johanson, Mr. Jakob Alfred",male,34,0,0,3101264,6.4958,,S
+204,0,3,"Youseff, Mr. Gerious",male,45.5,0,0,2628,7.225,,C
+205,1,3,"Cohen, Mr. Gurshon ""Gus""",male,18,0,0,A/5 3540,8.05,,S
+206,0,3,"Strom, Miss. Telma Matilda",female,2,0,1,347054,10.4625,G6,S
+207,0,3,"Backstrom, Mr. Karl Alfred",male,32,1,0,3101278,15.85,,S
+208,1,3,"Albimona, Mr. Nassef Cassem",male,26,0,0,2699,18.7875,,C
+209,1,3,"Carr, Miss. Helen ""Ellen""",female,16,0,0,367231,7.75,,Q
+210,1,1,"Blank, Mr. Henry",male,40,0,0,112277,31,A31,C
+211,0,3,"Ali, Mr. Ahmed",male,24,0,0,SOTON/O.Q. 3101311,7.05,,S
+212,1,2,"Cameron, Miss. Clear Annie",female,35,0,0,F.C.C. 13528,21,,S
+213,0,3,"Perkin, Mr. John Henry",male,22,0,0,A/5 21174,7.25,,S
+214,0,2,"Givard, Mr. Hans Kristensen",male,30,0,0,250646,13,,S
+215,0,3,"Kiernan, Mr. Philip",male,,1,0,367229,7.75,,Q
+216,1,1,"Newell, Miss. Madeleine",female,31,1,0,35273,113.275,D36,C
+217,1,3,"Honkanen, Miss. Eliina",female,27,0,0,STON/O2. 3101283,7.925,,S
+218,0,2,"Jacobsohn, Mr. Sidney Samuel",male,42,1,0,243847,27,,S
+219,1,1,"Bazzani, Miss. Albina",female,32,0,0,11813,76.2917,D15,C
+220,0,2,"Harris, Mr. Walter",male,30,0,0,W/C 14208,10.5,,S
+221,1,3,"Sunderland, Mr. Victor Francis",male,16,0,0,SOTON/OQ 392089,8.05,,S
+222,0,2,"Bracken, Mr. James H",male,27,0,0,220367,13,,S
+223,0,3,"Green, Mr. George Henry",male,51,0,0,21440,8.05,,S
+224,0,3,"Nenkoff, Mr. Christo",male,,0,0,349234,7.8958,,S
+225,1,1,"Hoyt, Mr. Frederick Maxfield",male,38,1,0,19943,90,C93,S
+226,0,3,"Berglund, Mr. Karl Ivar Sven",male,22,0,0,PP 4348,9.35,,S
+227,1,2,"Mellors, Mr. William John",male,19,0,0,SW/PP 751,10.5,,S
+228,0,3,"Lovell, Mr. John Hall (""Henry"")",male,20.5,0,0,A/5 21173,7.25,,S
+229,0,2,"Fahlstrom, Mr. Arne Jonas",male,18,0,0,236171,13,,S
+230,0,3,"Lefebre, Miss. Mathilde",female,,3,1,4133,25.4667,,S
+231,1,1,"Harris, Mrs. Henry Birkhardt (Irene Wallach)",female,35,1,0,36973,83.475,C83,S
+232,0,3,"Larsson, Mr. Bengt Edvin",male,29,0,0,347067,7.775,,S
+233,0,2,"Sjostedt, Mr. Ernst Adolf",male,59,0,0,237442,13.5,,S
+234,1,3,"Asplund, Miss. Lillian Gertrud",female,5,4,2,347077,31.3875,,S
+235,0,2,"Leyson, Mr. Robert William Norman",male,24,0,0,C.A. 29566,10.5,,S
+236,0,3,"Harknett, Miss. Alice Phoebe",female,,0,0,W./C. 6609,7.55,,S
+237,0,2,"Hold, Mr. Stephen",male,44,1,0,26707,26,,S
+238,1,2,"Collyer, Miss. Marjorie ""Lottie""",female,8,0,2,C.A. 31921,26.25,,S
+239,0,2,"Pengelly, Mr. Frederick William",male,19,0,0,28665,10.5,,S
+240,0,2,"Hunt, Mr. George Henry",male,33,0,0,SCO/W 1585,12.275,,S
+241,0,3,"Zabour, Miss. Thamine",female,,1,0,2665,14.4542,,C
+242,1,3,"Murphy, Miss. Katherine ""Kate""",female,,1,0,367230,15.5,,Q
+243,0,2,"Coleridge, Mr. Reginald Charles",male,29,0,0,W./C. 14263,10.5,,S
+244,0,3,"Maenpaa, Mr. Matti Alexanteri",male,22,0,0,STON/O 2. 3101275,7.125,,S
+245,0,3,"Attalah, Mr. Sleiman",male,30,0,0,2694,7.225,,C
+246,0,1,"Minahan, Dr. William Edward",male,44,2,0,19928,90,C78,Q
+247,0,3,"Lindahl, Miss. Agda Thorilda Viktoria",female,25,0,0,347071,7.775,,S
+248,1,2,"Hamalainen, Mrs. William (Anna)",female,24,0,2,250649,14.5,,S
+249,1,1,"Beckwith, Mr. Richard Leonard",male,37,1,1,11751,52.5542,D35,S
+250,0,2,"Carter, Rev. Ernest Courtenay",male,54,1,0,244252,26,,S
+251,0,3,"Reed, Mr. James George",male,,0,0,362316,7.25,,S
+252,0,3,"Strom, Mrs. Wilhelm (Elna Matilda Persson)",female,29,1,1,347054,10.4625,G6,S
+253,0,1,"Stead, Mr. William Thomas",male,62,0,0,113514,26.55,C87,S
+254,0,3,"Lobb, Mr. William Arthur",male,30,1,0,A/5. 3336,16.1,,S
+255,0,3,"Rosblom, Mrs. Viktor (Helena Wilhelmina)",female,41,0,2,370129,20.2125,,S
+256,1,3,"Touma, Mrs. Darwis (Hanne Youssef Razi)",female,29,0,2,2650,15.2458,,C
+257,1,1,"Thorne, Mrs. Gertrude Maybelle",female,,0,0,PC 17585,79.2,,C
+258,1,1,"Cherry, Miss. Gladys",female,30,0,0,110152,86.5,B77,S
+259,1,1,"Ward, Miss. Anna",female,35,0,0,PC 17755,512.3292,,C
+260,1,2,"Parrish, Mrs. (Lutie Davis)",female,50,0,1,230433,26,,S
+261,0,3,"Smith, Mr. Thomas",male,,0,0,384461,7.75,,Q
+262,1,3,"Asplund, Master. Edvin Rojj Felix",male,3,4,2,347077,31.3875,,S
+263,0,1,"Taussig, Mr. Emil",male,52,1,1,110413,79.65,E67,S
+264,0,1,"Harrison, Mr. William",male,40,0,0,112059,0,B94,S
+265,0,3,"Henry, Miss. Delia",female,,0,0,382649,7.75,,Q
+266,0,2,"Reeves, Mr. David",male,36,0,0,C.A. 17248,10.5,,S
+267,0,3,"Panula, Mr. Ernesti Arvid",male,16,4,1,3101295,39.6875,,S
+268,1,3,"Persson, Mr. Ernst Ulrik",male,25,1,0,347083,7.775,,S
+269,1,1,"Graham, Mrs. William Thompson (Edith Junkins)",female,58,0,1,PC 17582,153.4625,C125,S
+270,1,1,"Bissette, Miss. Amelia",female,35,0,0,PC 17760,135.6333,C99,S
+271,0,1,"Cairns, Mr. Alexander",male,,0,0,113798,31,,S
+272,1,3,"Tornquist, Mr. William Henry",male,25,0,0,LINE,0,,S
+273,1,2,"Mellinger, Mrs. (Elizabeth Anne Maidment)",female,41,0,1,250644,19.5,,S
+274,0,1,"Natsch, Mr. Charles H",male,37,0,1,PC 17596,29.7,C118,C
+275,1,3,"Healy, Miss. Hanora ""Nora""",female,,0,0,370375,7.75,,Q
+276,1,1,"Andrews, Miss. Kornelia Theodosia",female,63,1,0,13502,77.9583,D7,S
+277,0,3,"Lindblom, Miss. Augusta Charlotta",female,45,0,0,347073,7.75,,S
+278,0,2,"Parkes, Mr. Francis ""Frank""",male,,0,0,239853,0,,S
+279,0,3,"Rice, Master. Eric",male,7,4,1,382652,29.125,,Q
+280,1,3,"Abbott, Mrs. Stanton (Rosa Hunt)",female,35,1,1,C.A. 2673,20.25,,S
+281,0,3,"Duane, Mr. Frank",male,65,0,0,336439,7.75,,Q
+282,0,3,"Olsson, Mr. Nils Johan Goransson",male,28,0,0,347464,7.8542,,S
+283,0,3,"de Pelsmaeker, Mr. Alfons",male,16,0,0,345778,9.5,,S
+284,1,3,"Dorking, Mr. Edward Arthur",male,19,0,0,A/5. 10482,8.05,,S
+285,0,1,"Smith, Mr. Richard William",male,,0,0,113056,26,A19,S
+286,0,3,"Stankovic, Mr. Ivan",male,33,0,0,349239,8.6625,,C
+287,1,3,"de Mulder, Mr. Theodore",male,30,0,0,345774,9.5,,S
+288,0,3,"Naidenoff, Mr. Penko",male,22,0,0,349206,7.8958,,S
+289,1,2,"Hosono, Mr. Masabumi",male,42,0,0,237798,13,,S
+290,1,3,"Connolly, Miss. Kate",female,22,0,0,370373,7.75,,Q
+291,1,1,"Barber, Miss. Ellen ""Nellie""",female,26,0,0,19877,78.85,,S
+292,1,1,"Bishop, Mrs. Dickinson H (Helen Walton)",female,19,1,0,11967,91.0792,B49,C
+293,0,2,"Levy, Mr. Rene Jacques",male,36,0,0,SC/Paris 2163,12.875,D,C
+294,0,3,"Haas, Miss. Aloisia",female,24,0,0,349236,8.85,,S
+295,0,3,"Mineff, Mr. Ivan",male,24,0,0,349233,7.8958,,S
+296,0,1,"Lewy, Mr. Ervin G",male,,0,0,PC 17612,27.7208,,C
+297,0,3,"Hanna, Mr. Mansour",male,23.5,0,0,2693,7.2292,,C
+298,0,1,"Allison, Miss. Helen Loraine",female,2,1,2,113781,151.55,C22 C26,S
+299,1,1,"Saalfeld, Mr. Adolphe",male,,0,0,19988,30.5,C106,S
+300,1,1,"Baxter, Mrs. James (Helene DeLaudeniere Chaput)",female,50,0,1,PC 17558,247.5208,B58 B60,C
+301,1,3,"Kelly, Miss. Anna Katherine ""Annie Kate""",female,,0,0,9234,7.75,,Q
+302,1,3,"McCoy, Mr. Bernard",male,,2,0,367226,23.25,,Q
+303,0,3,"Johnson, Mr. William Cahoone Jr",male,19,0,0,LINE,0,,S
+304,1,2,"Keane, Miss. Nora A",female,,0,0,226593,12.35,E101,Q
+305,0,3,"Williams, Mr. Howard Hugh ""Harry""",male,,0,0,A/5 2466,8.05,,S
+306,1,1,"Allison, Master. Hudson Trevor",male,0.92,1,2,113781,151.55,C22 C26,S
+307,1,1,"Fleming, Miss. Margaret",female,,0,0,17421,110.8833,,C
+308,1,1,"Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)",female,17,1,0,PC 17758,108.9,C65,C
+309,0,2,"Abelson, Mr. Samuel",male,30,1,0,P/PP 3381,24,,C
+310,1,1,"Francatelli, Miss. Laura Mabel",female,30,0,0,PC 17485,56.9292,E36,C
+311,1,1,"Hays, Miss. Margaret Bechstein",female,24,0,0,11767,83.1583,C54,C
+312,1,1,"Ryerson, Miss. Emily Borie",female,18,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+313,0,2,"Lahtinen, Mrs. William (Anna Sylfven)",female,26,1,1,250651,26,,S
+314,0,3,"Hendekovic, Mr. Ignjac",male,28,0,0,349243,7.8958,,S
+315,0,2,"Hart, Mr. Benjamin",male,43,1,1,F.C.C. 13529,26.25,,S
+316,1,3,"Nilsson, Miss. Helmina Josefina",female,26,0,0,347470,7.8542,,S
+317,1,2,"Kantor, Mrs. Sinai (Miriam Sternin)",female,24,1,0,244367,26,,S
+318,0,2,"Moraweck, Dr. Ernest",male,54,0,0,29011,14,,S
+319,1,1,"Wick, Miss. Mary Natalie",female,31,0,2,36928,164.8667,C7,S
+320,1,1,"Spedden, Mrs. Frederic Oakley (Margaretta Corning Stone)",female,40,1,1,16966,134.5,E34,C
+321,0,3,"Dennis, Mr. Samuel",male,22,0,0,A/5 21172,7.25,,S
+322,0,3,"Danoff, Mr. Yoto",male,27,0,0,349219,7.8958,,S
+323,1,2,"Slayter, Miss. Hilda Mary",female,30,0,0,234818,12.35,,Q
+324,1,2,"Caldwell, Mrs. Albert Francis (Sylvia Mae Harbaugh)",female,22,1,1,248738,29,,S
+325,0,3,"Sage, Mr. George John Jr",male,,8,2,CA. 2343,69.55,,S
+326,1,1,"Young, Miss. Marie Grice",female,36,0,0,PC 17760,135.6333,C32,C
+327,0,3,"Nysveen, Mr. Johan Hansen",male,61,0,0,345364,6.2375,,S
+328,1,2,"Ball, Mrs. (Ada E Hall)",female,36,0,0,28551,13,D,S
+329,1,3,"Goldsmith, Mrs. Frank John (Emily Alice Brown)",female,31,1,1,363291,20.525,,S
+330,1,1,"Hippach, Miss. Jean Gertrude",female,16,0,1,111361,57.9792,B18,C
+331,1,3,"McCoy, Miss. Agnes",female,,2,0,367226,23.25,,Q
+332,0,1,"Partner, Mr. Austen",male,45.5,0,0,113043,28.5,C124,S
+333,0,1,"Graham, Mr. George Edward",male,38,0,1,PC 17582,153.4625,C91,S
+334,0,3,"Vander Planke, Mr. Leo Edmondus",male,16,2,0,345764,18,,S
+335,1,1,"Frauenthal, Mrs. Henry William (Clara Heinsheimer)",female,,1,0,PC 17611,133.65,,S
+336,0,3,"Denkoff, Mr. Mitto",male,,0,0,349225,7.8958,,S
+337,0,1,"Pears, Mr. Thomas Clinton",male,29,1,0,113776,66.6,C2,S
+338,1,1,"Burns, Miss. Elizabeth Margaret",female,41,0,0,16966,134.5,E40,C
+339,1,3,"Dahl, Mr. Karl Edwart",male,45,0,0,7598,8.05,,S
+340,0,1,"Blackwell, Mr. Stephen Weart",male,45,0,0,113784,35.5,T,S
+341,1,2,"Navratil, Master. Edmond Roger",male,2,1,1,230080,26,F2,S
+342,1,1,"Fortune, Miss. Alice Elizabeth",female,24,3,2,19950,263,C23 C25 C27,S
+343,0,2,"Collander, Mr. Erik Gustaf",male,28,0,0,248740,13,,S
+344,0,2,"Sedgwick, Mr. Charles Frederick Waddington",male,25,0,0,244361,13,,S
+345,0,2,"Fox, Mr. Stanley Hubert",male,36,0,0,229236,13,,S
+346,1,2,"Brown, Miss. Amelia ""Mildred""",female,24,0,0,248733,13,F33,S
+347,1,2,"Smith, Miss. Marion Elsie",female,40,0,0,31418,13,,S
+348,1,3,"Davison, Mrs. Thomas Henry (Mary E Finck)",female,,1,0,386525,16.1,,S
+349,1,3,"Coutts, Master. William Loch ""William""",male,3,1,1,C.A. 37671,15.9,,S
+350,0,3,"Dimic, Mr. Jovan",male,42,0,0,315088,8.6625,,S
+351,0,3,"Odahl, Mr. Nils Martin",male,23,0,0,7267,9.225,,S
+352,0,1,"Williams-Lambert, Mr. Fletcher Fellows",male,,0,0,113510,35,C128,S
+353,0,3,"Elias, Mr. Tannous",male,15,1,1,2695,7.2292,,C
+354,0,3,"Arnold-Franchi, Mr. Josef",male,25,1,0,349237,17.8,,S
+355,0,3,"Yousif, Mr. Wazli",male,,0,0,2647,7.225,,C
+356,0,3,"Vanden Steen, Mr. Leo Peter",male,28,0,0,345783,9.5,,S
+357,1,1,"Bowerman, Miss. Elsie Edith",female,22,0,1,113505,55,E33,S
+358,0,2,"Funk, Miss. Annie Clemmer",female,38,0,0,237671,13,,S
+359,1,3,"McGovern, Miss. Mary",female,,0,0,330931,7.8792,,Q
+360,1,3,"Mockler, Miss. Helen Mary ""Ellie""",female,,0,0,330980,7.8792,,Q
+361,0,3,"Skoog, Mr. Wilhelm",male,40,1,4,347088,27.9,,S
+362,0,2,"del Carlo, Mr. Sebastiano",male,29,1,0,SC/PARIS 2167,27.7208,,C
+363,0,3,"Barbara, Mrs. (Catherine David)",female,45,0,1,2691,14.4542,,C
+364,0,3,"Asim, Mr. Adola",male,35,0,0,SOTON/O.Q. 3101310,7.05,,S
+365,0,3,"O'Brien, Mr. Thomas",male,,1,0,370365,15.5,,Q
+366,0,3,"Adahl, Mr. Mauritz Nils Martin",male,30,0,0,C 7076,7.25,,S
+367,1,1,"Warren, Mrs. Frank Manley (Anna Sophia Atkinson)",female,60,1,0,110813,75.25,D37,C
+368,1,3,"Moussa, Mrs. (Mantoura Boulos)",female,,0,0,2626,7.2292,,C
+369,1,3,"Jermyn, Miss. Annie",female,,0,0,14313,7.75,,Q
+370,1,1,"Aubart, Mme. Leontine Pauline",female,24,0,0,PC 17477,69.3,B35,C
+371,1,1,"Harder, Mr. George Achilles",male,25,1,0,11765,55.4417,E50,C
+372,0,3,"Wiklund, Mr. Jakob Alfred",male,18,1,0,3101267,6.4958,,S
+373,0,3,"Beavan, Mr. William Thomas",male,19,0,0,323951,8.05,,S
+374,0,1,"Ringhini, Mr. Sante",male,22,0,0,PC 17760,135.6333,,C
+375,0,3,"Palsson, Miss. Stina Viola",female,3,3,1,349909,21.075,,S
+376,1,1,"Meyer, Mrs. Edgar Joseph (Leila Saks)",female,,1,0,PC 17604,82.1708,,C
+377,1,3,"Landergren, Miss. Aurora Adelia",female,22,0,0,C 7077,7.25,,S
+378,0,1,"Widener, Mr. Harry Elkins",male,27,0,2,113503,211.5,C82,C
+379,0,3,"Betros, Mr. Tannous",male,20,0,0,2648,4.0125,,C
+380,0,3,"Gustafsson, Mr. Karl Gideon",male,19,0,0,347069,7.775,,S
+381,1,1,"Bidois, Miss. Rosalie",female,42,0,0,PC 17757,227.525,,C
+382,1,3,"Nakid, Miss. Maria (""Mary"")",female,1,0,2,2653,15.7417,,C
+383,0,3,"Tikkanen, Mr. Juho",male,32,0,0,STON/O 2. 3101293,7.925,,S
+384,1,1,"Holverson, Mrs. Alexander Oskar (Mary Aline Towner)",female,35,1,0,113789,52,,S
+385,0,3,"Plotcharsky, Mr. Vasil",male,,0,0,349227,7.8958,,S
+386,0,2,"Davies, Mr. Charles Henry",male,18,0,0,S.O.C. 14879,73.5,,S
+387,0,3,"Goodwin, Master. Sidney Leonard",male,1,5,2,CA 2144,46.9,,S
+388,1,2,"Buss, Miss. Kate",female,36,0,0,27849,13,,S
+389,0,3,"Sadlier, Mr. Matthew",male,,0,0,367655,7.7292,,Q
+390,1,2,"Lehmann, Miss. Bertha",female,17,0,0,SC 1748,12,,C
+391,1,1,"Carter, Mr. William Ernest",male,36,1,2,113760,120,B96 B98,S
+392,1,3,"Jansson, Mr. Carl Olof",male,21,0,0,350034,7.7958,,S
+393,0,3,"Gustafsson, Mr. Johan Birger",male,28,2,0,3101277,7.925,,S
+394,1,1,"Newell, Miss. Marjorie",female,23,1,0,35273,113.275,D36,C
+395,1,3,"Sandstrom, Mrs. Hjalmar (Agnes Charlotta Bengtsson)",female,24,0,2,PP 9549,16.7,G6,S
+396,0,3,"Johansson, Mr. Erik",male,22,0,0,350052,7.7958,,S
+397,0,3,"Olsson, Miss. Elina",female,31,0,0,350407,7.8542,,S
+398,0,2,"McKane, Mr. Peter David",male,46,0,0,28403,26,,S
+399,0,2,"Pain, Dr. Alfred",male,23,0,0,244278,10.5,,S
+400,1,2,"Trout, Mrs. William H (Jessie L)",female,28,0,0,240929,12.65,,S
+401,1,3,"Niskanen, Mr. Juha",male,39,0,0,STON/O 2. 3101289,7.925,,S
+402,0,3,"Adams, Mr. John",male,26,0,0,341826,8.05,,S
+403,0,3,"Jussila, Miss. Mari Aina",female,21,1,0,4137,9.825,,S
+404,0,3,"Hakkarainen, Mr. Pekka Pietari",male,28,1,0,STON/O2. 3101279,15.85,,S
+405,0,3,"Oreskovic, Miss. Marija",female,20,0,0,315096,8.6625,,S
+406,0,2,"Gale, Mr. Shadrach",male,34,1,0,28664,21,,S
+407,0,3,"Widegren, Mr. Carl/Charles Peter",male,51,0,0,347064,7.75,,S
+408,1,2,"Richards, Master. William Rowe",male,3,1,1,29106,18.75,,S
+409,0,3,"Birkeland, Mr. Hans Martin Monsen",male,21,0,0,312992,7.775,,S
+410,0,3,"Lefebre, Miss. Ida",female,,3,1,4133,25.4667,,S
+411,0,3,"Sdycoff, Mr. Todor",male,,0,0,349222,7.8958,,S
+412,0,3,"Hart, Mr. Henry",male,,0,0,394140,6.8583,,Q
+413,1,1,"Minahan, Miss. Daisy E",female,33,1,0,19928,90,C78,Q
+414,0,2,"Cunningham, Mr. Alfred Fleming",male,,0,0,239853,0,,S
+415,1,3,"Sundman, Mr. Johan Julian",male,44,0,0,STON/O 2. 3101269,7.925,,S
+416,0,3,"Meek, Mrs. Thomas (Annie Louise Rowley)",female,,0,0,343095,8.05,,S
+417,1,2,"Drew, Mrs. James Vivian (Lulu Thorne Christian)",female,34,1,1,28220,32.5,,S
+418,1,2,"Silven, Miss. Lyyli Karoliina",female,18,0,2,250652,13,,S
+419,0,2,"Matthews, Mr. William John",male,30,0,0,28228,13,,S
+420,0,3,"Van Impe, Miss. Catharina",female,10,0,2,345773,24.15,,S
+421,0,3,"Gheorgheff, Mr. Stanio",male,,0,0,349254,7.8958,,C
+422,0,3,"Charters, Mr. David",male,21,0,0,A/5. 13032,7.7333,,Q
+423,0,3,"Zimmerman, Mr. Leo",male,29,0,0,315082,7.875,,S
+424,0,3,"Danbom, Mrs. Ernst Gilbert (Anna Sigrid Maria Brogren)",female,28,1,1,347080,14.4,,S
+425,0,3,"Rosblom, Mr. Viktor Richard",male,18,1,1,370129,20.2125,,S
+426,0,3,"Wiseman, Mr. Phillippe",male,,0,0,A/4. 34244,7.25,,S
+427,1,2,"Clarke, Mrs. Charles V (Ada Maria Winfield)",female,28,1,0,2003,26,,S
+428,1,2,"Phillips, Miss. Kate Florence (""Mrs Kate Louise Phillips Marshall"")",female,19,0,0,250655,26,,S
+429,0,3,"Flynn, Mr. James",male,,0,0,364851,7.75,,Q
+430,1,3,"Pickard, Mr. Berk (Berk Trembisky)",male,32,0,0,SOTON/O.Q. 392078,8.05,E10,S
+431,1,1,"Bjornstrom-Steffansson, Mr. Mauritz Hakan",male,28,0,0,110564,26.55,C52,S
+432,1,3,"Thorneycroft, Mrs. Percival (Florence Kate White)",female,,1,0,376564,16.1,,S
+433,1,2,"Louch, Mrs. Charles Alexander (Alice Adelaide Slow)",female,42,1,0,SC/AH 3085,26,,S
+434,0,3,"Kallio, Mr. Nikolai Erland",male,17,0,0,STON/O 2. 3101274,7.125,,S
+435,0,1,"Silvey, Mr. William Baird",male,50,1,0,13507,55.9,E44,S
+436,1,1,"Carter, Miss. Lucile Polk",female,14,1,2,113760,120,B96 B98,S
+437,0,3,"Ford, Miss. Doolina Margaret ""Daisy""",female,21,2,2,W./C. 6608,34.375,,S
+438,1,2,"Richards, Mrs. Sidney (Emily Hocking)",female,24,2,3,29106,18.75,,S
+439,0,1,"Fortune, Mr. Mark",male,64,1,4,19950,263,C23 C25 C27,S
+440,0,2,"Kvillner, Mr. Johan Henrik Johannesson",male,31,0,0,C.A. 18723,10.5,,S
+441,1,2,"Hart, Mrs. Benjamin (Esther Ada Bloomfield)",female,45,1,1,F.C.C. 13529,26.25,,S
+442,0,3,"Hampe, Mr. Leon",male,20,0,0,345769,9.5,,S
+443,0,3,"Petterson, Mr. Johan Emil",male,25,1,0,347076,7.775,,S
+444,1,2,"Reynaldo, Ms. Encarnacion",female,28,0,0,230434,13,,S
+445,1,3,"Johannesen-Bratthammer, Mr. Bernt",male,,0,0,65306,8.1125,,S
+446,1,1,"Dodge, Master. Washington",male,4,0,2,33638,81.8583,A34,S
+447,1,2,"Mellinger, Miss. Madeleine Violet",female,13,0,1,250644,19.5,,S
+448,1,1,"Seward, Mr. Frederic Kimber",male,34,0,0,113794,26.55,,S
+449,1,3,"Baclini, Miss. Marie Catherine",female,5,2,1,2666,19.2583,,C
+450,1,1,"Peuchen, Major. Arthur Godfrey",male,52,0,0,113786,30.5,C104,S
+451,0,2,"West, Mr. Edwy Arthur",male,36,1,2,C.A. 34651,27.75,,S
+452,0,3,"Hagland, Mr. Ingvald Olai Olsen",male,,1,0,65303,19.9667,,S
+453,0,1,"Foreman, Mr. Benjamin Laventall",male,30,0,0,113051,27.75,C111,C
+454,1,1,"Goldenberg, Mr. Samuel L",male,49,1,0,17453,89.1042,C92,C
+455,0,3,"Peduzzi, Mr. Joseph",male,,0,0,A/5 2817,8.05,,S
+456,1,3,"Jalsevac, Mr. Ivan",male,29,0,0,349240,7.8958,,C
+457,0,1,"Millet, Mr. Francis Davis",male,65,0,0,13509,26.55,E38,S
+458,1,1,"Kenyon, Mrs. Frederick R (Marion)",female,,1,0,17464,51.8625,D21,S
+459,1,2,"Toomey, Miss. Ellen",female,50,0,0,F.C.C. 13531,10.5,,S
+460,0,3,"O'Connor, Mr. Maurice",male,,0,0,371060,7.75,,Q
+461,1,1,"Anderson, Mr. Harry",male,48,0,0,19952,26.55,E12,S
+462,0,3,"Morley, Mr. William",male,34,0,0,364506,8.05,,S
+463,0,1,"Gee, Mr. Arthur H",male,47,0,0,111320,38.5,E63,S
+464,0,2,"Milling, Mr. Jacob Christian",male,48,0,0,234360,13,,S
+465,0,3,"Maisner, Mr. Simon",male,,0,0,A/S 2816,8.05,,S
+466,0,3,"Goncalves, Mr. Manuel Estanslas",male,38,0,0,SOTON/O.Q. 3101306,7.05,,S
+467,0,2,"Campbell, Mr. William",male,,0,0,239853,0,,S
+468,0,1,"Smart, Mr. John Montgomery",male,56,0,0,113792,26.55,,S
+469,0,3,"Scanlan, Mr. James",male,,0,0,36209,7.725,,Q
+470,1,3,"Baclini, Miss. Helene Barbara",female,0.75,2,1,2666,19.2583,,C
+471,0,3,"Keefe, Mr. Arthur",male,,0,0,323592,7.25,,S
+472,0,3,"Cacic, Mr. Luka",male,38,0,0,315089,8.6625,,S
+473,1,2,"West, Mrs. Edwy Arthur (Ada Mary Worth)",female,33,1,2,C.A. 34651,27.75,,S
+474,1,2,"Jerwan, Mrs. Amin S (Marie Marthe Thuillard)",female,23,0,0,SC/AH Basle 541,13.7917,D,C
+475,0,3,"Strandberg, Miss. Ida Sofia",female,22,0,0,7553,9.8375,,S
+476,0,1,"Clifford, Mr. George Quincy",male,,0,0,110465,52,A14,S
+477,0,2,"Renouf, Mr. Peter Henry",male,34,1,0,31027,21,,S
+478,0,3,"Braund, Mr. Lewis Richard",male,29,1,0,3460,7.0458,,S
+479,0,3,"Karlsson, Mr. Nils August",male,22,0,0,350060,7.5208,,S
+480,1,3,"Hirvonen, Miss. Hildur E",female,2,0,1,3101298,12.2875,,S
+481,0,3,"Goodwin, Master. Harold Victor",male,9,5,2,CA 2144,46.9,,S
+482,0,2,"Frost, Mr. Anthony Wood ""Archie""",male,,0,0,239854,0,,S
+483,0,3,"Rouse, Mr. Richard Henry",male,50,0,0,A/5 3594,8.05,,S
+484,1,3,"Turkula, Mrs. (Hedwig)",female,63,0,0,4134,9.5875,,S
+485,1,1,"Bishop, Mr. Dickinson H",male,25,1,0,11967,91.0792,B49,C
+486,0,3,"Lefebre, Miss. Jeannie",female,,3,1,4133,25.4667,,S
+487,1,1,"Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby)",female,35,1,0,19943,90,C93,S
+488,0,1,"Kent, Mr. Edward Austin",male,58,0,0,11771,29.7,B37,C
+489,0,3,"Somerton, Mr. Francis William",male,30,0,0,A.5. 18509,8.05,,S
+490,1,3,"Coutts, Master. Eden Leslie ""Neville""",male,9,1,1,C.A. 37671,15.9,,S
+491,0,3,"Hagland, Mr. Konrad Mathias Reiersen",male,,1,0,65304,19.9667,,S
+492,0,3,"Windelov, Mr. Einar",male,21,0,0,SOTON/OQ 3101317,7.25,,S
+493,0,1,"Molson, Mr. Harry Markland",male,55,0,0,113787,30.5,C30,S
+494,0,1,"Artagaveytia, Mr. Ramon",male,71,0,0,PC 17609,49.5042,,C
+495,0,3,"Stanley, Mr. Edward Roland",male,21,0,0,A/4 45380,8.05,,S
+496,0,3,"Yousseff, Mr. Gerious",male,,0,0,2627,14.4583,,C
+497,1,1,"Eustis, Miss. Elizabeth Mussey",female,54,1,0,36947,78.2667,D20,C
+498,0,3,"Shellard, Mr. Frederick William",male,,0,0,C.A. 6212,15.1,,S
+499,0,1,"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)",female,25,1,2,113781,151.55,C22 C26,S
+500,0,3,"Svensson, Mr. Olof",male,24,0,0,350035,7.7958,,S
+501,0,3,"Calic, Mr. Petar",male,17,0,0,315086,8.6625,,S
+502,0,3,"Canavan, Miss. Mary",female,21,0,0,364846,7.75,,Q
+503,0,3,"O'Sullivan, Miss. Bridget Mary",female,,0,0,330909,7.6292,,Q
+504,0,3,"Laitinen, Miss. Kristina Sofia",female,37,0,0,4135,9.5875,,S
+505,1,1,"Maioni, Miss. Roberta",female,16,0,0,110152,86.5,B79,S
+506,0,1,"Penasco y Castellana, Mr. Victor de Satode",male,18,1,0,PC 17758,108.9,C65,C
+507,1,2,"Quick, Mrs. Frederick Charles (Jane Richards)",female,33,0,2,26360,26,,S
+508,1,1,"Bradley, Mr. George (""George Arthur Brayton"")",male,,0,0,111427,26.55,,S
+509,0,3,"Olsen, Mr. Henry Margido",male,28,0,0,C 4001,22.525,,S
+510,1,3,"Lang, Mr. Fang",male,26,0,0,1601,56.4958,,S
+511,1,3,"Daly, Mr. Eugene Patrick",male,29,0,0,382651,7.75,,Q
+512,0,3,"Webber, Mr. James",male,,0,0,SOTON/OQ 3101316,8.05,,S
+513,1,1,"McGough, Mr. James Robert",male,36,0,0,PC 17473,26.2875,E25,S
+514,1,1,"Rothschild, Mrs. Martin (Elizabeth L. Barrett)",female,54,1,0,PC 17603,59.4,,C
+515,0,3,"Coleff, Mr. Satio",male,24,0,0,349209,7.4958,,S
+516,0,1,"Walker, Mr. William Anderson",male,47,0,0,36967,34.0208,D46,S
+517,1,2,"Lemore, Mrs. (Amelia Milley)",female,34,0,0,C.A. 34260,10.5,F33,S
+518,0,3,"Ryan, Mr. Patrick",male,,0,0,371110,24.15,,Q
+519,1,2,"Angle, Mrs. William A (Florence ""Mary"" Agnes Hughes)",female,36,1,0,226875,26,,S
+520,0,3,"Pavlovic, Mr. Stefo",male,32,0,0,349242,7.8958,,S
+521,1,1,"Perreault, Miss. Anne",female,30,0,0,12749,93.5,B73,S
+522,0,3,"Vovk, Mr. Janko",male,22,0,0,349252,7.8958,,S
+523,0,3,"Lahoud, Mr. Sarkis",male,,0,0,2624,7.225,,C
+524,1,1,"Hippach, Mrs. Louis Albert (Ida Sophia Fischer)",female,44,0,1,111361,57.9792,B18,C
+525,0,3,"Kassem, Mr. Fared",male,,0,0,2700,7.2292,,C
+526,0,3,"Farrell, Mr. James",male,40.5,0,0,367232,7.75,,Q
+527,1,2,"Ridsdale, Miss. Lucy",female,50,0,0,W./C. 14258,10.5,,S
+528,0,1,"Farthing, Mr. John",male,,0,0,PC 17483,221.7792,C95,S
+529,0,3,"Salonen, Mr. Johan Werner",male,39,0,0,3101296,7.925,,S
+530,0,2,"Hocking, Mr. Richard George",male,23,2,1,29104,11.5,,S
+531,1,2,"Quick, Miss. Phyllis May",female,2,1,1,26360,26,,S
+532,0,3,"Toufik, Mr. Nakli",male,,0,0,2641,7.2292,,C
+533,0,3,"Elias, Mr. Joseph Jr",male,17,1,1,2690,7.2292,,C
+534,1,3,"Peter, Mrs. Catherine (Catherine Rizk)",female,,0,2,2668,22.3583,,C
+535,0,3,"Cacic, Miss. Marija",female,30,0,0,315084,8.6625,,S
+536,1,2,"Hart, Miss. Eva Miriam",female,7,0,2,F.C.C. 13529,26.25,,S
+537,0,1,"Butt, Major. Archibald Willingham",male,45,0,0,113050,26.55,B38,S
+538,1,1,"LeRoy, Miss. Bertha",female,30,0,0,PC 17761,106.425,,C
+539,0,3,"Risien, Mr. Samuel Beard",male,,0,0,364498,14.5,,S
+540,1,1,"Frolicher, Miss. Hedwig Margaritha",female,22,0,2,13568,49.5,B39,C
+541,1,1,"Crosby, Miss. Harriet R",female,36,0,2,WE/P 5735,71,B22,S
+542,0,3,"Andersson, Miss. Ingeborg Constanzia",female,9,4,2,347082,31.275,,S
+543,0,3,"Andersson, Miss. Sigrid Elisabeth",female,11,4,2,347082,31.275,,S
+544,1,2,"Beane, Mr. Edward",male,32,1,0,2908,26,,S
+545,0,1,"Douglas, Mr. Walter Donald",male,50,1,0,PC 17761,106.425,C86,C
+546,0,1,"Nicholson, Mr. Arthur Ernest",male,64,0,0,693,26,,S
+547,1,2,"Beane, Mrs. Edward (Ethel Clarke)",female,19,1,0,2908,26,,S
+548,1,2,"Padro y Manent, Mr. Julian",male,,0,0,SC/PARIS 2146,13.8625,,C
+549,0,3,"Goldsmith, Mr. Frank John",male,33,1,1,363291,20.525,,S
+550,1,2,"Davies, Master. John Morgan Jr",male,8,1,1,C.A. 33112,36.75,,S
+551,1,1,"Thayer, Mr. John Borland Jr",male,17,0,2,17421,110.8833,C70,C
+552,0,2,"Sharp, Mr. Percival James R",male,27,0,0,244358,26,,S
+553,0,3,"O'Brien, Mr. Timothy",male,,0,0,330979,7.8292,,Q
+554,1,3,"Leeni, Mr. Fahim (""Philip Zenni"")",male,22,0,0,2620,7.225,,C
+555,1,3,"Ohman, Miss. Velin",female,22,0,0,347085,7.775,,S
+556,0,1,"Wright, Mr. George",male,62,0,0,113807,26.55,,S
+557,1,1,"Duff Gordon, Lady. (Lucille Christiana Sutherland) (""Mrs Morgan"")",female,48,1,0,11755,39.6,A16,C
+558,0,1,"Robbins, Mr. Victor",male,,0,0,PC 17757,227.525,,C
+559,1,1,"Taussig, Mrs. Emil (Tillie Mandelbaum)",female,39,1,1,110413,79.65,E67,S
+560,1,3,"de Messemaeker, Mrs. Guillaume Joseph (Emma)",female,36,1,0,345572,17.4,,S
+561,0,3,"Morrow, Mr. Thomas Rowan",male,,0,0,372622,7.75,,Q
+562,0,3,"Sivic, Mr. Husein",male,40,0,0,349251,7.8958,,S
+563,0,2,"Norman, Mr. Robert Douglas",male,28,0,0,218629,13.5,,S
+564,0,3,"Simmons, Mr. John",male,,0,0,SOTON/OQ 392082,8.05,,S
+565,0,3,"Meanwell, Miss. (Marion Ogden)",female,,0,0,SOTON/O.Q. 392087,8.05,,S
+566,0,3,"Davies, Mr. Alfred J",male,24,2,0,A/4 48871,24.15,,S
+567,0,3,"Stoytcheff, Mr. Ilia",male,19,0,0,349205,7.8958,,S
+568,0,3,"Palsson, Mrs. Nils (Alma Cornelia Berglund)",female,29,0,4,349909,21.075,,S
+569,0,3,"Doharr, Mr. Tannous",male,,0,0,2686,7.2292,,C
+570,1,3,"Jonsson, Mr. Carl",male,32,0,0,350417,7.8542,,S
+571,1,2,"Harris, Mr. George",male,62,0,0,S.W./PP 752,10.5,,S
+572,1,1,"Appleton, Mrs. Edward Dale (Charlotte Lamson)",female,53,2,0,11769,51.4792,C101,S
+573,1,1,"Flynn, Mr. John Irwin (""Irving"")",male,36,0,0,PC 17474,26.3875,E25,S
+574,1,3,"Kelly, Miss. Mary",female,,0,0,14312,7.75,,Q
+575,0,3,"Rush, Mr. Alfred George John",male,16,0,0,A/4. 20589,8.05,,S
+576,0,3,"Patchett, Mr. George",male,19,0,0,358585,14.5,,S
+577,1,2,"Garside, Miss. Ethel",female,34,0,0,243880,13,,S
+578,1,1,"Silvey, Mrs. William Baird (Alice Munger)",female,39,1,0,13507,55.9,E44,S
+579,0,3,"Caram, Mrs. Joseph (Maria Elias)",female,,1,0,2689,14.4583,,C
+580,1,3,"Jussila, Mr. Eiriik",male,32,0,0,STON/O 2. 3101286,7.925,,S
+581,1,2,"Christy, Miss. Julie Rachel",female,25,1,1,237789,30,,S
+582,1,1,"Thayer, Mrs. John Borland (Marian Longstreth Morris)",female,39,1,1,17421,110.8833,C68,C
+583,0,2,"Downton, Mr. William James",male,54,0,0,28403,26,,S
+584,0,1,"Ross, Mr. John Hugo",male,36,0,0,13049,40.125,A10,C
+585,0,3,"Paulner, Mr. Uscher",male,,0,0,3411,8.7125,,C
+586,1,1,"Taussig, Miss. Ruth",female,18,0,2,110413,79.65,E68,S
+587,0,2,"Jarvis, Mr. John Denzil",male,47,0,0,237565,15,,S
+588,1,1,"Frolicher-Stehli, Mr. Maxmillian",male,60,1,1,13567,79.2,B41,C
+589,0,3,"Gilinski, Mr. Eliezer",male,22,0,0,14973,8.05,,S
+590,0,3,"Murdlin, Mr. Joseph",male,,0,0,A./5. 3235,8.05,,S
+591,0,3,"Rintamaki, Mr. Matti",male,35,0,0,STON/O 2. 3101273,7.125,,S
+592,1,1,"Stephenson, Mrs. Walter Bertram (Martha Eustis)",female,52,1,0,36947,78.2667,D20,C
+593,0,3,"Elsbury, Mr. William James",male,47,0,0,A/5 3902,7.25,,S
+594,0,3,"Bourke, Miss. Mary",female,,0,2,364848,7.75,,Q
+595,0,2,"Chapman, Mr. John Henry",male,37,1,0,SC/AH 29037,26,,S
+596,0,3,"Van Impe, Mr. Jean Baptiste",male,36,1,1,345773,24.15,,S
+597,1,2,"Leitch, Miss. Jessie Wills",female,,0,0,248727,33,,S
+598,0,3,"Johnson, Mr. Alfred",male,49,0,0,LINE,0,,S
+599,0,3,"Boulos, Mr. Hanna",male,,0,0,2664,7.225,,C
+600,1,1,"Duff Gordon, Sir. Cosmo Edmund (""Mr Morgan"")",male,49,1,0,PC 17485,56.9292,A20,C
+601,1,2,"Jacobsohn, Mrs. Sidney Samuel (Amy Frances Christy)",female,24,2,1,243847,27,,S
+602,0,3,"Slabenoff, Mr. Petco",male,,0,0,349214,7.8958,,S
+603,0,1,"Harrington, Mr. Charles H",male,,0,0,113796,42.4,,S
+604,0,3,"Torber, Mr. Ernst William",male,44,0,0,364511,8.05,,S
+605,1,1,"Homer, Mr. Harry (""Mr E Haven"")",male,35,0,0,111426,26.55,,C
+606,0,3,"Lindell, Mr. Edvard Bengtsson",male,36,1,0,349910,15.55,,S
+607,0,3,"Karaic, Mr. Milan",male,30,0,0,349246,7.8958,,S
+608,1,1,"Daniel, Mr. Robert Williams",male,27,0,0,113804,30.5,,S
+609,1,2,"Laroche, Mrs. Joseph (Juliette Marie Louise Lafargue)",female,22,1,2,SC/Paris 2123,41.5792,,C
+610,1,1,"Shutes, Miss. Elizabeth W",female,40,0,0,PC 17582,153.4625,C125,S
+611,0,3,"Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren)",female,39,1,5,347082,31.275,,S
+612,0,3,"Jardin, Mr. Jose Neto",male,,0,0,SOTON/O.Q. 3101305,7.05,,S
+613,1,3,"Murphy, Miss. Margaret Jane",female,,1,0,367230,15.5,,Q
+614,0,3,"Horgan, Mr. John",male,,0,0,370377,7.75,,Q
+615,0,3,"Brocklebank, Mr. William Alfred",male,35,0,0,364512,8.05,,S
+616,1,2,"Herman, Miss. Alice",female,24,1,2,220845,65,,S
+617,0,3,"Danbom, Mr. Ernst Gilbert",male,34,1,1,347080,14.4,,S
+618,0,3,"Lobb, Mrs. William Arthur (Cordelia K Stanlick)",female,26,1,0,A/5. 3336,16.1,,S
+619,1,2,"Becker, Miss. Marion Louise",female,4,2,1,230136,39,F4,S
+620,0,2,"Gavey, Mr. Lawrence",male,26,0,0,31028,10.5,,S
+621,0,3,"Yasbeck, Mr. Antoni",male,27,1,0,2659,14.4542,,C
+622,1,1,"Kimball, Mr. Edwin Nelson Jr",male,42,1,0,11753,52.5542,D19,S
+623,1,3,"Nakid, Mr. Sahid",male,20,1,1,2653,15.7417,,C
+624,0,3,"Hansen, Mr. Henry Damsgaard",male,21,0,0,350029,7.8542,,S
+625,0,3,"Bowen, Mr. David John ""Dai""",male,21,0,0,54636,16.1,,S
+626,0,1,"Sutton, Mr. Frederick",male,61,0,0,36963,32.3208,D50,S
+627,0,2,"Kirkland, Rev. Charles Leonard",male,57,0,0,219533,12.35,,Q
+628,1,1,"Longley, Miss. Gretchen Fiske",female,21,0,0,13502,77.9583,D9,S
+629,0,3,"Bostandyeff, Mr. Guentcho",male,26,0,0,349224,7.8958,,S
+630,0,3,"O'Connell, Mr. Patrick D",male,,0,0,334912,7.7333,,Q
+631,1,1,"Barkworth, Mr. Algernon Henry Wilson",male,80,0,0,27042,30,A23,S
+632,0,3,"Lundahl, Mr. Johan Svensson",male,51,0,0,347743,7.0542,,S
+633,1,1,"Stahelin-Maeglin, Dr. Max",male,32,0,0,13214,30.5,B50,C
+634,0,1,"Parr, Mr. William Henry Marsh",male,,0,0,112052,0,,S
+635,0,3,"Skoog, Miss. Mabel",female,9,3,2,347088,27.9,,S
+636,1,2,"Davis, Miss. Mary",female,28,0,0,237668,13,,S
+637,0,3,"Leinonen, Mr. Antti Gustaf",male,32,0,0,STON/O 2. 3101292,7.925,,S
+638,0,2,"Collyer, Mr. Harvey",male,31,1,1,C.A. 31921,26.25,,S
+639,0,3,"Panula, Mrs. Juha (Maria Emilia Ojala)",female,41,0,5,3101295,39.6875,,S
+640,0,3,"Thorneycroft, Mr. Percival",male,,1,0,376564,16.1,,S
+641,0,3,"Jensen, Mr. Hans Peder",male,20,0,0,350050,7.8542,,S
+642,1,1,"Sagesser, Mlle. Emma",female,24,0,0,PC 17477,69.3,B35,C
+643,0,3,"Skoog, Miss. Margit Elizabeth",female,2,3,2,347088,27.9,,S
+644,1,3,"Foo, Mr. Choong",male,,0,0,1601,56.4958,,S
+645,1,3,"Baclini, Miss. Eugenie",female,0.75,2,1,2666,19.2583,,C
+646,1,1,"Harper, Mr. Henry Sleeper",male,48,1,0,PC 17572,76.7292,D33,C
+647,0,3,"Cor, Mr. Liudevit",male,19,0,0,349231,7.8958,,S
+648,1,1,"Simonius-Blumer, Col. Oberst Alfons",male,56,0,0,13213,35.5,A26,C
+649,0,3,"Willey, Mr. Edward",male,,0,0,S.O./P.P. 751,7.55,,S
+650,1,3,"Stanley, Miss. Amy Zillah Elsie",female,23,0,0,CA. 2314,7.55,,S
+651,0,3,"Mitkoff, Mr. Mito",male,,0,0,349221,7.8958,,S
+652,1,2,"Doling, Miss. Elsie",female,18,0,1,231919,23,,S
+653,0,3,"Kalvik, Mr. Johannes Halvorsen",male,21,0,0,8475,8.4333,,S
+654,1,3,"O'Leary, Miss. Hanora ""Norah""",female,,0,0,330919,7.8292,,Q
+655,0,3,"Hegarty, Miss. Hanora ""Nora""",female,18,0,0,365226,6.75,,Q
+656,0,2,"Hickman, Mr. Leonard Mark",male,24,2,0,S.O.C. 14879,73.5,,S
+657,0,3,"Radeff, Mr. Alexander",male,,0,0,349223,7.8958,,S
+658,0,3,"Bourke, Mrs. John (Catherine)",female,32,1,1,364849,15.5,,Q
+659,0,2,"Eitemiller, Mr. George Floyd",male,23,0,0,29751,13,,S
+660,0,1,"Newell, Mr. Arthur Webster",male,58,0,2,35273,113.275,D48,C
+661,1,1,"Frauenthal, Dr. Henry William",male,50,2,0,PC 17611,133.65,,S
+662,0,3,"Badt, Mr. Mohamed",male,40,0,0,2623,7.225,,C
+663,0,1,"Colley, Mr. Edward Pomeroy",male,47,0,0,5727,25.5875,E58,S
+664,0,3,"Coleff, Mr. Peju",male,36,0,0,349210,7.4958,,S
+665,1,3,"Lindqvist, Mr. Eino William",male,20,1,0,STON/O 2. 3101285,7.925,,S
+666,0,2,"Hickman, Mr. Lewis",male,32,2,0,S.O.C. 14879,73.5,,S
+667,0,2,"Butler, Mr. Reginald Fenton",male,25,0,0,234686,13,,S
+668,0,3,"Rommetvedt, Mr. Knud Paust",male,,0,0,312993,7.775,,S
+669,0,3,"Cook, Mr. Jacob",male,43,0,0,A/5 3536,8.05,,S
+670,1,1,"Taylor, Mrs. Elmer Zebley (Juliet Cummins Wright)",female,,1,0,19996,52,C126,S
+671,1,2,"Brown, Mrs. Thomas William Solomon (Elizabeth Catherine Ford)",female,40,1,1,29750,39,,S
+672,0,1,"Davidson, Mr. Thornton",male,31,1,0,F.C. 12750,52,B71,S
+673,0,2,"Mitchell, Mr. Henry Michael",male,70,0,0,C.A. 24580,10.5,,S
+674,1,2,"Wilhelms, Mr. Charles",male,31,0,0,244270,13,,S
+675,0,2,"Watson, Mr. Ennis Hastings",male,,0,0,239856,0,,S
+676,0,3,"Edvardsson, Mr. Gustaf Hjalmar",male,18,0,0,349912,7.775,,S
+677,0,3,"Sawyer, Mr. Frederick Charles",male,24.5,0,0,342826,8.05,,S
+678,1,3,"Turja, Miss. Anna Sofia",female,18,0,0,4138,9.8417,,S
+679,0,3,"Goodwin, Mrs. Frederick (Augusta Tyler)",female,43,1,6,CA 2144,46.9,,S
+680,1,1,"Cardeza, Mr. Thomas Drake Martinez",male,36,0,1,PC 17755,512.3292,B51 B53 B55,C
+681,0,3,"Peters, Miss. Katie",female,,0,0,330935,8.1375,,Q
+682,1,1,"Hassab, Mr. Hammad",male,27,0,0,PC 17572,76.7292,D49,C
+683,0,3,"Olsvigen, Mr. Thor Anderson",male,20,0,0,6563,9.225,,S
+684,0,3,"Goodwin, Mr. Charles Edward",male,14,5,2,CA 2144,46.9,,S
+685,0,2,"Brown, Mr. Thomas William Solomon",male,60,1,1,29750,39,,S
+686,0,2,"Laroche, Mr. Joseph Philippe Lemercier",male,25,1,2,SC/Paris 2123,41.5792,,C
+687,0,3,"Panula, Mr. Jaako Arnold",male,14,4,1,3101295,39.6875,,S
+688,0,3,"Dakic, Mr. Branko",male,19,0,0,349228,10.1708,,S
+689,0,3,"Fischer, Mr. Eberhard Thelander",male,18,0,0,350036,7.7958,,S
+690,1,1,"Madill, Miss. Georgette Alexandra",female,15,0,1,24160,211.3375,B5,S
+691,1,1,"Dick, Mr. Albert Adrian",male,31,1,0,17474,57,B20,S
+692,1,3,"Karun, Miss. Manca",female,4,0,1,349256,13.4167,,C
+693,1,3,"Lam, Mr. Ali",male,,0,0,1601,56.4958,,S
+694,0,3,"Saad, Mr. Khalil",male,25,0,0,2672,7.225,,C
+695,0,1,"Weir, Col. John",male,60,0,0,113800,26.55,,S
+696,0,2,"Chapman, Mr. Charles Henry",male,52,0,0,248731,13.5,,S
+697,0,3,"Kelly, Mr. James",male,44,0,0,363592,8.05,,S
+698,1,3,"Mullens, Miss. Katherine ""Katie""",female,,0,0,35852,7.7333,,Q
+699,0,1,"Thayer, Mr. John Borland",male,49,1,1,17421,110.8833,C68,C
+700,0,3,"Humblen, Mr. Adolf Mathias Nicolai Olsen",male,42,0,0,348121,7.65,F G63,S
+701,1,1,"Astor, Mrs. John Jacob (Madeleine Talmadge Force)",female,18,1,0,PC 17757,227.525,C62 C64,C
+702,1,1,"Silverthorne, Mr. Spencer Victor",male,35,0,0,PC 17475,26.2875,E24,S
+703,0,3,"Barbara, Miss. Saiide",female,18,0,1,2691,14.4542,,C
+704,0,3,"Gallagher, Mr. Martin",male,25,0,0,36864,7.7417,,Q
+705,0,3,"Hansen, Mr. Henrik Juul",male,26,1,0,350025,7.8542,,S
+706,0,2,"Morley, Mr. Henry Samuel (""Mr Henry Marshall"")",male,39,0,0,250655,26,,S
+707,1,2,"Kelly, Mrs. Florence ""Fannie""",female,45,0,0,223596,13.5,,S
+708,1,1,"Calderhead, Mr. Edward Pennington",male,42,0,0,PC 17476,26.2875,E24,S
+709,1,1,"Cleaver, Miss. Alice",female,22,0,0,113781,151.55,,S
+710,1,3,"Moubarek, Master. Halim Gonios (""William George"")",male,,1,1,2661,15.2458,,C
+711,1,1,"Mayne, Mlle. Berthe Antonine (""Mrs de Villiers"")",female,24,0,0,PC 17482,49.5042,C90,C
+712,0,1,"Klaber, Mr. Herman",male,,0,0,113028,26.55,C124,S
+713,1,1,"Taylor, Mr. Elmer Zebley",male,48,1,0,19996,52,C126,S
+714,0,3,"Larsson, Mr. August Viktor",male,29,0,0,7545,9.4833,,S
+715,0,2,"Greenberg, Mr. Samuel",male,52,0,0,250647,13,,S
+716,0,3,"Soholt, Mr. Peter Andreas Lauritz Andersen",male,19,0,0,348124,7.65,F G73,S
+717,1,1,"Endres, Miss. Caroline Louise",female,38,0,0,PC 17757,227.525,C45,C
+718,1,2,"Troutt, Miss. Edwina Celia ""Winnie""",female,27,0,0,34218,10.5,E101,S
+719,0,3,"McEvoy, Mr. Michael",male,,0,0,36568,15.5,,Q
+720,0,3,"Johnson, Mr. Malkolm Joackim",male,33,0,0,347062,7.775,,S
+721,1,2,"Harper, Miss. Annie Jessie ""Nina""",female,6,0,1,248727,33,,S
+722,0,3,"Jensen, Mr. Svend Lauritz",male,17,1,0,350048,7.0542,,S
+723,0,2,"Gillespie, Mr. William Henry",male,34,0,0,12233,13,,S
+724,0,2,"Hodges, Mr. Henry Price",male,50,0,0,250643,13,,S
+725,1,1,"Chambers, Mr. Norman Campbell",male,27,1,0,113806,53.1,E8,S
+726,0,3,"Oreskovic, Mr. Luka",male,20,0,0,315094,8.6625,,S
+727,1,2,"Renouf, Mrs. Peter Henry (Lillian Jefferys)",female,30,3,0,31027,21,,S
+728,1,3,"Mannion, Miss. Margareth",female,,0,0,36866,7.7375,,Q
+729,0,2,"Bryhl, Mr. Kurt Arnold Gottfrid",male,25,1,0,236853,26,,S
+730,0,3,"Ilmakangas, Miss. Pieta Sofia",female,25,1,0,STON/O2. 3101271,7.925,,S
+731,1,1,"Allen, Miss. Elisabeth Walton",female,29,0,0,24160,211.3375,B5,S
+732,0,3,"Hassan, Mr. Houssein G N",male,11,0,0,2699,18.7875,,C
+733,0,2,"Knight, Mr. Robert J",male,,0,0,239855,0,,S
+734,0,2,"Berriman, Mr. William John",male,23,0,0,28425,13,,S
+735,0,2,"Troupiansky, Mr. Moses Aaron",male,23,0,0,233639,13,,S
+736,0,3,"Williams, Mr. Leslie",male,28.5,0,0,54636,16.1,,S
+737,0,3,"Ford, Mrs. Edward (Margaret Ann Watson)",female,48,1,3,W./C. 6608,34.375,,S
+738,1,1,"Lesurer, Mr. Gustave J",male,35,0,0,PC 17755,512.3292,B101,C
+739,0,3,"Ivanoff, Mr. Kanio",male,,0,0,349201,7.8958,,S
+740,0,3,"Nankoff, Mr. Minko",male,,0,0,349218,7.8958,,S
+741,1,1,"Hawksford, Mr. Walter James",male,,0,0,16988,30,D45,S
+742,0,1,"Cavendish, Mr. Tyrell William",male,36,1,0,19877,78.85,C46,S
+743,1,1,"Ryerson, Miss. Susan Parker ""Suzette""",female,21,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+744,0,3,"McNamee, Mr. Neal",male,24,1,0,376566,16.1,,S
+745,1,3,"Stranden, Mr. Juho",male,31,0,0,STON/O 2. 3101288,7.925,,S
+746,0,1,"Crosby, Capt. Edward Gifford",male,70,1,1,WE/P 5735,71,B22,S
+747,0,3,"Abbott, Mr. Rossmore Edward",male,16,1,1,C.A. 2673,20.25,,S
+748,1,2,"Sinkkonen, Miss. Anna",female,30,0,0,250648,13,,S
+749,0,1,"Marvin, Mr. Daniel Warner",male,19,1,0,113773,53.1,D30,S
+750,0,3,"Connaghton, Mr. Michael",male,31,0,0,335097,7.75,,Q
+751,1,2,"Wells, Miss. Joan",female,4,1,1,29103,23,,S
+752,1,3,"Moor, Master. Meier",male,6,0,1,392096,12.475,E121,S
+753,0,3,"Vande Velde, Mr. Johannes Joseph",male,33,0,0,345780,9.5,,S
+754,0,3,"Jonkoff, Mr. Lalio",male,23,0,0,349204,7.8958,,S
+755,1,2,"Herman, Mrs. Samuel (Jane Laver)",female,48,1,2,220845,65,,S
+756,1,2,"Hamalainen, Master. Viljo",male,0.67,1,1,250649,14.5,,S
+757,0,3,"Carlsson, Mr. August Sigfrid",male,28,0,0,350042,7.7958,,S
+758,0,2,"Bailey, Mr. Percy Andrew",male,18,0,0,29108,11.5,,S
+759,0,3,"Theobald, Mr. Thomas Leonard",male,34,0,0,363294,8.05,,S
+760,1,1,"Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)",female,33,0,0,110152,86.5,B77,S
+761,0,3,"Garfirth, Mr. John",male,,0,0,358585,14.5,,S
+762,0,3,"Nirva, Mr. Iisakki Antino Aijo",male,41,0,0,SOTON/O2 3101272,7.125,,S
+763,1,3,"Barah, Mr. Hanna Assi",male,20,0,0,2663,7.2292,,C
+764,1,1,"Carter, Mrs. William Ernest (Lucile Polk)",female,36,1,2,113760,120,B96 B98,S
+765,0,3,"Eklund, Mr. Hans Linus",male,16,0,0,347074,7.775,,S
+766,1,1,"Hogeboom, Mrs. John C (Anna Andrews)",female,51,1,0,13502,77.9583,D11,S
+767,0,1,"Brewe, Dr. Arthur Jackson",male,,0,0,112379,39.6,,C
+768,0,3,"Mangan, Miss. Mary",female,30.5,0,0,364850,7.75,,Q
+769,0,3,"Moran, Mr. Daniel J",male,,1,0,371110,24.15,,Q
+770,0,3,"Gronnestad, Mr. Daniel Danielsen",male,32,0,0,8471,8.3625,,S
+771,0,3,"Lievens, Mr. Rene Aime",male,24,0,0,345781,9.5,,S
+772,0,3,"Jensen, Mr. Niels Peder",male,48,0,0,350047,7.8542,,S
+773,0,2,"Mack, Mrs. (Mary)",female,57,0,0,S.O./P.P. 3,10.5,E77,S
+774,0,3,"Elias, Mr. Dibo",male,,0,0,2674,7.225,,C
+775,1,2,"Hocking, Mrs. Elizabeth (Eliza Needs)",female,54,1,3,29105,23,,S
+776,0,3,"Myhrman, Mr. Pehr Fabian Oliver Malkolm",male,18,0,0,347078,7.75,,S
+777,0,3,"Tobin, Mr. Roger",male,,0,0,383121,7.75,F38,Q
+778,1,3,"Emanuel, Miss. Virginia Ethel",female,5,0,0,364516,12.475,,S
+779,0,3,"Kilgannon, Mr. Thomas J",male,,0,0,36865,7.7375,,Q
+780,1,1,"Robert, Mrs. Edward Scott (Elisabeth Walton McMillan)",female,43,0,1,24160,211.3375,B3,S
+781,1,3,"Ayoub, Miss. Banoura",female,13,0,0,2687,7.2292,,C
+782,1,1,"Dick, Mrs. Albert Adrian (Vera Gillespie)",female,17,1,0,17474,57,B20,S
+783,0,1,"Long, Mr. Milton Clyde",male,29,0,0,113501,30,D6,S
+784,0,3,"Johnston, Mr. Andrew G",male,,1,2,W./C. 6607,23.45,,S
+785,0,3,"Ali, Mr. William",male,25,0,0,SOTON/O.Q. 3101312,7.05,,S
+786,0,3,"Harmer, Mr. Abraham (David Lishin)",male,25,0,0,374887,7.25,,S
+787,1,3,"Sjoblom, Miss. Anna Sofia",female,18,0,0,3101265,7.4958,,S
+788,0,3,"Rice, Master. George Hugh",male,8,4,1,382652,29.125,,Q
+789,1,3,"Dean, Master. Bertram Vere",male,1,1,2,C.A. 2315,20.575,,S
+790,0,1,"Guggenheim, Mr. Benjamin",male,46,0,0,PC 17593,79.2,B82 B84,C
+791,0,3,"Keane, Mr. Andrew ""Andy""",male,,0,0,12460,7.75,,Q
+792,0,2,"Gaskell, Mr. Alfred",male,16,0,0,239865,26,,S
+793,0,3,"Sage, Miss. Stella Anna",female,,8,2,CA. 2343,69.55,,S
+794,0,1,"Hoyt, Mr. William Fisher",male,,0,0,PC 17600,30.6958,,C
+795,0,3,"Dantcheff, Mr. Ristiu",male,25,0,0,349203,7.8958,,S
+796,0,2,"Otter, Mr. Richard",male,39,0,0,28213,13,,S
+797,1,1,"Leader, Dr. Alice (Farnham)",female,49,0,0,17465,25.9292,D17,S
+798,1,3,"Osman, Mrs. Mara",female,31,0,0,349244,8.6833,,S
+799,0,3,"Ibrahim Shawah, Mr. Yousseff",male,30,0,0,2685,7.2292,,C
+800,0,3,"Van Impe, Mrs. Jean Baptiste (Rosalie Paula Govaert)",female,30,1,1,345773,24.15,,S
+801,0,2,"Ponesell, Mr. Martin",male,34,0,0,250647,13,,S
+802,1,2,"Collyer, Mrs. Harvey (Charlotte Annie Tate)",female,31,1,1,C.A. 31921,26.25,,S
+803,1,1,"Carter, Master. William Thornton II",male,11,1,2,113760,120,B96 B98,S
+804,1,3,"Thomas, Master. Assad Alexander",male,0.42,0,1,2625,8.5167,,C
+805,1,3,"Hedman, Mr. Oskar Arvid",male,27,0,0,347089,6.975,,S
+806,0,3,"Johansson, Mr. Karl Johan",male,31,0,0,347063,7.775,,S
+807,0,1,"Andrews, Mr. Thomas Jr",male,39,0,0,112050,0,A36,S
+808,0,3,"Pettersson, Miss. Ellen Natalia",female,18,0,0,347087,7.775,,S
+809,0,2,"Meyer, Mr. August",male,39,0,0,248723,13,,S
+810,1,1,"Chambers, Mrs. Norman Campbell (Bertha Griggs)",female,33,1,0,113806,53.1,E8,S
+811,0,3,"Alexander, Mr. William",male,26,0,0,3474,7.8875,,S
+812,0,3,"Lester, Mr. James",male,39,0,0,A/4 48871,24.15,,S
+813,0,2,"Slemen, Mr. Richard James",male,35,0,0,28206,10.5,,S
+814,0,3,"Andersson, Miss. Ebba Iris Alfrida",female,6,4,2,347082,31.275,,S
+815,0,3,"Tomlin, Mr. Ernest Portage",male,30.5,0,0,364499,8.05,,S
+816,0,1,"Fry, Mr. Richard",male,,0,0,112058,0,B102,S
+817,0,3,"Heininen, Miss. Wendla Maria",female,23,0,0,STON/O2. 3101290,7.925,,S
+818,0,2,"Mallet, Mr. Albert",male,31,1,1,S.C./PARIS 2079,37.0042,,C
+819,0,3,"Holm, Mr. John Fredrik Alexander",male,43,0,0,C 7075,6.45,,S
+820,0,3,"Skoog, Master. Karl Thorsten",male,10,3,2,347088,27.9,,S
+821,1,1,"Hays, Mrs. Charles Melville (Clara Jennings Gregg)",female,52,1,1,12749,93.5,B69,S
+822,1,3,"Lulic, Mr. Nikola",male,27,0,0,315098,8.6625,,S
+823,0,1,"Reuchlin, Jonkheer. John George",male,38,0,0,19972,0,,S
+824,1,3,"Moor, Mrs. (Beila)",female,27,0,1,392096,12.475,E121,S
+825,0,3,"Panula, Master. Urho Abraham",male,2,4,1,3101295,39.6875,,S
+826,0,3,"Flynn, Mr. John",male,,0,0,368323,6.95,,Q
+827,0,3,"Lam, Mr. Len",male,,0,0,1601,56.4958,,S
+828,1,2,"Mallet, Master. Andre",male,1,0,2,S.C./PARIS 2079,37.0042,,C
+829,1,3,"McCormack, Mr. Thomas Joseph",male,,0,0,367228,7.75,,Q
+830,1,1,"Stone, Mrs. George Nelson (Martha Evelyn)",female,62,0,0,113572,80,B28,
+831,1,3,"Yasbeck, Mrs. Antoni (Selini Alexander)",female,15,1,0,2659,14.4542,,C
+832,1,2,"Richards, Master. George Sibley",male,0.83,1,1,29106,18.75,,S
+833,0,3,"Saad, Mr. Amin",male,,0,0,2671,7.2292,,C
+834,0,3,"Augustsson, Mr. Albert",male,23,0,0,347468,7.8542,,S
+835,0,3,"Allum, Mr. Owen George",male,18,0,0,2223,8.3,,S
+836,1,1,"Compton, Miss. Sara Rebecca",female,39,1,1,PC 17756,83.1583,E49,C
+837,0,3,"Pasic, Mr. Jakob",male,21,0,0,315097,8.6625,,S
+838,0,3,"Sirota, Mr. Maurice",male,,0,0,392092,8.05,,S
+839,1,3,"Chip, Mr. Chang",male,32,0,0,1601,56.4958,,S
+840,1,1,"Marechal, Mr. Pierre",male,,0,0,11774,29.7,C47,C
+841,0,3,"Alhomaki, Mr. Ilmari Rudolf",male,20,0,0,SOTON/O2 3101287,7.925,,S
+842,0,2,"Mudd, Mr. Thomas Charles",male,16,0,0,S.O./P.P. 3,10.5,,S
+843,1,1,"Serepeca, Miss. Augusta",female,30,0,0,113798,31,,C
+844,0,3,"Lemberopolous, Mr. Peter L",male,34.5,0,0,2683,6.4375,,C
+845,0,3,"Culumovic, Mr. Jeso",male,17,0,0,315090,8.6625,,S
+846,0,3,"Abbing, Mr. Anthony",male,42,0,0,C.A. 5547,7.55,,S
+847,0,3,"Sage, Mr. Douglas Bullen",male,,8,2,CA. 2343,69.55,,S
+848,0,3,"Markoff, Mr. Marin",male,35,0,0,349213,7.8958,,C
+849,0,2,"Harper, Rev. John",male,28,0,1,248727,33,,S
+850,1,1,"Goldenberg, Mrs. Samuel L (Edwiga Grabowska)",female,,1,0,17453,89.1042,C92,C
+851,0,3,"Andersson, Master. Sigvard Harald Elias",male,4,4,2,347082,31.275,,S
+852,0,3,"Svensson, Mr. Johan",male,74,0,0,347060,7.775,,S
+853,0,3,"Boulos, Miss. Nourelain",female,9,1,1,2678,15.2458,,C
+854,1,1,"Lines, Miss. Mary Conover",female,16,0,1,PC 17592,39.4,D28,S
+855,0,2,"Carter, Mrs. Ernest Courtenay (Lilian Hughes)",female,44,1,0,244252,26,,S
+856,1,3,"Aks, Mrs. Sam (Leah Rosen)",female,18,0,1,392091,9.35,,S
+857,1,1,"Wick, Mrs. George Dennick (Mary Hitchcock)",female,45,1,1,36928,164.8667,,S
+858,1,1,"Daly, Mr. Peter Denis ",male,51,0,0,113055,26.55,E17,S
+859,1,3,"Baclini, Mrs. Solomon (Latifa Qurban)",female,24,0,3,2666,19.2583,,C
+860,0,3,"Razi, Mr. Raihed",male,,0,0,2629,7.2292,,C
+861,0,3,"Hansen, Mr. Claus Peter",male,41,2,0,350026,14.1083,,S
+862,0,2,"Giles, Mr. Frederick Edward",male,21,1,0,28134,11.5,,S
+863,1,1,"Swift, Mrs. Frederick Joel (Margaret Welles Barron)",female,48,0,0,17466,25.9292,D17,S
+864,0,3,"Sage, Miss. Dorothy Edith ""Dolly""",female,,8,2,CA. 2343,69.55,,S
+865,0,2,"Gill, Mr. John William",male,24,0,0,233866,13,,S
+866,1,2,"Bystrom, Mrs. (Karolina)",female,42,0,0,236852,13,,S
+867,1,2,"Duran y More, Miss. Asuncion",female,27,1,0,SC/PARIS 2149,13.8583,,C
+868,0,1,"Roebling, Mr. Washington Augustus II",male,31,0,0,PC 17590,50.4958,A24,S
+869,0,3,"van Melkebeke, Mr. Philemon",male,,0,0,345777,9.5,,S
+870,1,3,"Johnson, Master. Harold Theodor",male,4,1,1,347742,11.1333,,S
+871,0,3,"Balkic, Mr. Cerin",male,26,0,0,349248,7.8958,,S
+872,1,1,"Beckwith, Mrs. Richard Leonard (Sallie Monypeny)",female,47,1,1,11751,52.5542,D35,S
+873,0,1,"Carlsson, Mr. Frans Olof",male,33,0,0,695,5,B51 B53 B55,S
+874,0,3,"Vander Cruyssen, Mr. Victor",male,47,0,0,345765,9,,S
+875,1,2,"Abelson, Mrs. Samuel (Hannah Wizosky)",female,28,1,0,P/PP 3381,24,,C
+876,1,3,"Najib, Miss. Adele Kiamie ""Jane""",female,15,0,0,2667,7.225,,C
+877,0,3,"Gustafsson, Mr. Alfred Ossian",male,20,0,0,7534,9.8458,,S
+878,0,3,"Petroff, Mr. Nedelio",male,19,0,0,349212,7.8958,,S
+879,0,3,"Laleff, Mr. Kristo",male,,0,0,349217,7.8958,,S
+880,1,1,"Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)",female,56,0,1,11767,83.1583,C50,C
+881,1,2,"Shelley, Mrs. William (Imanita Parrish Hall)",female,25,0,1,230433,26,,S
+882,0,3,"Markun, Mr. Johann",male,33,0,0,349257,7.8958,,S
+883,0,3,"Dahlberg, Miss. Gerda Ulrika",female,22,0,0,7552,10.5167,,S
+884,0,2,"Banfield, Mr. Frederick James",male,28,0,0,C.A./SOTON 34068,10.5,,S
+885,0,3,"Sutehall, Mr. Henry Jr",male,25,0,0,SOTON/OQ 392076,7.05,,S
+886,0,3,"Rice, Mrs. William (Margaret Norton)",female,39,0,5,382652,29.125,,Q
+887,0,2,"Montvila, Rev. Juozas",male,27,0,0,211536,13,,S
+888,1,1,"Graham, Miss. Margaret Edith",female,19,0,0,112053,30,B42,S
+889,0,3,"Johnston, Miss. Catherine Helen ""Carrie""",female,,1,2,W./C. 6607,23.45,,S
+890,1,1,"Behr, Mr. Karl Howell",male,26,0,0,111369,30,C148,C
+891,0,3,"Dooley, Mr. Patrick",male,32,0,0,370376,7.75,,Q
diff --git a/demo/dataset/files/world.mp4 b/demo/dataset/files/world.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..9bce44c33e275d6107240a1101032a7835fd8eed
--- /dev/null
+++ b/demo/dataset/files/world.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:71944d7430c461f0cd6e7fd10cee7eb72786352a3678fc7bc0ae3d410f72aece
+size 1570024
diff --git a/demo/dataset/run.ipynb b/demo/dataset/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ec1863e03c0ad8d03d7d6f88347850a33a4074b8
--- /dev/null
+++ b/demo/dataset/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataset"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/Bunny.obj https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/Bunny.obj\n", "!wget -q -O files/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/cantina.wav\n", "!wget -q -O files/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/cheetah1.jpg\n", "!wget -q -O files/time.csv https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/time.csv\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/titanic.csv\n", "!wget -q -O files/world.mp4 https://github.com/gradio-app/gradio/raw/main/demo/dataset/files/world.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import numpy as np\n", "\n", "\n", "txt = \"the quick brown fox\"\n", "num = 10\n", "\n", "img = os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\")\n", "vid = os.path.join(os.path.abspath(''), \"files/world.mp4\")\n", "audio = os.path.join(os.path.abspath(''), \"files/cantina.wav\")\n", "csv = os.path.join(os.path.abspath(''), \"files/time.csv\")\n", "model = os.path.join(os.path.abspath(''), \"files/Bunny.obj\")\n", "\n", "dataframe = [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 1, 2], [3, 4, 5, 6]]\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"# Dataset previews\")\n", " a = gr.Audio(visible=False)\n", " gr.Dataset(\n", " components=[a],\n", " label=\"Audio\",\n", " samples=[\n", " [audio],\n", " [audio],\n", " [audio],\n", " [audio],\n", " [audio],\n", " [audio],\n", " ],\n", " )\n", " c = gr.Checkbox(visible=False)\n", " gr.Dataset(\n", " label=\"Checkbox\",\n", " components=[c],\n", " samples=[[True], [True], [False], [True], [False], [False]],\n", " )\n", "\n", " c_2 = gr.CheckboxGroup(visible=False, choices=['a', 'b', 'c'])\n", " gr.Dataset(\n", " label=\"CheckboxGroup\",\n", " components=[c_2],\n", " samples=[\n", " [[\"a\"]],\n", " [[\"a\", \"b\"]],\n", " [[\"a\", \"b\", \"c\"]],\n", " [[\"b\"]],\n", " [[\"c\"]],\n", " [[\"a\", \"c\"]],\n", " ],\n", " )\n", " c_3 = gr.ColorPicker(visible=False)\n", " gr.Dataset(\n", " label=\"ColorPicker\",\n", " components=[c_3],\n", " samples=[\n", " [\"#FFFFFF\"],\n", " [\"#000000\"],\n", " [\"#FFFFFF\"],\n", " [\"#000000\"],\n", " [\"#FFFFFF\"],\n", " [\"#000000\"],\n", " ],\n", " )\n", " d = gr.DataFrame(visible=False)\n", " gr.Dataset(\n", " components=[d],\n", " label=\"Dataframe\",\n", " samples=[\n", " [np.zeros((3, 3)).tolist()],\n", " [np.ones((2, 2)).tolist()],\n", " [np.random.randint(0, 10, (3, 10)).tolist()],\n", " [np.random.randint(0, 10, (10, 3)).tolist()],\n", " [np.random.randint(0, 10, (10, 10)).tolist()],\n", " ],\n", " )\n", " d_2 = gr.Dropdown(visible=False, choices=[\"one\", \"two\", \"three\"])\n", " gr.Dataset(\n", " components=[d_2],\n", " label=\"Dropdown\",\n", " samples=[[\"one\"], [\"two\"], [\"three\"], [\"one\"], [\"two\"], [\"three\"]],\n", " )\n", " f = gr.File(visible=False)\n", " gr.Dataset(\n", " components=[f],\n", " label=\"File\",\n", " samples=[\n", " [csv],\n", " [csv],\n", " [csv],\n", " [csv],\n", " [csv],\n", " [csv],\n", " ],\n", " )\n", " h = gr.HTML(visible=False)\n", " gr.Dataset(\n", " components=[h],\n", " label=\"HTML\",\n", " samples=[\n", " [\"hi\"],\n", " [\"hi\"],\n", " [\"hi\"],\n", " [\"hi\"],\n", " [\"hi\"],\n", " [\"hi\"],\n", " ],\n", " )\n", " i = gr.Image(visible=False)\n", " gr.Dataset(\n", " components=[i],\n", " label=\"Image\",\n", " samples=[[img], [img], [img], [img], [img], [img]],\n", " )\n", " m = gr.Markdown(visible=False)\n", " gr.Dataset(\n", " components=[m],\n", " label=\"Markdown\",\n", " samples=[\n", " [\"# hi\"],\n", " [\"# hi\"],\n", " [\"# hi\"],\n", " [\"# hi\"],\n", " [\"# hi\"],\n", " [\"# hi\"],\n", " ],\n", " )\n", " m_2 = gr.Model3D(visible=False)\n", " gr.Dataset(\n", " components=[m_2],\n", " label=\"Model3D\",\n", " samples=[[model], [model], [model], [model], [model], [model]],\n", " )\n", " n = gr.Number(visible=False)\n", " gr.Dataset(\n", " label=\"Number\",\n", " components=[n],\n", " samples=[[1], [1], [1], [1], [1], [1]],\n", " )\n", " r = gr.Radio(visible=False, choices=[\"one\", \"two\", \"three\"])\n", " gr.Dataset(\n", " components=[r],\n", " label=\"Radio\",\n", " samples=[[\"one\"], [\"two\"], [\"three\"], [\"one\"], [\"two\"], [\"three\"]],\n", " )\n", " s = gr.Slider(visible=False)\n", " gr.Dataset(\n", " label=\"Slider\",\n", " components=[s],\n", " samples=[[1], [1], [1], [1], [1], [1]],\n", " )\n", " t = gr.Textbox(visible=False)\n", " gr.Dataset(\n", " label=\"Textbox\",\n", " components=[t],\n", " samples=[\n", " [\"Some value\"],\n", " [\"Some value\"],\n", " [\"Some value\"],\n", " [\"Some value\"],\n", " [\"Some value\"],\n", " [\"Some value\"],\n", " ],\n", " )\n", " v = gr.Video(visible=False)\n", " gr.Dataset(\n", " components=[v],\n", " label=\"Video\",\n", " samples=[[vid], [vid], [vid], [vid], [vid], [vid]],\n", " )\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataset/run.py b/demo/dataset/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c03f84df9582bdf969cecab7c961975ab92a8798
--- /dev/null
+++ b/demo/dataset/run.py
@@ -0,0 +1,174 @@
+import gradio as gr
+import os
+import numpy as np
+
+
+txt = "the quick brown fox"
+num = 10
+
+img = os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg")
+vid = os.path.join(os.path.dirname(__file__), "files/world.mp4")
+audio = os.path.join(os.path.dirname(__file__), "files/cantina.wav")
+csv = os.path.join(os.path.dirname(__file__), "files/time.csv")
+model = os.path.join(os.path.dirname(__file__), "files/Bunny.obj")
+
+dataframe = [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 1, 2], [3, 4, 5, 6]]
+
+with gr.Blocks() as demo:
+ gr.Markdown("# Dataset previews")
+ a = gr.Audio(visible=False)
+ gr.Dataset(
+ components=[a],
+ label="Audio",
+ samples=[
+ [audio],
+ [audio],
+ [audio],
+ [audio],
+ [audio],
+ [audio],
+ ],
+ )
+ c = gr.Checkbox(visible=False)
+ gr.Dataset(
+ label="Checkbox",
+ components=[c],
+ samples=[[True], [True], [False], [True], [False], [False]],
+ )
+
+ c_2 = gr.CheckboxGroup(visible=False, choices=['a', 'b', 'c'])
+ gr.Dataset(
+ label="CheckboxGroup",
+ components=[c_2],
+ samples=[
+ [["a"]],
+ [["a", "b"]],
+ [["a", "b", "c"]],
+ [["b"]],
+ [["c"]],
+ [["a", "c"]],
+ ],
+ )
+ c_3 = gr.ColorPicker(visible=False)
+ gr.Dataset(
+ label="ColorPicker",
+ components=[c_3],
+ samples=[
+ ["#FFFFFF"],
+ ["#000000"],
+ ["#FFFFFF"],
+ ["#000000"],
+ ["#FFFFFF"],
+ ["#000000"],
+ ],
+ )
+ d = gr.DataFrame(visible=False)
+ gr.Dataset(
+ components=[d],
+ label="Dataframe",
+ samples=[
+ [np.zeros((3, 3)).tolist()],
+ [np.ones((2, 2)).tolist()],
+ [np.random.randint(0, 10, (3, 10)).tolist()],
+ [np.random.randint(0, 10, (10, 3)).tolist()],
+ [np.random.randint(0, 10, (10, 10)).tolist()],
+ ],
+ )
+ d_2 = gr.Dropdown(visible=False, choices=["one", "two", "three"])
+ gr.Dataset(
+ components=[d_2],
+ label="Dropdown",
+ samples=[["one"], ["two"], ["three"], ["one"], ["two"], ["three"]],
+ )
+ f = gr.File(visible=False)
+ gr.Dataset(
+ components=[f],
+ label="File",
+ samples=[
+ [csv],
+ [csv],
+ [csv],
+ [csv],
+ [csv],
+ [csv],
+ ],
+ )
+ h = gr.HTML(visible=False)
+ gr.Dataset(
+ components=[h],
+ label="HTML",
+ samples=[
+ ["hi"],
+ ["hi"],
+ ["hi"],
+ ["hi"],
+ ["hi"],
+ ["hi"],
+ ],
+ )
+ i = gr.Image(visible=False)
+ gr.Dataset(
+ components=[i],
+ label="Image",
+ samples=[[img], [img], [img], [img], [img], [img]],
+ )
+ m = gr.Markdown(visible=False)
+ gr.Dataset(
+ components=[m],
+ label="Markdown",
+ samples=[
+ ["# hi"],
+ ["# hi"],
+ ["# hi"],
+ ["# hi"],
+ ["# hi"],
+ ["# hi"],
+ ],
+ )
+ m_2 = gr.Model3D(visible=False)
+ gr.Dataset(
+ components=[m_2],
+ label="Model3D",
+ samples=[[model], [model], [model], [model], [model], [model]],
+ )
+ n = gr.Number(visible=False)
+ gr.Dataset(
+ label="Number",
+ components=[n],
+ samples=[[1], [1], [1], [1], [1], [1]],
+ )
+ r = gr.Radio(visible=False, choices=["one", "two", "three"])
+ gr.Dataset(
+ components=[r],
+ label="Radio",
+ samples=[["one"], ["two"], ["three"], ["one"], ["two"], ["three"]],
+ )
+ s = gr.Slider(visible=False)
+ gr.Dataset(
+ label="Slider",
+ components=[s],
+ samples=[[1], [1], [1], [1], [1], [1]],
+ )
+ t = gr.Textbox(visible=False)
+ gr.Dataset(
+ label="Textbox",
+ components=[t],
+ samples=[
+ ["Some value"],
+ ["Some value"],
+ ["Some value"],
+ ["Some value"],
+ ["Some value"],
+ ["Some value"],
+ ],
+ )
+ v = gr.Video(visible=False)
+ gr.Dataset(
+ components=[v],
+ label="Video",
+ samples=[[vid], [vid], [vid], [vid], [vid], [vid]],
+ )
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/dataset_component/run.ipynb b/demo/dataset_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..00645124315cd7486d427e7e2010f943096c9345
--- /dev/null
+++ b/demo/dataset_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataset_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Dataset(components=[gr.Textbox(visible=False)],\n", " label=\"Text Dataset\",\n", " samples=[\n", " [\"The quick brown fox jumps over the lazy dog\"],\n", " [\"Build & share delightful machine learning apps\"],\n", " [\"She sells seashells by the seashore\"],\n", " [\"Supercalifragilisticexpialidocious\"],\n", " [\"Lorem ipsum\"],\n", " [\"That's all folks!\"]\n", " ],\n", " )\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dataset_component/run.py b/demo/dataset_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2f8715c16821835f96e01bb10eb01d65f9003ec
--- /dev/null
+++ b/demo/dataset_component/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Dataset(components=[gr.Textbox(visible=False)],
+ label="Text Dataset",
+ samples=[
+ ["The quick brown fox jumps over the lazy dog"],
+ ["Build & share delightful machine learning apps"],
+ ["She sells seashells by the seashore"],
+ ["Supercalifragilisticexpialidocious"],
+ ["Lorem ipsum"],
+ ["That's all folks!"]
+ ],
+ )
+demo.launch()
\ No newline at end of file
diff --git a/demo/depth_estimation/DESCRIPTION.md b/demo/depth_estimation/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..ae8ed89df7f6c687b0bbd5cd75d22a6393972786
--- /dev/null
+++ b/demo/depth_estimation/DESCRIPTION.md
@@ -0,0 +1 @@
+A demo for predicting the depth of an image and generating a 3D model of it.
\ No newline at end of file
diff --git a/demo/depth_estimation/examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg b/demo/depth_estimation/examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..811c1744a482b8a25e2f797bb89d42855c71c4ea
Binary files /dev/null and b/demo/depth_estimation/examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg differ
diff --git a/demo/depth_estimation/packages.txt b/demo/depth_estimation/packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a72c3b87c81fa656ec198458485c0f6b4f7df89a
--- /dev/null
+++ b/demo/depth_estimation/packages.txt
@@ -0,0 +1 @@
+libgl1-mesa-glx
\ No newline at end of file
diff --git a/demo/depth_estimation/requirements.txt b/demo/depth_estimation/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2523321b8abade09ec342ba0a79af3a9febf5ac0
--- /dev/null
+++ b/demo/depth_estimation/requirements.txt
@@ -0,0 +1,6 @@
+torch
+git+https://github.com/nielsrogge/transformers.git@add_dpt_redesign#egg=transformers
+numpy
+Pillow
+jinja2
+open3d
\ No newline at end of file
diff --git a/demo/depth_estimation/run.ipynb b/demo/depth_estimation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d2cd8cef6811533fb0625f8eefd06b4219e00a81
--- /dev/null
+++ b/demo/depth_estimation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: depth_estimation\n", "### A demo for predicting the depth of an image and generating a 3D model of it.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch git+https://github.com/nielsrogge/transformers.git@add_dpt_redesign#egg=transformers numpy Pillow jinja2 open3d"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('examples')\n", "!wget -q -O examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg https://github.com/gradio-app/gradio/raw/main/demo/depth_estimation/examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/depth_estimation/packages.txt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import DPTFeatureExtractor, DPTForDepthEstimation\n", "import torch\n", "import numpy as np\n", "from PIL import Image\n", "import open3d as o3d\n", "from pathlib import Path\n", "\n", "feature_extractor = DPTFeatureExtractor.from_pretrained(\"Intel/dpt-large\")\n", "model = DPTForDepthEstimation.from_pretrained(\"Intel/dpt-large\")\n", "\n", "def process_image(image_path):\n", " image_path = Path(image_path)\n", " image_raw = Image.open(image_path)\n", " image = image_raw.resize(\n", " (800, int(800 * image_raw.size[1] / image_raw.size[0])),\n", " Image.Resampling.LANCZOS)\n", "\n", " # prepare image for the model\n", " encoding = feature_extractor(image, return_tensors=\"pt\")\n", "\n", " # forward pass\n", " with torch.no_grad():\n", " outputs = model(**encoding)\n", " predicted_depth = outputs.predicted_depth\n", "\n", " # interpolate to original size\n", " prediction = torch.nn.functional.interpolate(\n", " predicted_depth.unsqueeze(1),\n", " size=image.size[::-1],\n", " mode=\"bicubic\",\n", " align_corners=False,\n", " ).squeeze()\n", " output = prediction.cpu().numpy()\n", " depth_image = (output * 255 / np.max(output)).astype('uint8')\n", " try:\n", " gltf_path = create_3d_obj(np.array(image), depth_image, image_path)\n", " img = Image.fromarray(depth_image)\n", " return [img, gltf_path, gltf_path]\n", " except Exception:\n", " gltf_path = create_3d_obj(\n", " np.array(image), depth_image, image_path, depth=8)\n", " img = Image.fromarray(depth_image)\n", " return [img, gltf_path, gltf_path]\n", " except:\n", " print(\"Error reconstructing 3D model\")\n", " raise Exception(\"Error reconstructing 3D model\")\n", "\n", "\n", "def create_3d_obj(rgb_image, depth_image, image_path, depth=10):\n", " depth_o3d = o3d.geometry.Image(depth_image)\n", " image_o3d = o3d.geometry.Image(rgb_image)\n", " rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(\n", " image_o3d, depth_o3d, convert_rgb_to_intensity=False)\n", " w = int(depth_image.shape[1])\n", " h = int(depth_image.shape[0])\n", "\n", " camera_intrinsic = o3d.camera.PinholeCameraIntrinsic()\n", " camera_intrinsic.set_intrinsics(w, h, 500, 500, w/2, h/2)\n", "\n", " pcd = o3d.geometry.PointCloud.create_from_rgbd_image(\n", " rgbd_image, camera_intrinsic)\n", "\n", " print('normals')\n", " pcd.normals = o3d.utility.Vector3dVector(\n", " np.zeros((1, 3))) # invalidate existing normals\n", " pcd.estimate_normals(\n", " search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30))\n", " pcd.orient_normals_towards_camera_location(\n", " camera_location=np.array([0., 0., 1000.]))\n", " pcd.transform([[1, 0, 0, 0],\n", " [0, -1, 0, 0],\n", " [0, 0, -1, 0],\n", " [0, 0, 0, 1]])\n", " pcd.transform([[-1, 0, 0, 0],\n", " [0, 1, 0, 0],\n", " [0, 0, 1, 0],\n", " [0, 0, 0, 1]])\n", "\n", " print('run Poisson surface reconstruction')\n", " with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug):\n", " mesh_raw, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(\n", " pcd, depth=depth, width=0, scale=1.1, linear_fit=True)\n", "\n", " voxel_size = max(mesh_raw.get_max_bound() - mesh_raw.get_min_bound()) / 256\n", " print(f'voxel_size = {voxel_size:e}')\n", " mesh = mesh_raw.simplify_vertex_clustering(\n", " voxel_size=voxel_size,\n", " contraction=o3d.geometry.SimplificationContraction.Average)\n", "\n", " # vertices_to_remove = densities < np.quantile(densities, 0.001)\n", " # mesh.remove_vertices_by_mask(vertices_to_remove)\n", " bbox = pcd.get_axis_aligned_bounding_box()\n", " mesh_crop = mesh.crop(bbox)\n", " gltf_path = f'./{image_path.stem}.gltf'\n", " o3d.io.write_triangle_mesh(\n", " gltf_path, mesh_crop, write_triangle_uvs=True)\n", " return gltf_path\n", "\n", "title = \"Demo: zero-shot depth estimation with DPT + 3D Point Cloud\"\n", "description = \"This demo is a variation from the original DPT Demo . It uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object.\"\n", "examples = [[\"examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg\"]]\n", "\n", "iface = gr.Interface(fn=process_image,\n", " inputs=[gr.Image(\n", " type=\"filepath\", label=\"Input Image\")],\n", " outputs=[gr.Image(label=\"predicted depth\", type=\"pil\"),\n", " gr.Model3D(label=\"3d mesh reconstruction\", clear_color=[\n", " 1.0, 1.0, 1.0, 1.0]),\n", " gr.File(label=\"3d gLTF\")],\n", " title=title,\n", " description=description,\n", " examples=examples,\n", " allow_flagging=\"never\",\n", " cache_examples=False)\n", "\n", "iface.launch(debug=True)"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/depth_estimation/run.py b/demo/depth_estimation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..147ef06df8b234c950d10d40d3e111f0d2b22384
--- /dev/null
+++ b/demo/depth_estimation/run.py
@@ -0,0 +1,117 @@
+import gradio as gr
+from transformers import DPTFeatureExtractor, DPTForDepthEstimation
+import torch
+import numpy as np
+from PIL import Image
+import open3d as o3d
+from pathlib import Path
+
+feature_extractor = DPTFeatureExtractor.from_pretrained("Intel/dpt-large")
+model = DPTForDepthEstimation.from_pretrained("Intel/dpt-large")
+
+def process_image(image_path):
+ image_path = Path(image_path)
+ image_raw = Image.open(image_path)
+ image = image_raw.resize(
+ (800, int(800 * image_raw.size[1] / image_raw.size[0])),
+ Image.Resampling.LANCZOS)
+
+ # prepare image for the model
+ encoding = feature_extractor(image, return_tensors="pt")
+
+ # forward pass
+ with torch.no_grad():
+ outputs = model(**encoding)
+ predicted_depth = outputs.predicted_depth
+
+ # interpolate to original size
+ prediction = torch.nn.functional.interpolate(
+ predicted_depth.unsqueeze(1),
+ size=image.size[::-1],
+ mode="bicubic",
+ align_corners=False,
+ ).squeeze()
+ output = prediction.cpu().numpy()
+ depth_image = (output * 255 / np.max(output)).astype('uint8')
+ try:
+ gltf_path = create_3d_obj(np.array(image), depth_image, image_path)
+ img = Image.fromarray(depth_image)
+ return [img, gltf_path, gltf_path]
+ except Exception:
+ gltf_path = create_3d_obj(
+ np.array(image), depth_image, image_path, depth=8)
+ img = Image.fromarray(depth_image)
+ return [img, gltf_path, gltf_path]
+ except:
+ print("Error reconstructing 3D model")
+ raise Exception("Error reconstructing 3D model")
+
+
+def create_3d_obj(rgb_image, depth_image, image_path, depth=10):
+ depth_o3d = o3d.geometry.Image(depth_image)
+ image_o3d = o3d.geometry.Image(rgb_image)
+ rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(
+ image_o3d, depth_o3d, convert_rgb_to_intensity=False)
+ w = int(depth_image.shape[1])
+ h = int(depth_image.shape[0])
+
+ camera_intrinsic = o3d.camera.PinholeCameraIntrinsic()
+ camera_intrinsic.set_intrinsics(w, h, 500, 500, w/2, h/2)
+
+ pcd = o3d.geometry.PointCloud.create_from_rgbd_image(
+ rgbd_image, camera_intrinsic)
+
+ print('normals')
+ pcd.normals = o3d.utility.Vector3dVector(
+ np.zeros((1, 3))) # invalidate existing normals
+ pcd.estimate_normals(
+ search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30))
+ pcd.orient_normals_towards_camera_location(
+ camera_location=np.array([0., 0., 1000.]))
+ pcd.transform([[1, 0, 0, 0],
+ [0, -1, 0, 0],
+ [0, 0, -1, 0],
+ [0, 0, 0, 1]])
+ pcd.transform([[-1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, 0],
+ [0, 0, 0, 1]])
+
+ print('run Poisson surface reconstruction')
+ with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug):
+ mesh_raw, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
+ pcd, depth=depth, width=0, scale=1.1, linear_fit=True)
+
+ voxel_size = max(mesh_raw.get_max_bound() - mesh_raw.get_min_bound()) / 256
+ print(f'voxel_size = {voxel_size:e}')
+ mesh = mesh_raw.simplify_vertex_clustering(
+ voxel_size=voxel_size,
+ contraction=o3d.geometry.SimplificationContraction.Average)
+
+ # vertices_to_remove = densities < np.quantile(densities, 0.001)
+ # mesh.remove_vertices_by_mask(vertices_to_remove)
+ bbox = pcd.get_axis_aligned_bounding_box()
+ mesh_crop = mesh.crop(bbox)
+ gltf_path = f'./{image_path.stem}.gltf'
+ o3d.io.write_triangle_mesh(
+ gltf_path, mesh_crop, write_triangle_uvs=True)
+ return gltf_path
+
+title = "Demo: zero-shot depth estimation with DPT + 3D Point Cloud"
+description = "This demo is a variation from the original DPT Demo . It uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object."
+examples = [["examples/1-jonathan-borba-CgWTqYxHEkg-unsplash.jpg"]]
+
+iface = gr.Interface(fn=process_image,
+ inputs=[gr.Image(
+ type="filepath", label="Input Image")],
+ outputs=[gr.Image(label="predicted depth", type="pil"),
+ gr.Model3D(label="3d mesh reconstruction", clear_color=[
+ 1.0, 1.0, 1.0, 1.0]),
+ gr.File(label="3d gLTF")],
+ title=title,
+ description=description,
+ examples=examples,
+ allow_flagging="never",
+ cache_examples=False)
+
+iface.launch(debug=True)
\ No newline at end of file
diff --git a/demo/diff_texts/run.ipynb b/demo/diff_texts/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..44143c71cfc3dba3f79ff78a5bdc7bbd3defe27b
--- /dev/null
+++ b/demo/diff_texts/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: diff_texts"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from difflib import Differ\n", "\n", "import gradio as gr\n", "\n", "\n", "def diff_texts(text1, text2):\n", " d = Differ()\n", " return [\n", " (token[2:], token[0] if token[0] != \" \" else None)\n", " for token in d.compare(text1, text2)\n", " ]\n", "\n", "\n", "demo = gr.Interface(\n", " diff_texts,\n", " [\n", " gr.Textbox(\n", " label=\"Text 1\",\n", " info=\"Initial text\",\n", " lines=3,\n", " value=\"The quick brown fox jumped over the lazy dogs.\",\n", " ),\n", " gr.Textbox(\n", " label=\"Text 2\",\n", " info=\"Text to compare\",\n", " lines=3,\n", " value=\"The fast brown fox jumps over lazy dogs.\",\n", " ),\n", " ],\n", " gr.HighlightedText(\n", " label=\"Diff\",\n", " combine_adjacent=True,\n", " show_legend=True,\n", " color_map={\"+\": \"red\", \"-\": \"green\"}),\n", " theme=gr.themes.Base()\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/diff_texts/run.py b/demo/diff_texts/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..badf25a0d7c894cf1a77506e8affefd6454a4011
--- /dev/null
+++ b/demo/diff_texts/run.py
@@ -0,0 +1,38 @@
+from difflib import Differ
+
+import gradio as gr
+
+
+def diff_texts(text1, text2):
+ d = Differ()
+ return [
+ (token[2:], token[0] if token[0] != " " else None)
+ for token in d.compare(text1, text2)
+ ]
+
+
+demo = gr.Interface(
+ diff_texts,
+ [
+ gr.Textbox(
+ label="Text 1",
+ info="Initial text",
+ lines=3,
+ value="The quick brown fox jumped over the lazy dogs.",
+ ),
+ gr.Textbox(
+ label="Text 2",
+ info="Text to compare",
+ lines=3,
+ value="The fast brown fox jumps over lazy dogs.",
+ ),
+ ],
+ gr.HighlightedText(
+ label="Diff",
+ combine_adjacent=True,
+ show_legend=True,
+ color_map={"+": "red", "-": "green"}),
+ theme=gr.themes.Base()
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/diff_texts/screenshot.png b/demo/diff_texts/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfa051f58bd8a49ccb0ddfc491794c75c68b836f
Binary files /dev/null and b/demo/diff_texts/screenshot.png differ
diff --git a/demo/diffusers_with_batching/requirements.txt b/demo/diffusers_with_batching/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b6ca9fbe3cf454a9f4ff4e46b8f392f8ae6bcc18
--- /dev/null
+++ b/demo/diffusers_with_batching/requirements.txt
@@ -0,0 +1,3 @@
+torch
+transformers
+diffusers
\ No newline at end of file
diff --git a/demo/diffusers_with_batching/run.ipynb b/demo/diffusers_with_batching/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..03fd6cbc7afc7bc69f08f3fdfef690a2c9a88c42
--- /dev/null
+++ b/demo/diffusers_with_batching/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: diffusers_with_batching"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers diffusers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import torch\n", "from diffusers import DiffusionPipeline\n", "import gradio as gr\n", "\n", "generator = DiffusionPipeline.from_pretrained(\"CompVis/ldm-text2im-large-256\")\n", "# move to GPU if available\n", "if torch.cuda.is_available():\n", " generator = generator.to(\"cuda\")\n", "\n", "def generate(prompts):\n", " images = generator(list(prompts)).images\n", " return [images]\n", "\n", "demo = gr.Interface(generate, \n", " \"textbox\", \n", " \"image\", \n", " batch=True, \n", " max_batch_size=4 # Set the batch size based on your CPU/GPU memory\n", ").queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/diffusers_with_batching/run.py b/demo/diffusers_with_batching/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6923d1c78bd00336ac44690cfb2ac2b0ad5b0292
--- /dev/null
+++ b/demo/diffusers_with_batching/run.py
@@ -0,0 +1,22 @@
+import torch
+from diffusers import DiffusionPipeline
+import gradio as gr
+
+generator = DiffusionPipeline.from_pretrained("CompVis/ldm-text2im-large-256")
+# move to GPU if available
+if torch.cuda.is_available():
+ generator = generator.to("cuda")
+
+def generate(prompts):
+ images = generator(list(prompts)).images
+ return [images]
+
+demo = gr.Interface(generate,
+ "textbox",
+ "image",
+ batch=True,
+ max_batch_size=4 # Set the batch size based on your CPU/GPU memory
+).queue()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/digit_classifier/requirements.txt b/demo/digit_classifier/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b3a60b6da25b54d3e1a3696814eed57ef4ef62b7
--- /dev/null
+++ b/demo/digit_classifier/requirements.txt
@@ -0,0 +1 @@
+tensorflow
\ No newline at end of file
diff --git a/demo/digit_classifier/run.ipynb b/demo/digit_classifier/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..fc8c772e6eab37666d6477ee0ccd0b3c7aa28ce2
--- /dev/null
+++ b/demo/digit_classifier/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: digit_classifier"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio tensorflow"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from urllib.request import urlretrieve\n", "\n", "import tensorflow as tf\n", "\n", "import gradio as gr\n", "\n", "urlretrieve(\n", " \"https://gr-models.s3-us-west-2.amazonaws.com/mnist-model.h5\", \"mnist-model.h5\"\n", ")\n", "model = tf.keras.models.load_model(\"mnist-model.h5\")\n", "\n", "\n", "def recognize_digit(image):\n", " image = image.reshape(1, -1)\n", " prediction = model.predict(image).tolist()[0]\n", " return {str(i): prediction[i] for i in range(10)}\n", "\n", "\n", "im = gr.Image(shape=(28, 28), image_mode=\"L\", invert_colors=False, source=\"canvas\")\n", "\n", "demo = gr.Interface(\n", " recognize_digit,\n", " im,\n", " gr.Label(num_top_classes=3),\n", " live=True,\n", " capture_session=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/digit_classifier/run.py b/demo/digit_classifier/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..74a35f669b5e7af255df9b52327f7ca42755e51a
--- /dev/null
+++ b/demo/digit_classifier/run.py
@@ -0,0 +1,30 @@
+from urllib.request import urlretrieve
+
+import tensorflow as tf
+
+import gradio as gr
+
+urlretrieve(
+ "https://gr-models.s3-us-west-2.amazonaws.com/mnist-model.h5", "mnist-model.h5"
+)
+model = tf.keras.models.load_model("mnist-model.h5")
+
+
+def recognize_digit(image):
+ image = image.reshape(1, -1)
+ prediction = model.predict(image).tolist()[0]
+ return {str(i): prediction[i] for i in range(10)}
+
+
+im = gr.Image(shape=(28, 28), image_mode="L", invert_colors=False, source="canvas")
+
+demo = gr.Interface(
+ recognize_digit,
+ im,
+ gr.Label(num_top_classes=3),
+ live=True,
+ capture_session=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/digit_classifier/screenshot.png b/demo/digit_classifier/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f80f61cb13e05f2a7996ec2127beef4289ece3b
Binary files /dev/null and b/demo/digit_classifier/screenshot.png differ
diff --git a/demo/dropdown_component/run.ipynb b/demo/dropdown_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b4fe8baf63f6d49756de7741f43495287afe4636
--- /dev/null
+++ b/demo/dropdown_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dropdown_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Dropdown(choices=[\"First Choice\", \"Second Choice\", \"Third Choice\"])\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/dropdown_component/run.py b/demo/dropdown_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c6b9296198bcc8c8461038dcb19f52a8efe7e6a
--- /dev/null
+++ b/demo/dropdown_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Dropdown(choices=["First Choice", "Second Choice", "Third Choice"])
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/duplicatebutton_component/run.ipynb b/demo/duplicatebutton_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..af5cb73164434fe6d1b15fc9de676415cacf8457
--- /dev/null
+++ b/demo/duplicatebutton_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: duplicatebutton_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.DuplicateButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/duplicatebutton_component/run.py b/demo/duplicatebutton_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8f3146847373df6b76dc53df4b6f2267211ac38
--- /dev/null
+++ b/demo/duplicatebutton_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.DuplicateButton()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/english_translator/requirements.txt b/demo/english_translator/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4803a9a0e9ae8187b540e01e595e7d10bb49968d
--- /dev/null
+++ b/demo/english_translator/requirements.txt
@@ -0,0 +1,2 @@
+transformers
+torch
\ No newline at end of file
diff --git a/demo/english_translator/run.ipynb b/demo/english_translator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..eb3f9893220d21a110207a07fc129679124735c7
--- /dev/null
+++ b/demo/english_translator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: english_translator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio transformers torch"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "from transformers import pipeline\n", "\n", "pipe = pipeline(\"translation\", model=\"t5-base\")\n", "\n", "\n", "def translate(text):\n", " return pipe(text)[0][\"translation_text\"]\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " english = gr.Textbox(label=\"English text\")\n", " translate_btn = gr.Button(value=\"Translate\")\n", " with gr.Column():\n", " german = gr.Textbox(label=\"German Text\")\n", "\n", " translate_btn.click(translate, inputs=english, outputs=german, api_name=\"translate-to-german\")\n", " examples = gr.Examples(examples=[\"I went to the supermarket yesterday.\", \"Helen is a good swimmer.\"],\n", " inputs=[english])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/english_translator/run.py b/demo/english_translator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d73a19fbee13d2e86b162abd17de1b0ea0938ea2
--- /dev/null
+++ b/demo/english_translator/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+
+from transformers import pipeline
+
+pipe = pipeline("translation", model="t5-base")
+
+
+def translate(text):
+ return pipe(text)[0]["translation_text"]
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ english = gr.Textbox(label="English text")
+ translate_btn = gr.Button(value="Translate")
+ with gr.Column():
+ german = gr.Textbox(label="German Text")
+
+ translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")
+ examples = gr.Examples(examples=["I went to the supermarket yesterday.", "Helen is a good swimmer."],
+ inputs=[english])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/event_trigger/img/a.jpg b/demo/event_trigger/img/a.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..765f840973dae7ff5e985fc238ea493d851bb5fb
Binary files /dev/null and b/demo/event_trigger/img/a.jpg differ
diff --git a/demo/event_trigger/img/b.jpg b/demo/event_trigger/img/b.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..7774fb80bb4f03a37d2e0fefae4d250b40542487
Binary files /dev/null and b/demo/event_trigger/img/b.jpg differ
diff --git a/demo/event_trigger/mp4/a.mp4 b/demo/event_trigger/mp4/a.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..95a61f6b4a753497d97f51c6a8f18727cef7d628
Binary files /dev/null and b/demo/event_trigger/mp4/a.mp4 differ
diff --git a/demo/event_trigger/mp4/b.mp4 b/demo/event_trigger/mp4/b.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..7b2d7c723ea53ce763eb49f551bd955858850673
Binary files /dev/null and b/demo/event_trigger/mp4/b.mp4 differ
diff --git a/demo/event_trigger/run.ipynb b/demo/event_trigger/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..62ddb0dcc111b9355f90d9d36cc444bc2d39196e
--- /dev/null
+++ b/demo/event_trigger/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.Video(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " def video_end():\n", " print(\"video_end\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", " video1.end(fn=video_end)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/event_trigger/run.py b/demo/event_trigger/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2497d750ffd9bd99e8e4b4c5b977c4b2e2942f69
--- /dev/null
+++ b/demo/event_trigger/run.py
@@ -0,0 +1,146 @@
+# %%
+import gradio as gr
+
+
+TEST_VIDEO_A = "mp4/a.mp4"
+TEST_VIDEO_B = "mp4/b.mp4"
+
+TEST_IMAGE_A = "img/a.jpg"
+TEST_IMAGE_B = "img/b.jpg"
+
+
+def alert_change(component, value):
+ print(f"Detected {component} change, {type(value)}")
+
+ if type(value) == list or type(value) == str:
+ print(value)
+
+
+def change_interactive(state):
+ return gr.Video(interactive=not state), not state
+
+
+with gr.Blocks() as demo:
+ with gr.Tab(label="Text change"):
+ with gr.Row():
+ with gr.Column():
+ textbox1 = gr.Textbox()
+ textbox2 = gr.Textbox(interactive=True)
+
+ with gr.Column():
+ btn = gr.Button()
+
+ def btn_click(state):
+ return state
+
+ def text_change(value):
+ print("text_change", value)
+
+ btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)
+ textbox2.change(fn=alert_change, inputs=[gr.State("Text"), textbox2])
+
+ with gr.Tab(label="Video change, play, pause"):
+ with gr.Row():
+ with gr.Column():
+ radio1 = gr.Radio(
+ choices=[TEST_VIDEO_A, TEST_VIDEO_B],
+ interactive=True,
+ type="index",
+ )
+
+ video_btn = gr.Button("Change interactive")
+
+ with gr.Column():
+ video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)
+ video1_interactive = gr.State(value=False)
+
+ def change_video(index):
+ if index == 0:
+ return TEST_VIDEO_A
+ elif index == 1:
+ return TEST_VIDEO_B
+
+ def video_play():
+ print("video_play")
+
+ def video_pause():
+ print("video_pause")
+
+ def video_stop():
+ print("video_stop")
+
+ def video_end():
+ print("video_end")
+
+ video1.play(fn=video_play)
+ video1.pause(fn=video_pause)
+ video1.stop(fn=video_stop)
+ video1.end(fn=video_end)
+
+ radio1.change(fn=change_video, inputs=radio1, outputs=video1)
+ video1.change(fn=alert_change, inputs=[gr.State("Video"), video1])
+
+ video_btn.click(
+ fn=change_interactive,
+ inputs=video1_interactive,
+ outputs=[video1, video1_interactive],
+ )
+
+ with gr.Tab(label="Image change"):
+ with gr.Row():
+ with gr.Column():
+ radio2 = gr.Radio(
+ choices=[TEST_IMAGE_A, TEST_IMAGE_B],
+ interactive=True,
+ type="index",
+ )
+
+ with gr.Column():
+ image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)
+
+ def change_image(index):
+ if index == 0:
+ return TEST_IMAGE_A
+ elif index == 1:
+ return TEST_IMAGE_B
+
+ radio2.change(fn=change_image, inputs=radio2, outputs=image1)
+ image1.change(fn=alert_change, inputs=[gr.State("Image"), image1])
+
+ with gr.Tab(label="File"):
+ with gr.Row():
+ with gr.Column():
+ radio3 = gr.Radio(
+ choices=["A", "B", "AB"],
+ interactive=True,
+ type="index",
+ )
+
+ file_btn = gr.Button("Change interactive")
+
+ with gr.Column():
+ file1 = gr.File(
+ value=[TEST_IMAGE_A, TEST_IMAGE_B],
+ interactive=False,
+ file_count="multiple",
+ )
+ file1_interactive = gr.State(value=False)
+
+ def change_file(index):
+ if index == 0:
+ return [TEST_IMAGE_A]
+ elif index == 1:
+ return [TEST_IMAGE_A]
+ elif index == 2:
+ return [TEST_IMAGE_A, TEST_IMAGE_B]
+
+ radio3.change(fn=change_file, inputs=radio3, outputs=file1)
+ file1.change(fn=alert_change, inputs=[gr.State("File"), file1])
+
+ file_btn.click(
+ fn=change_interactive,
+ inputs=file1_interactive,
+ outputs=[file1, file1_interactive],
+ )
+
+demo.launch()
diff --git a/demo/examples_component/images/cheetah1.jpg b/demo/examples_component/images/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/examples_component/images/cheetah1.jpg differ
diff --git a/demo/examples_component/images/lion.jpg b/demo/examples_component/images/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/examples_component/images/lion.jpg differ
diff --git a/demo/examples_component/images/lion.webp b/demo/examples_component/images/lion.webp
new file mode 100644
index 0000000000000000000000000000000000000000..69529a94fe818676da684852b88bed94986c9418
Binary files /dev/null and b/demo/examples_component/images/lion.webp differ
diff --git a/demo/examples_component/images/logo.png b/demo/examples_component/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f1df7156f0a690a2415903061e19c20e24adac4
Binary files /dev/null and b/demo/examples_component/images/logo.png differ
diff --git a/demo/examples_component/run.ipynb b/demo/examples_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..090af8fc0feb052489ec65b04f7990f8a273742b
--- /dev/null
+++ b/demo/examples_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: examples_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('images')\n", "!wget -q -O images/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/examples_component/images/cheetah1.jpg\n", "!wget -q -O images/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/examples_component/images/lion.jpg\n", "!wget -q -O images/lion.webp https://github.com/gradio-app/gradio/raw/main/demo/examples_component/images/lion.webp\n", "!wget -q -O images/logo.png https://github.com/gradio-app/gradio/raw/main/demo/examples_component/images/logo.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def flip(i):\n", " return i.rotate(180)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " img_i = gr.Image(label=\"Input Image\", type=\"pil\")\n", " with gr.Column():\n", " img_o = gr.Image(label=\"Output Image\")\n", " with gr.Row():\n", " btn = gr.Button(value=\"Flip Image\")\n", " btn.click(flip, inputs=[img_i], outputs=[img_o])\n", "\n", " gr.Examples(\n", " [\n", " os.path.join(os.path.abspath(''), \"images/cheetah1.jpg\"),\n", " os.path.join(os.path.abspath(''), \"images/lion.jpg\"),\n", " ],\n", " img_i,\n", " img_o,\n", " flip,\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/examples_component/run.py b/demo/examples_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..60f615a30e4ef423feb54d21a41980ae6eedd47f
--- /dev/null
+++ b/demo/examples_component/run.py
@@ -0,0 +1,29 @@
+import gradio as gr
+import os
+
+
+def flip(i):
+ return i.rotate(180)
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ img_i = gr.Image(label="Input Image", type="pil")
+ with gr.Column():
+ img_o = gr.Image(label="Output Image")
+ with gr.Row():
+ btn = gr.Button(value="Flip Image")
+ btn.click(flip, inputs=[img_i], outputs=[img_o])
+
+ gr.Examples(
+ [
+ os.path.join(os.path.dirname(__file__), "images/cheetah1.jpg"),
+ os.path.join(os.path.dirname(__file__), "images/lion.jpg"),
+ ],
+ img_i,
+ img_o,
+ flip,
+ )
+
+demo.launch()
diff --git a/demo/fake_diffusion/DESCRIPTION.md b/demo/fake_diffusion/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..0eab50a7a18c4208939b013dd63eead420f05839
--- /dev/null
+++ b/demo/fake_diffusion/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo uses a fake model to showcase iterative output. The Image output will update every time a generator is returned until the final image.
\ No newline at end of file
diff --git a/demo/fake_diffusion/requirements.txt b/demo/fake_diffusion/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..24ce15ab7ead32f98c7ac3edcd34bb2010ff4326
--- /dev/null
+++ b/demo/fake_diffusion/requirements.txt
@@ -0,0 +1 @@
+numpy
diff --git a/demo/fake_diffusion/run.ipynb b/demo/fake_diffusion/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8f1a104278645d32747e029c23b61fb7563e0d26
--- /dev/null
+++ b/demo/fake_diffusion/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fake_diffusion\n", "### This demo uses a fake model to showcase iterative output. The Image output will update every time a generator is returned until the final image.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "\n", "def fake_diffusion(steps):\n", " for i in range(steps):\n", " time.sleep(1)\n", " image = np.random.random((600, 600, 3))\n", " yield image\n", " image = np.ones((1000,1000,3), np.uint8)\n", " image[:] = [255, 124, 0]\n", " yield image\n", "\n", "\n", "demo = gr.Interface(fake_diffusion,\n", " inputs=gr.Slider(1, 10, 3, step=1),\n", " outputs=\"image\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fake_diffusion/run.py b/demo/fake_diffusion/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..554942c6eee2090b86f9ace67765018b136196da
--- /dev/null
+++ b/demo/fake_diffusion/run.py
@@ -0,0 +1,20 @@
+import gradio as gr
+import numpy as np
+import time
+
+def fake_diffusion(steps):
+ for i in range(steps):
+ time.sleep(1)
+ image = np.random.random((600, 600, 3))
+ yield image
+ image = np.ones((1000,1000,3), np.uint8)
+ image[:] = [255, 124, 0]
+ yield image
+
+
+demo = gr.Interface(fake_diffusion,
+ inputs=gr.Slider(1, 10, 3, step=1),
+ outputs="image")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/fake_diffusion_with_gif/image.gif b/demo/fake_diffusion_with_gif/image.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2b55b9b8eacc08da2e6ec1cb1c9d95ea7cf66f4a
--- /dev/null
+++ b/demo/fake_diffusion_with_gif/image.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:58c6fc2b7f07b13c94f201692c432adaf3011face3be8b61800a9917dc1ad147
+size 1761134
diff --git a/demo/fake_diffusion_with_gif/run.ipynb b/demo/fake_diffusion_with_gif/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0b6c8d386cf1550c34cb357b0d78e315c67c2501
--- /dev/null
+++ b/demo/fake_diffusion_with_gif/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fake_diffusion_with_gif"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/fake_diffusion_with_gif/image.gif"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "import os\n", "from PIL import Image\n", "import requests\n", "from io import BytesIO\n", "\n", "\n", "def create_gif(images):\n", " pil_images = []\n", " for image in images:\n", " if isinstance(image, str):\n", " response = requests.get(image)\n", " image = Image.open(BytesIO(response.content))\n", " else:\n", " image = Image.fromarray((image * 255).astype(np.uint8))\n", " pil_images.append(image)\n", " fp_out = os.path.join(os.path.abspath(''), \"image.gif\")\n", " img = pil_images.pop(0)\n", " img.save(fp=fp_out, format='GIF', append_images=pil_images,\n", " save_all=True, duration=400, loop=0)\n", " return fp_out\n", "\n", "\n", "def fake_diffusion(steps):\n", " images = []\n", " for _ in range(steps):\n", " time.sleep(1)\n", " image = np.random.random((600, 600, 3))\n", " images.append(image)\n", " yield image, gr.Image(visible=False)\n", "\n", " time.sleep(1)\n", " image = \"https://gradio-builds.s3.amazonaws.com/diffusion_image/cute_dog.jpg\"\n", " images.append(image)\n", " gif_path = create_gif(images)\n", "\n", " yield image, gr.Image(value=gif_path, visible=True)\n", "\n", "\n", "demo = gr.Interface(fake_diffusion,\n", " inputs=gr.Slider(1, 10, 3, step=1),\n", " outputs=[\"image\", gr.Image(label=\"All Images\", visible=False)])\n", "demo.queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fake_diffusion_with_gif/run.py b/demo/fake_diffusion_with_gif/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c1d01de70112d68ca2af56e8e7da78298f8a536
--- /dev/null
+++ b/demo/fake_diffusion_with_gif/run.py
@@ -0,0 +1,48 @@
+import gradio as gr
+import numpy as np
+import time
+import os
+from PIL import Image
+import requests
+from io import BytesIO
+
+
+def create_gif(images):
+ pil_images = []
+ for image in images:
+ if isinstance(image, str):
+ response = requests.get(image)
+ image = Image.open(BytesIO(response.content))
+ else:
+ image = Image.fromarray((image * 255).astype(np.uint8))
+ pil_images.append(image)
+ fp_out = os.path.join(os.path.dirname(__file__), "image.gif")
+ img = pil_images.pop(0)
+ img.save(fp=fp_out, format='GIF', append_images=pil_images,
+ save_all=True, duration=400, loop=0)
+ return fp_out
+
+
+def fake_diffusion(steps):
+ images = []
+ for _ in range(steps):
+ time.sleep(1)
+ image = np.random.random((600, 600, 3))
+ images.append(image)
+ yield image, gr.Image(visible=False)
+
+ time.sleep(1)
+ image = "https://gradio-builds.s3.amazonaws.com/diffusion_image/cute_dog.jpg"
+ images.append(image)
+ gif_path = create_gif(images)
+
+ yield image, gr.Image(value=gif_path, visible=True)
+
+
+demo = gr.Interface(fake_diffusion,
+ inputs=gr.Slider(1, 10, 3, step=1),
+ outputs=["image", gr.Image(label="All Images", visible=False)])
+demo.queue()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/fake_gan/DESCRIPTION.md b/demo/fake_gan/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..2eb2efc0f04eb97bb167e391ab7aa8f5dea8e3b4
--- /dev/null
+++ b/demo/fake_gan/DESCRIPTION.md
@@ -0,0 +1 @@
+This is a fake GAN that shows how to create a text-to-image interface for image generation. Check out the Stable Diffusion demo for more: https://hf.co/spaces/stabilityai/stable-diffusion/
\ No newline at end of file
diff --git a/demo/fake_gan/files/cheetah1.jpg b/demo/fake_gan/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/fake_gan/files/cheetah1.jpg differ
diff --git a/demo/fake_gan/run.ipynb b/demo/fake_gan/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..77783d1e3ea17c283f72eb3efd16a599b3e6fa4c
--- /dev/null
+++ b/demo/fake_gan/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fake_gan\n", "### This is a fake GAN that shows how to create a text-to-image interface for image generation. Check out the Stable Diffusion demo for more: https://hf.co/spaces/stabilityai/stable-diffusion/\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/fake_gan/files/cheetah1.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["# This demo needs to be run from the repo folder.\n", "# python demo/fake_gan/run.py\n", "import random\n", "\n", "import gradio as gr\n", "\n", "\n", "def fake_gan():\n", " images = [\n", " (random.choice(\n", " [\n", " \"http://www.marketingtool.online/en/face-generator/img/faces/avatar-1151ce9f4b2043de0d2e3b7826127998.jpg\",\n", " \"http://www.marketingtool.online/en/face-generator/img/faces/avatar-116b5e92936b766b7fdfc242649337f7.jpg\",\n", " \"http://www.marketingtool.online/en/face-generator/img/faces/avatar-1163530ca19b5cebe1b002b8ec67b6fc.jpg\",\n", " \"http://www.marketingtool.online/en/face-generator/img/faces/avatar-1116395d6e6a6581eef8b8038f4c8e55.jpg\",\n", " \"http://www.marketingtool.online/en/face-generator/img/faces/avatar-11319be65db395d0e8e6855d18ddcef0.jpg\",\n", " ]\n", " ), f\"label {i}\")\n", " for i in range(3)\n", " ]\n", " return images\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gallery = gr.Gallery(\n", " label=\"Generated images\", show_label=False, elem_id=\"gallery\"\n", " , columns=[3], rows=[1], object_fit=\"contain\", height=\"auto\")\n", " btn = gr.Button(\"Generate images\", scale=0)\n", "\n", " btn.click(fake_gan, None, gallery)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fake_gan/run.py b/demo/fake_gan/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b3ea489cee0f42b6bc26b4809ba7c62dba54d1f6
--- /dev/null
+++ b/demo/fake_gan/run.py
@@ -0,0 +1,33 @@
+# This demo needs to be run from the repo folder.
+# python demo/fake_gan/run.py
+import random
+
+import gradio as gr
+
+
+def fake_gan():
+ images = [
+ (random.choice(
+ [
+ "http://www.marketingtool.online/en/face-generator/img/faces/avatar-1151ce9f4b2043de0d2e3b7826127998.jpg",
+ "http://www.marketingtool.online/en/face-generator/img/faces/avatar-116b5e92936b766b7fdfc242649337f7.jpg",
+ "http://www.marketingtool.online/en/face-generator/img/faces/avatar-1163530ca19b5cebe1b002b8ec67b6fc.jpg",
+ "http://www.marketingtool.online/en/face-generator/img/faces/avatar-1116395d6e6a6581eef8b8038f4c8e55.jpg",
+ "http://www.marketingtool.online/en/face-generator/img/faces/avatar-11319be65db395d0e8e6855d18ddcef0.jpg",
+ ]
+ ), f"label {i}")
+ for i in range(3)
+ ]
+ return images
+
+
+with gr.Blocks() as demo:
+ gallery = gr.Gallery(
+ label="Generated images", show_label=False, elem_id="gallery"
+ , columns=[3], rows=[1], object_fit="contain", height="auto")
+ btn = gr.Button("Generate images", scale=0)
+
+ btn.click(fake_gan, None, gallery)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/fake_gan_2/files/cheetah1.jpg b/demo/fake_gan_2/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/fake_gan_2/files/cheetah1.jpg differ
diff --git a/demo/fake_gan_2/files/elephant.jpg b/demo/fake_gan_2/files/elephant.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..26eb3bb4db525ffb929ecb163a87ec3ecc34b373
Binary files /dev/null and b/demo/fake_gan_2/files/elephant.jpg differ
diff --git a/demo/fake_gan_2/files/tiger.jpg b/demo/fake_gan_2/files/tiger.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4a9cbc15b17593d555b07bdc30f80a0c2a3db052
Binary files /dev/null and b/demo/fake_gan_2/files/tiger.jpg differ
diff --git a/demo/fake_gan_2/files/zebra.jpg b/demo/fake_gan_2/files/zebra.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..b3805a9d3921a4707b00bab3de7e2ecbcb859d00
Binary files /dev/null and b/demo/fake_gan_2/files/zebra.jpg differ
diff --git a/demo/fake_gan_2/run.ipynb b/demo/fake_gan_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..fd35b2f5389fe5e3862c1faac1a71903d1f815aa
--- /dev/null
+++ b/demo/fake_gan_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fake_gan_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/fake_gan_2/files/cheetah1.jpg\n", "!wget -q -O files/elephant.jpg https://github.com/gradio-app/gradio/raw/main/demo/fake_gan_2/files/elephant.jpg\n", "!wget -q -O files/tiger.jpg https://github.com/gradio-app/gradio/raw/main/demo/fake_gan_2/files/tiger.jpg\n", "!wget -q -O files/zebra.jpg https://github.com/gradio-app/gradio/raw/main/demo/fake_gan_2/files/zebra.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["# This demo needs to be run from the repo folder.\n", "# python demo/fake_gan/run.py\n", "import random\n", "import time\n", "\n", "import gradio as gr\n", "\n", "\n", "def fake_gan(desc):\n", " if desc == \"NSFW\":\n", " raise gr.Error(\"NSFW - banned content.\")\n", " if desc == \"error\":\n", " raise ValueError(\"error\")\n", " time.sleep(9)\n", " image = random.choice(\n", " [\n", " \"files/cheetah1.jpg\",\n", " \"files/elephant.jpg\",\n", " \"files/tiger.jpg\",\n", " \"files/zebra.jpg\",\n", " ]\n", " )\n", " return image\n", "\n", "\n", "demo = gr.Interface(\n", " fn=fake_gan,\n", " inputs=gr.Textbox(),\n", " outputs=gr.Image(label=\"Generated Image\"),\n", " title=\"FD-GAN\",\n", " description=\"This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.\",\n", ")\n", "demo.queue(max_size=3)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fake_gan_2/run.py b/demo/fake_gan_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c32b0526c4713f4a7cc07b24569d8893d4d7952
--- /dev/null
+++ b/demo/fake_gan_2/run.py
@@ -0,0 +1,36 @@
+# This demo needs to be run from the repo folder.
+# python demo/fake_gan/run.py
+import random
+import time
+
+import gradio as gr
+
+
+def fake_gan(desc):
+ if desc == "NSFW":
+ raise gr.Error("NSFW - banned content.")
+ if desc == "error":
+ raise ValueError("error")
+ time.sleep(9)
+ image = random.choice(
+ [
+ "files/cheetah1.jpg",
+ "files/elephant.jpg",
+ "files/tiger.jpg",
+ "files/zebra.jpg",
+ ]
+ )
+ return image
+
+
+demo = gr.Interface(
+ fn=fake_gan,
+ inputs=gr.Textbox(),
+ outputs=gr.Image(label="Generated Image"),
+ title="FD-GAN",
+ description="This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.",
+)
+demo.queue(max_size=3)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/fake_gan_no_input/run.ipynb b/demo/fake_gan_no_input/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2bc045f386c1c3be90214940fc0601a620e4420c
--- /dev/null
+++ b/demo/fake_gan_no_input/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fake_gan_no_input"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import time\n", "\n", "import gradio as gr\n", "\n", "\n", "def fake_gan():\n", " time.sleep(1)\n", " images = [\n", " \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\",\n", " \"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80\",\n", " \"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80\",\n", " ]\n", " return images\n", "\n", "\n", "demo = gr.Interface(\n", " fn=fake_gan,\n", " inputs=None,\n", " outputs=gr.Gallery(label=\"Generated Images\", columns=[2]),\n", " title=\"FD-GAN\",\n", " description=\"This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fake_gan_no_input/run.py b/demo/fake_gan_no_input/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..de46905c56ef0dfc9f5b6c2f672dd0889538b571
--- /dev/null
+++ b/demo/fake_gan_no_input/run.py
@@ -0,0 +1,25 @@
+import time
+
+import gradio as gr
+
+
+def fake_gan():
+ time.sleep(1)
+ images = [
+ "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
+ "https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80",
+ "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
+ ]
+ return images
+
+
+demo = gr.Interface(
+ fn=fake_gan,
+ inputs=None,
+ outputs=gr.Gallery(label="Generated Images", columns=[2]),
+ title="FD-GAN",
+ description="This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/file_component/run.ipynb b/demo/file_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ea487a02e3dfd9d41d0d20b6ec395a6d3593738c
--- /dev/null
+++ b/demo/file_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.File()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/file_component/run.py b/demo/file_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..518899d2e0e9233e689035dfed5180412d6cb148
--- /dev/null
+++ b/demo/file_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.File()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/file_component_events/run.ipynb b/demo/file_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..af0f035d70830542c2f67fffe49b37fb51df961c
--- /dev/null
+++ b/demo/file_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " \n", " with gr.Row():\n", " with gr.Column():\n", " file_component = gr.File(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(label=\"Upload Single File Output\", file_count=\"single\")\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_multiple = gr.File(label=\"Upload Multiple Files\", file_count=\"multiple\")\n", " with gr.Column():\n", " output_file_2 = gr.File(label=\"Upload Multiple Files Output\", file_count=\"multiple\")\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/file_component_events/run.py b/demo/file_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..12a5a02c3fd184400dc5b0415440f9041645b7f3
--- /dev/null
+++ b/demo/file_component_events/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+
+ with gr.Row():
+ with gr.Column():
+ file_component = gr.File(label="Upload Single File", file_count="single")
+ with gr.Column():
+ output_file_1 = gr.File(label="Upload Single File Output", file_count="single")
+ num_load_btn_1 = gr.Number(label="# Load Upload Single File", value=0)
+ file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])
+ with gr.Row():
+ with gr.Column():
+ file_component_multiple = gr.File(label="Upload Multiple Files", file_count="multiple")
+ with gr.Column():
+ output_file_2 = gr.File(label="Upload Multiple Files Output", file_count="multiple")
+ num_load_btn_2 = gr.Number(label="# Load Upload Multiple Files", value=0)
+ file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/file_explorer/run.ipynb b/demo/file_explorer/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..34a79bc6e0a0123b07231c7e6b35d99cc72e51eb
--- /dev/null
+++ b/demo/file_explorer/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pathlib import Path\n", "\n", "current_file_path = Path(__file__).resolve()\n", "relative_path = \"path/to/file\"\n", "absolute_path = (current_file_path.parent / \"..\" / \"..\" / \"gradio\").resolve()\n", "\n", "\n", "def get_file_content(file):\n", " return (file,)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown('### `FileExplorer` to `FileExplorer` -- `file_count=\"multiple\"`')\n", " submit_btn = gr.Button(\"Select\")\n", " with gr.Row():\n", " file = gr.FileExplorer(\n", " glob=\"**/{components,themes}/*.py\",\n", " # value=[\"themes/utils\"],\n", " root=absolute_path,\n", " ignore_glob=\"**/__init__.py\",\n", " )\n", "\n", " file2 = gr.FileExplorer(\n", " glob=\"**/{components,themes}/**/*.py\",\n", " root=absolute_path,\n", " ignore_glob=\"**/__init__.py\",\n", " )\n", " submit_btn.click(lambda x: x, file, file2)\n", "\n", " gr.Markdown(\"---\")\n", " gr.Markdown('### `FileExplorer` to `Code` -- `file_count=\"single\"`')\n", " with gr.Group():\n", " with gr.Row():\n", " file_3 = gr.FileExplorer(\n", " scale=1,\n", " glob=\"**/{components,themes}/**/*.py\",\n", " value=[\"themes/utils\"],\n", " file_count=\"single\",\n", " root=absolute_path,\n", " ignore_glob=\"**/__init__.py\",\n", " elem_id=\"file\",\n", " )\n", "\n", " code = gr.Code(lines=30, scale=2, language=\"python\")\n", "\n", " file_3.change(get_file_content, file_3, code)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/file_explorer/run.py b/demo/file_explorer/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6db60c188890ff12c369aa80ea37b8a567555834
--- /dev/null
+++ b/demo/file_explorer/run.py
@@ -0,0 +1,51 @@
+import gradio as gr
+from pathlib import Path
+
+current_file_path = Path(__file__).resolve()
+relative_path = "path/to/file"
+absolute_path = (current_file_path.parent / ".." / ".." / "gradio").resolve()
+
+
+def get_file_content(file):
+ return (file,)
+
+
+with gr.Blocks() as demo:
+ gr.Markdown('### `FileExplorer` to `FileExplorer` -- `file_count="multiple"`')
+ submit_btn = gr.Button("Select")
+ with gr.Row():
+ file = gr.FileExplorer(
+ glob="**/{components,themes}/*.py",
+ # value=["themes/utils"],
+ root=absolute_path,
+ ignore_glob="**/__init__.py",
+ )
+
+ file2 = gr.FileExplorer(
+ glob="**/{components,themes}/**/*.py",
+ root=absolute_path,
+ ignore_glob="**/__init__.py",
+ )
+ submit_btn.click(lambda x: x, file, file2)
+
+ gr.Markdown("---")
+ gr.Markdown('### `FileExplorer` to `Code` -- `file_count="single"`')
+ with gr.Group():
+ with gr.Row():
+ file_3 = gr.FileExplorer(
+ scale=1,
+ glob="**/{components,themes}/**/*.py",
+ value=["themes/utils"],
+ file_count="single",
+ root=absolute_path,
+ ignore_glob="**/__init__.py",
+ elem_id="file",
+ )
+
+ code = gr.Code(lines=30, scale=2, language="python")
+
+ file_3.change(get_file_content, file_3, code)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/file_explorer_component/run.ipynb b/demo/file_explorer_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e57e663503a4f1528141716392de587866fe1090
--- /dev/null
+++ b/demo/file_explorer_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.FileExplorer()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/file_explorer_component/run.py b/demo/file_explorer_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..de1c1d5804bce0bd6cc6a6fb2b2f2f8df389fb17
--- /dev/null
+++ b/demo/file_explorer_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.FileExplorer()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/file_explorer_component_events/dir1/bar.txt b/demo/file_explorer_component_events/dir1/bar.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir1/foo.txt b/demo/file_explorer_component_events/dir1/foo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir2/baz.png b/demo/file_explorer_component_events/dir2/baz.png
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir2/foo.png b/demo/file_explorer_component_events/dir2/foo.png
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir3/dir3_foo.txt b/demo/file_explorer_component_events/dir3/dir3_foo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir3/dir4/dir5/dir5_foo.txt b/demo/file_explorer_component_events/dir3/dir4/dir5/dir5_foo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir3/dir4/dir7/dir7_foo.txt b/demo/file_explorer_component_events/dir3/dir4/dir7/dir7_foo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/dir3/dir4/dir_4_foo.txt b/demo/file_explorer_component_events/dir3/dir4/dir_4_foo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/file_explorer_component_events/run.ipynb b/demo/file_explorer_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..60efe8e1e6117b6df3aebd6b2ea1fbada1c9759d
--- /dev/null
+++ b/demo/file_explorer_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('dir1')\n", "!wget -q -O dir1/bar.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/bar.txt\n", "!wget -q -O dir1/foo.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/foo.txt\n", "os.mkdir('dir2')\n", "!wget -q -O dir2/baz.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/baz.png\n", "!wget -q -O dir2/foo.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/foo.png\n", "os.mkdir('dir3')\n", "!wget -q -O dir3/dir3_foo.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir3/dir3_foo.txt\n", "!wget -q -O dir3/dir4 https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir3/dir4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pathlib import Path\n", "\n", "base_root = Path(__file__).parent.resolve()\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " dd = gr.Dropdown(label=\"Select File Explorer Root\",\n", " value=str(base_root / \"dir1\"),\n", " choices=[str(base_root / \"dir1\"), str(base_root / \"dir2\"),\n", " str(base_root / \"dir3\")])\n", " with gr.Group():\n", " dir_only_glob = gr.Checkbox(label=\"Show only directories\", value=False)\n", " ignore_dir_in_glob = gr.Checkbox(label=\"Ignore directories in glob\", value=False)\n", "\n", " fe = gr.FileExplorer(root=str(base_root / \"dir1\"),\n", " glob=\"**/*\", interactive=True)\n", " textbox = gr.Textbox(label=\"Selected Directory\")\n", " run = gr.Button(\"Run\")\n", " \n", " dir_only_glob.select(lambda s: gr.FileExplorer(glob=\"**/\" if s else \"**/*.*\",\n", " file_count=\"multiple\",\n", " root=str(base_root / \"dir3\")) ,\n", " inputs=[dir_only_glob], outputs=[fe])\n", " ignore_dir_in_glob.select(lambda s: gr.FileExplorer(glob=\"**/*\",\n", " ignore_glob=\"**/\",\n", " root=str(base_root / \"dir3\")),\n", " inputs=[ignore_dir_in_glob], outputs=[fe]) \n", "\n", " dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])\n", " run.click(lambda s: \",\".join(s) if isinstance(s, list) else s, inputs=[fe], outputs=[textbox])\n", "\n", " with gr.Row():\n", " a = gr.Textbox(elem_id=\"input-box\")\n", " a.change(lambda x: x, inputs=[a])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/file_explorer_component_events/run.py b/demo/file_explorer_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..0e1022d20b5a014c19333d6d96e2a3a7ec5bfc6c
--- /dev/null
+++ b/demo/file_explorer_component_events/run.py
@@ -0,0 +1,39 @@
+import gradio as gr
+from pathlib import Path
+
+base_root = Path(__file__).parent.resolve()
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ dd = gr.Dropdown(label="Select File Explorer Root",
+ value=str(base_root / "dir1"),
+ choices=[str(base_root / "dir1"), str(base_root / "dir2"),
+ str(base_root / "dir3")])
+ with gr.Group():
+ dir_only_glob = gr.Checkbox(label="Show only directories", value=False)
+ ignore_dir_in_glob = gr.Checkbox(label="Ignore directories in glob", value=False)
+
+ fe = gr.FileExplorer(root=str(base_root / "dir1"),
+ glob="**/*", interactive=True)
+ textbox = gr.Textbox(label="Selected Directory")
+ run = gr.Button("Run")
+
+ dir_only_glob.select(lambda s: gr.FileExplorer(glob="**/" if s else "**/*.*",
+ file_count="multiple",
+ root=str(base_root / "dir3")) ,
+ inputs=[dir_only_glob], outputs=[fe])
+ ignore_dir_in_glob.select(lambda s: gr.FileExplorer(glob="**/*",
+ ignore_glob="**/",
+ root=str(base_root / "dir3")),
+ inputs=[ignore_dir_in_glob], outputs=[fe])
+
+ dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])
+ run.click(lambda s: ",".join(s) if isinstance(s, list) else s, inputs=[fe], outputs=[textbox])
+
+ with gr.Row():
+ a = gr.Textbox(elem_id="input-box")
+ a.change(lambda x: x, inputs=[a])
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/filter_records/run.ipynb b/demo/filter_records/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1b25ad97263e26bc59966addb810f00bbf7e28c7
--- /dev/null
+++ b/demo/filter_records/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: filter_records"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def filter_records(records, gender):\n", " return records[records[\"gender\"] == gender]\n", "\n", "\n", "demo = gr.Interface(\n", " filter_records,\n", " [\n", " gr.Dataframe(\n", " headers=[\"name\", \"age\", \"gender\"],\n", " datatype=[\"str\", \"number\", \"str\"],\n", " row_count=5,\n", " col_count=(3, \"fixed\"),\n", " ),\n", " gr.Dropdown([\"M\", \"F\", \"O\"]),\n", " ],\n", " \"dataframe\",\n", " description=\"Enter gender as 'M', 'F', or 'O' for other.\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/filter_records/run.py b/demo/filter_records/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f173bf9611996177b8d6db1b72cde12af424c5a7
--- /dev/null
+++ b/demo/filter_records/run.py
@@ -0,0 +1,24 @@
+import gradio as gr
+
+
+def filter_records(records, gender):
+ return records[records["gender"] == gender]
+
+
+demo = gr.Interface(
+ filter_records,
+ [
+ gr.Dataframe(
+ headers=["name", "age", "gender"],
+ datatype=["str", "number", "str"],
+ row_count=5,
+ col_count=(3, "fixed"),
+ ),
+ gr.Dropdown(["M", "F", "O"]),
+ ],
+ "dataframe",
+ description="Enter gender as 'M', 'F', or 'O' for other.",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/filter_records/screenshot.png b/demo/filter_records/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..a53732b937a66d69a76b0548c5d20bbf31ccaab3
Binary files /dev/null and b/demo/filter_records/screenshot.png differ
diff --git a/demo/fraud_detector/fraud.csv b/demo/fraud_detector/fraud.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8fe13def6c7e0fb86714908a04e8b1df2e0910d2
--- /dev/null
+++ b/demo/fraud_detector/fraud.csv
@@ -0,0 +1,11 @@
+time,retail,food,other
+0,109,145,86
+1,35,87,43
+2,49,117,34
+3,127,66,17
+4,39,82,17
+5,101,56,79
+6,100,129,67
+7,17,88,97
+8,76,85,145
+9,111,106,35
diff --git a/demo/fraud_detector/requirements.txt b/demo/fraud_detector/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1411a4a0b5ab886adfb744e685d150151ab10023
--- /dev/null
+++ b/demo/fraud_detector/requirements.txt
@@ -0,0 +1 @@
+pandas
\ No newline at end of file
diff --git a/demo/fraud_detector/run.ipynb b/demo/fraud_detector/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..aa0efaaf91c9fec7cda928276b5deee3d933df53
--- /dev/null
+++ b/demo/fraud_detector/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: fraud_detector"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/fraud_detector/fraud.csv"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import random\n", "import os\n", "import gradio as gr\n", "\n", "\n", "def fraud_detector(card_activity, categories, sensitivity):\n", " activity_range = random.randint(0, 100)\n", " drop_columns = [\n", " column for column in [\"retail\", \"food\", \"other\"] if column not in categories\n", " ]\n", " if len(drop_columns):\n", " card_activity.drop(columns=drop_columns, inplace=True)\n", " return (\n", " card_activity,\n", " card_activity,\n", " {\"fraud\": activity_range / 100.0, \"not fraud\": 1 - activity_range / 100.0},\n", " )\n", "\n", "\n", "demo = gr.Interface(\n", " fraud_detector,\n", " [\n", " gr.CheckboxGroup(\n", " [\"retail\", \"food\", \"other\"], value=[\"retail\", \"food\", \"other\"]\n", " ),\n", " gr.Slider(1, 3),\n", " ],\n", " [\n", " \"dataframe\",\n", " gr.Label(label=\"Fraud Level\"),\n", " ],\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"fraud.csv\"), [\"retail\", \"food\", \"other\"], 1.0],\n", " ],\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/fraud_detector/run.py b/demo/fraud_detector/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3425cb8f1872ba629193330d1eabab0e18a9d17b
--- /dev/null
+++ b/demo/fraud_detector/run.py
@@ -0,0 +1,37 @@
+import random
+import os
+import gradio as gr
+
+
+def fraud_detector(card_activity, categories, sensitivity):
+ activity_range = random.randint(0, 100)
+ drop_columns = [
+ column for column in ["retail", "food", "other"] if column not in categories
+ ]
+ if len(drop_columns):
+ card_activity.drop(columns=drop_columns, inplace=True)
+ return (
+ card_activity,
+ card_activity,
+ {"fraud": activity_range / 100.0, "not fraud": 1 - activity_range / 100.0},
+ )
+
+
+demo = gr.Interface(
+ fraud_detector,
+ [
+ gr.CheckboxGroup(
+ ["retail", "food", "other"], value=["retail", "food", "other"]
+ ),
+ gr.Slider(1, 3),
+ ],
+ [
+ "dataframe",
+ gr.Label(label="Fraud Level"),
+ ],
+ examples=[
+ [os.path.join(os.path.dirname(__file__), "fraud.csv"), ["retail", "food", "other"], 1.0],
+ ],
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/fraud_detector/screenshot.png b/demo/fraud_detector/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a03d3b953139ec742fd1801e737ed091bf93212
Binary files /dev/null and b/demo/fraud_detector/screenshot.png differ
diff --git a/demo/gallery_component/run.ipynb b/demo/gallery_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ce858d3c1ff29892982c35c8cd8c26114beeb04f
--- /dev/null
+++ b/demo/gallery_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gallery_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " cheetahs = [\n", " \"https://upload.wikimedia.org/wikipedia/commons/0/09/TheCheethcat.jpg\",\n", " \"https://nationalzoo.si.edu/sites/default/files/animals/cheetah-003.jpg\",\n", " \"https://img.etimg.com/thumb/msid-50159822,width-650,imgsize-129520,,resizemode-4,quality-100/.jpg\",\n", " \"https://nationalzoo.si.edu/sites/default/files/animals/cheetah-002.jpg\",\n", " \"https://images.theconversation.com/files/375893/original/file-20201218-13-a8h8uq.jpg?ixlib=rb-1.1.0&rect=16%2C407%2C5515%2C2924&q=45&auto=format&w=496&fit=clip\",\n", " ]\n", " gr.Gallery(value=cheetahs, columns=4)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gallery_component/run.py b/demo/gallery_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..1bc775fb691065e210b86d2cc2eaa1a04751557e
--- /dev/null
+++ b/demo/gallery_component/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ cheetahs = [
+ "https://upload.wikimedia.org/wikipedia/commons/0/09/TheCheethcat.jpg",
+ "https://nationalzoo.si.edu/sites/default/files/animals/cheetah-003.jpg",
+ "https://img.etimg.com/thumb/msid-50159822,width-650,imgsize-129520,,resizemode-4,quality-100/.jpg",
+ "https://nationalzoo.si.edu/sites/default/files/animals/cheetah-002.jpg",
+ "https://images.theconversation.com/files/375893/original/file-20201218-13-a8h8uq.jpg?ixlib=rb-1.1.0&rect=16%2C407%2C5515%2C2924&q=45&auto=format&w=496&fit=clip",
+ ]
+ gr.Gallery(value=cheetahs, columns=4)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/gallery_component_events/run.ipynb b/demo/gallery_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3d0de829f5b8c0a2ba4a06078336c84c262223a4
--- /dev/null
+++ b/demo/gallery_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gallery_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "\n", "with gr.Blocks() as demo:\n", " cheetahs = [\n", " \"https://gradio-builds.s3.amazonaws.com/assets/cheetah-003.jpg\",\n", " \"https://gradio-builds.s3.amazonaws.com/assets/lite-logo.png\",\n", " \"https://gradio-builds.s3.amazonaws.com/assets/TheCheethcat.jpg\",\n", " ]\n", " with gr.Row():\n", " with gr.Column():\n", " gal = gr.Gallery(columns=4, interactive=True, label=\"Input Gallery\")\n", " btn = gr.Button()\n", " with gr.Column():\n", " output_gal = gr.Gallery(columns=4, interactive=True, label=\"Output Gallery\")\n", " with gr.Row():\n", " textbox = gr.Json(label=\"uploaded files\")\n", " num_upload = gr.Number(value=0, label=\"Num Upload\")\n", " num_change = gr.Number(value=0, label=\"Num Change\")\n", " select_output = gr.Textbox(label=\"Select Data\")\n", " gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])\n", " gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])\n", " \n", " btn.click(lambda: cheetahs, None, [output_gal])\n", "\n", " def select(select_data: gr.SelectData):\n", " return select_data.value['image']['url']\n", "\n", " output_gal.select(select, None, select_output)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gallery_component_events/run.py b/demo/gallery_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..841bb7c317b16d944cf9fb050308bc883a0f7a9f
--- /dev/null
+++ b/demo/gallery_component_events/run.py
@@ -0,0 +1,33 @@
+import gradio as gr
+
+
+with gr.Blocks() as demo:
+ cheetahs = [
+ "https://gradio-builds.s3.amazonaws.com/assets/cheetah-003.jpg",
+ "https://gradio-builds.s3.amazonaws.com/assets/lite-logo.png",
+ "https://gradio-builds.s3.amazonaws.com/assets/TheCheethcat.jpg",
+ ]
+ with gr.Row():
+ with gr.Column():
+ gal = gr.Gallery(columns=4, interactive=True, label="Input Gallery")
+ btn = gr.Button()
+ with gr.Column():
+ output_gal = gr.Gallery(columns=4, interactive=True, label="Output Gallery")
+ with gr.Row():
+ textbox = gr.Json(label="uploaded files")
+ num_upload = gr.Number(value=0, label="Num Upload")
+ num_change = gr.Number(value=0, label="Num Change")
+ select_output = gr.Textbox(label="Select Data")
+ gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])
+ gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])
+
+ btn.click(lambda: cheetahs, None, [output_gal])
+
+ def select(select_data: gr.SelectData):
+ return select_data.value['image']['url']
+
+ output_gal.select(select, None, select_output)
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/gallery_selections/run.ipynb b/demo/gallery_selections/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a07e4e5fa362f45336b0ecb56c26af37e112f4ca
--- /dev/null
+++ b/demo/gallery_selections/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gallery_selections"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "\n", "with gr.Blocks() as demo:\n", " imgs = gr.State()\n", " gallery = gr.Gallery(allow_preview=False)\n", "\n", " def deselect_images():\n", " return gr.Gallery(selected_index=None)\n", "\n", " def generate_images():\n", " images = []\n", " for _ in range(9):\n", " image = np.ones((100, 100, 3), dtype=np.uint8) * np.random.randint(\n", " 0, 255, 3\n", " ) # image is a solid single color\n", " images.append(image)\n", " return images, images\n", "\n", " demo.load(generate_images, None, [gallery, imgs])\n", "\n", " with gr.Row():\n", " selected = gr.Number(show_label=False)\n", " darken_btn = gr.Button(\"Darken selected\")\n", " deselect_button = gr.Button(\"Deselect\")\n", "\n", " deselect_button.click(deselect_images, None, gallery)\n", "\n", " def get_select_index(evt: gr.SelectData):\n", " return evt.index\n", "\n", " gallery.select(get_select_index, None, selected)\n", "\n", " def darken_img(imgs, index):\n", " index = int(index)\n", " imgs[index] = np.round(imgs[index] * 0.8).astype(np.uint8)\n", " return imgs, imgs\n", "\n", " darken_btn.click(darken_img, [imgs, selected], [imgs, gallery])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gallery_selections/run.py b/demo/gallery_selections/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..0518de0fb4f9dde216aa1fc0c8fa9fc9ba03b989
--- /dev/null
+++ b/demo/gallery_selections/run.py
@@ -0,0 +1,42 @@
+import gradio as gr
+import numpy as np
+
+with gr.Blocks() as demo:
+ imgs = gr.State()
+ gallery = gr.Gallery(allow_preview=False)
+
+ def deselect_images():
+ return gr.Gallery(selected_index=None)
+
+ def generate_images():
+ images = []
+ for _ in range(9):
+ image = np.ones((100, 100, 3), dtype=np.uint8) * np.random.randint(
+ 0, 255, 3
+ ) # image is a solid single color
+ images.append(image)
+ return images, images
+
+ demo.load(generate_images, None, [gallery, imgs])
+
+ with gr.Row():
+ selected = gr.Number(show_label=False)
+ darken_btn = gr.Button("Darken selected")
+ deselect_button = gr.Button("Deselect")
+
+ deselect_button.click(deselect_images, None, gallery)
+
+ def get_select_index(evt: gr.SelectData):
+ return evt.index
+
+ gallery.select(get_select_index, None, selected)
+
+ def darken_img(imgs, index):
+ index = int(index)
+ imgs[index] = np.round(imgs[index] * 0.8).astype(np.uint8)
+ return imgs, imgs
+
+ darken_btn.click(darken_img, [imgs, selected], [imgs, gallery])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/generate_english_german/requirements.txt b/demo/generate_english_german/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4803a9a0e9ae8187b540e01e595e7d10bb49968d
--- /dev/null
+++ b/demo/generate_english_german/requirements.txt
@@ -0,0 +1,2 @@
+transformers
+torch
\ No newline at end of file
diff --git a/demo/generate_english_german/run.ipynb b/demo/generate_english_german/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..52608e681203e451028f49fcee4b8e029bd65dd0
--- /dev/null
+++ b/demo/generate_english_german/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: generate_english_german"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio transformers torch"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "from transformers import pipeline\n", "\n", "english_translator = gr.load(name=\"spaces/gradio/english_translator\")\n", "english_generator = pipeline(\"text-generation\", model=\"distilgpt2\")\n", "\n", "\n", "def generate_text(text):\n", " english_text = english_generator(text)[0][\"generated_text\"]\n", " german_text = english_translator(english_text)\n", " return english_text, german_text\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " seed = gr.Text(label=\"Input Phrase\")\n", " with gr.Column():\n", " english = gr.Text(label=\"Generated English Text\")\n", " german = gr.Text(label=\"Generated German Text\")\n", " btn = gr.Button(\"Generate\")\n", " btn.click(generate_text, inputs=[seed], outputs=[english, german])\n", " gr.Examples([\"My name is Clara and I am\"], inputs=[seed])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/generate_english_german/run.py b/demo/generate_english_german/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..621007e7708557b944a65e5b347eaded2df9bde7
--- /dev/null
+++ b/demo/generate_english_german/run.py
@@ -0,0 +1,27 @@
+import gradio as gr
+
+from transformers import pipeline
+
+english_translator = gr.load(name="spaces/gradio/english_translator")
+english_generator = pipeline("text-generation", model="distilgpt2")
+
+
+def generate_text(text):
+ english_text = english_generator(text)[0]["generated_text"]
+ german_text = english_translator(english_text)
+ return english_text, german_text
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ seed = gr.Text(label="Input Phrase")
+ with gr.Column():
+ english = gr.Text(label="Generated English Text")
+ german = gr.Text(label="Generated German Text")
+ btn = gr.Button("Generate")
+ btn.click(generate_text, inputs=[seed], outputs=[english, german])
+ gr.Examples(["My name is Clara and I am"], inputs=[seed])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/generate_notebooks.py b/demo/generate_notebooks.py
new file mode 100644
index 0000000000000000000000000000000000000000..dcc0f62f63e35df8e3c7be4e00b9f155973ec10e
--- /dev/null
+++ b/demo/generate_notebooks.py
@@ -0,0 +1,82 @@
+import nbformat as nbf
+import os
+import json
+import random
+import subprocess
+
+GRADIO_DEMO_DIR = os.getcwd()
+DEMOS_TO_SKIP = {"all_demos", "reset_components", "custom_path", "kitchen_sink_random"}
+
+demos = os.listdir(GRADIO_DEMO_DIR)
+demos = [demo for demo in demos if demo not in DEMOS_TO_SKIP and os.path.isdir(os.path.join(GRADIO_DEMO_DIR, demo)) and os.path.exists(os.path.join(GRADIO_DEMO_DIR, demo, "run.py"))]
+
+def git_tracked(demo, file):
+ osstdout = subprocess.Popen(f"cd {demo} && git ls-files --error-unmatch {file}", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
+ osstdout.wait()
+ return not osstdout.returncode
+
+for demo in demos:
+ nb = nbf.v4.new_notebook()
+ text = f"# Gradio Demo: {demo}"
+
+ if os.path.exists(os.path.join(GRADIO_DEMO_DIR, demo, "DESCRIPTION.md")):
+ with open(os.path.join(GRADIO_DEMO_DIR, demo, "DESCRIPTION.md"), "r", encoding="utf8") as f:
+ description = f.read()
+ text += f"""\n### {description}
+ """
+
+ files = os.listdir(os.path.join(GRADIO_DEMO_DIR, demo))
+ skip = ["run.py", "run.ipynb", "setup.sh", ".gitignore", "requirements.txt", "DESCRIPTION.md", "screenshot.png", "screenshot.gif"]
+ files = [file for file in files if file not in skip if git_tracked(demo, file)]
+ files.sort()
+ if files:
+ get_files = "# Downloading files from the demo repo\nimport os"
+ for file in files:
+ if os.path.isdir(os.path.join(GRADIO_DEMO_DIR, demo, file)):
+ sub_files = os.listdir(os.path.join(GRADIO_DEMO_DIR, demo, file))
+ sub_files = [sub for sub in sub_files if sub not in skip if git_tracked(demo, f"{file}/{sub}")]
+ sub_files.sort()
+ if sub_files:
+ get_files += f"\nos.mkdir('{file}')"
+ for sub_file in sub_files:
+ get_files += f"\n!wget -q -O {file}/{sub_file} https://github.com/gradio-app/gradio/raw/main/demo/{demo}/{file}/{sub_file}"
+ else:
+ get_files += f"\n!wget -q https://github.com/gradio-app/gradio/raw/main/demo/{demo}/{file}"
+
+ requirements = ""
+ if os.path.exists(os.path.join(GRADIO_DEMO_DIR, demo, "requirements.txt")):
+ with open(os.path.join(GRADIO_DEMO_DIR, demo, "requirements.txt"), "r", encoding="utf8") as f:
+ requirements = f.read().split("\n")
+ requirements = " ".join(requirements)
+
+ installs = f"!pip install -q gradio {requirements}"
+
+ with open(os.path.join(GRADIO_DEMO_DIR, demo, "run.py"), "r", encoding="utf8") as f:
+ code = f.read()
+ code = code.replace("os.path.dirname(__file__)", "os.path.abspath('')")
+
+ if files:
+ nb['cells'] = [nbf.v4.new_markdown_cell(text),
+ nbf.v4.new_code_cell(installs),
+ nbf.v4.new_code_cell(get_files),
+ nbf.v4.new_code_cell(code)]
+ else:
+ nb['cells'] = [nbf.v4.new_markdown_cell(text),
+ nbf.v4.new_code_cell(installs),
+ nbf.v4.new_code_cell(code)]
+
+ output_notebook = os.path.join(GRADIO_DEMO_DIR, demo, "run.ipynb")
+
+ with open(output_notebook, 'w', encoding="utf8") as f:
+ nbf.write(nb, f)
+
+ with open(output_notebook, "r", encoding="utf8") as f:
+ content = f.read()
+
+ content = json.loads(content)
+ for i, cell in enumerate(content["cells"]):
+ random.seed(i)
+ cell["id"] = str(random.getrandbits(128))
+
+ with open(output_notebook, "w", encoding="utf8") as f:
+ f.write(json.dumps(content))
diff --git a/demo/generate_tone/requirements.txt b/demo/generate_tone/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..296d654528b719e554528b956c4bf5a1516e812c
--- /dev/null
+++ b/demo/generate_tone/requirements.txt
@@ -0,0 +1 @@
+numpy
\ No newline at end of file
diff --git a/demo/generate_tone/run.ipynb b/demo/generate_tone/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..989748f5bc4df16ddb2f7a98a8e1d7c0f3eac428
--- /dev/null
+++ b/demo/generate_tone/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: generate_tone"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "import gradio as gr\n", "\n", "notes = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"]\n", "\n", "def generate_tone(note, octave, duration):\n", " sr = 48000\n", " a4_freq, tones_from_a4 = 440, 12 * (octave - 4) + (note - 9)\n", " frequency = a4_freq * 2 ** (tones_from_a4 / 12)\n", " duration = int(duration)\n", " audio = np.linspace(0, duration, duration * sr)\n", " audio = (20000 * np.sin(audio * (2 * np.pi * frequency))).astype(np.int16)\n", " return sr, audio\n", "\n", "demo = gr.Interface(\n", " generate_tone,\n", " [\n", " gr.Dropdown(notes, type=\"index\"),\n", " gr.Slider(4, 6, step=1),\n", " gr.Textbox(value=1, label=\"Duration in seconds\"),\n", " ],\n", " \"audio\",\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/generate_tone/run.py b/demo/generate_tone/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..da71860ae30b901e4408d548889c2e9aff74c1a7
--- /dev/null
+++ b/demo/generate_tone/run.py
@@ -0,0 +1,25 @@
+import numpy as np
+import gradio as gr
+
+notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
+
+def generate_tone(note, octave, duration):
+ sr = 48000
+ a4_freq, tones_from_a4 = 440, 12 * (octave - 4) + (note - 9)
+ frequency = a4_freq * 2 ** (tones_from_a4 / 12)
+ duration = int(duration)
+ audio = np.linspace(0, duration, duration * sr)
+ audio = (20000 * np.sin(audio * (2 * np.pi * frequency))).astype(np.int16)
+ return sr, audio
+
+demo = gr.Interface(
+ generate_tone,
+ [
+ gr.Dropdown(notes, type="index"),
+ gr.Slider(4, 6, step=1),
+ gr.Textbox(value=1, label="Duration in seconds"),
+ ],
+ "audio",
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/generate_tone/screenshot.png b/demo/generate_tone/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..b89ce992199b4dc6a6fde5f485b5fe1690e94b4e
Binary files /dev/null and b/demo/generate_tone/screenshot.png differ
diff --git a/demo/gif_maker/requirements.txt b/demo/gif_maker/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1db7aea116e2b2026e2b660df58af81d997599e6
--- /dev/null
+++ b/demo/gif_maker/requirements.txt
@@ -0,0 +1 @@
+opencv-python
\ No newline at end of file
diff --git a/demo/gif_maker/run.ipynb b/demo/gif_maker/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f4a60a02bb9148b3d86b8619ec5439a3a022a305
--- /dev/null
+++ b/demo/gif_maker/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gif_maker"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio opencv-python"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import cv2\n", "import gradio as gr\n", "\n", "def gif_maker(img_files):\n", " img_array = []\n", " for filename in img_files:\n", " img = cv2.imread(filename.name)\n", " height, width, _ = img.shape\n", " size = (width,height)\n", " img_array.append(img)\n", " output_file = \"test.mp4\"\n", " out = cv2.VideoWriter(output_file,cv2.VideoWriter_fourcc(*'h264'), 15, size) \n", " for i in range(len(img_array)):\n", " out.write(img_array[i])\n", " out.release()\n", " return output_file\n", "\n", "demo = gr.Interface(gif_maker, inputs=gr.File(file_count=\"multiple\"), outputs=gr.Video())\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gif_maker/run.py b/demo/gif_maker/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..67707fd9f8307788da39b7fce578087f53d6e2da
--- /dev/null
+++ b/demo/gif_maker/run.py
@@ -0,0 +1,21 @@
+import cv2
+import gradio as gr
+
+def gif_maker(img_files):
+ img_array = []
+ for filename in img_files:
+ img = cv2.imread(filename.name)
+ height, width, _ = img.shape
+ size = (width,height)
+ img_array.append(img)
+ output_file = "test.mp4"
+ out = cv2.VideoWriter(output_file,cv2.VideoWriter_fourcc(*'h264'), 15, size)
+ for i in range(len(img_array)):
+ out.write(img_array[i])
+ out.release()
+ return output_file
+
+demo = gr.Interface(gif_maker, inputs=gr.File(file_count="multiple"), outputs=gr.Video())
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/gpt2_xl/run.ipynb b/demo/gpt2_xl/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ecb906578d0a0578e9a80812123ac39434839e36
--- /dev/null
+++ b/demo/gpt2_xl/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gpt2_xl"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "title = \"gpt2-xl\"\n", "\n", "examples = [\n", " [\"The tower is 324 metres (1,063 ft) tall,\"],\n", " [\"The Moon's orbit around Earth has\"],\n", " [\"The smooth Borealis basin in the Northern Hemisphere covers 40%\"],\n", "]\n", "\n", "demo = gr.load(\n", " \"huggingface/gpt2-xl\",\n", " inputs=gr.Textbox(lines=5, max_lines=6, label=\"Input Text\"),\n", " title=title,\n", " examples=examples,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gpt2_xl/run.py b/demo/gpt2_xl/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..330c192c3613575cad2e1baf5f42bbe1758eb1f3
--- /dev/null
+++ b/demo/gpt2_xl/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+
+title = "gpt2-xl"
+
+examples = [
+ ["The tower is 324 metres (1,063 ft) tall,"],
+ ["The Moon's orbit around Earth has"],
+ ["The smooth Borealis basin in the Northern Hemisphere covers 40%"],
+]
+
+demo = gr.load(
+ "huggingface/gpt2-xl",
+ inputs=gr.Textbox(lines=5, max_lines=6, label="Input Text"),
+ title=title,
+ examples=examples,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/gpt2_xl_unified/run.ipynb b/demo/gpt2_xl_unified/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..28aa6e08f78a90dd5d91778e7898c6d7577c5131
--- /dev/null
+++ b/demo/gpt2_xl_unified/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gpt2_xl_unified"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "component = gr.Textbox(lines=5, label=\"Text\")\n", "api = gr.load(\"huggingface/gpt2-xl\")\n", "\n", "demo = gr.Interface(\n", " fn=lambda x: x[:-50] + api(x[-50:]),\n", " inputs=component,\n", " outputs=component,\n", " title=\"gpt2-xl\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/gpt2_xl_unified/run.py b/demo/gpt2_xl_unified/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb92d80f42359b09cd1221f737c6f93ea87c245a
--- /dev/null
+++ b/demo/gpt2_xl_unified/run.py
@@ -0,0 +1,14 @@
+import gradio as gr
+
+component = gr.Textbox(lines=5, label="Text")
+api = gr.load("huggingface/gpt2-xl")
+
+demo = gr.Interface(
+ fn=lambda x: x[:-50] + api(x[-50:]),
+ inputs=component,
+ outputs=component,
+ title="gpt2-xl",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/hangman/run.ipynb b/demo/hangman/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e0ff591e59a718f90324c3828d122d004e8bb9f2
--- /dev/null
+++ b/demo/hangman/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hangman"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "secret_word = \"gradio\"\n", "\n", "with gr.Blocks() as demo: \n", " used_letters_var = gr.State([])\n", " with gr.Row() as row:\n", " with gr.Column():\n", " input_letter = gr.Textbox(label=\"Enter letter\")\n", " btn = gr.Button(\"Guess Letter\")\n", " with gr.Column():\n", " hangman = gr.Textbox(\n", " label=\"Hangman\",\n", " value=\"_\"*len(secret_word)\n", " )\n", " used_letters_box = gr.Textbox(label=\"Used Letters\")\n", "\n", " def guess_letter(letter, used_letters):\n", " used_letters.append(letter)\n", " answer = \"\".join([\n", " (letter if letter in used_letters else \"_\")\n", " for letter in secret_word\n", " ])\n", " return {\n", " used_letters_var: used_letters,\n", " used_letters_box: \", \".join(used_letters),\n", " hangman: answer\n", " }\n", " btn.click(\n", " guess_letter, \n", " [input_letter, used_letters_var],\n", " [used_letters_var, used_letters_box, hangman]\n", " )\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hangman/run.py b/demo/hangman/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a0ddc622d5c4b6a73a6ea99ab95a09103a92d62
--- /dev/null
+++ b/demo/hangman/run.py
@@ -0,0 +1,35 @@
+import gradio as gr
+
+secret_word = "gradio"
+
+with gr.Blocks() as demo:
+ used_letters_var = gr.State([])
+ with gr.Row() as row:
+ with gr.Column():
+ input_letter = gr.Textbox(label="Enter letter")
+ btn = gr.Button("Guess Letter")
+ with gr.Column():
+ hangman = gr.Textbox(
+ label="Hangman",
+ value="_"*len(secret_word)
+ )
+ used_letters_box = gr.Textbox(label="Used Letters")
+
+ def guess_letter(letter, used_letters):
+ used_letters.append(letter)
+ answer = "".join([
+ (letter if letter in used_letters else "_")
+ for letter in secret_word
+ ])
+ return {
+ used_letters_var: used_letters,
+ used_letters_box: ", ".join(used_letters),
+ hangman: answer
+ }
+ btn.click(
+ guess_letter,
+ [input_letter, used_letters_var],
+ [used_letters_var, used_letters_box, hangman]
+ )
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/hello_blocks/run.ipynb b/demo/hello_blocks/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7b2773e4ea1488c88c897f98a83ea5f69d779d48
--- /dev/null
+++ b/demo/hello_blocks/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_blocks"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name):\n", " return \"Hello \" + name + \"!\"\n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(label=\"Output Box\")\n", " greet_btn = gr.Button(\"Greet\")\n", " greet_btn.click(fn=greet, inputs=name, outputs=output, api_name=\"greet\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_blocks/run.py b/demo/hello_blocks/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..30451c1389fba4ff806731535b1536c97eb7f023
--- /dev/null
+++ b/demo/hello_blocks/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+ greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/hello_blocks/screenshot.gif b/demo/hello_blocks/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..620ec8ff12cfe88fb4140add3558b7129e82fbef
Binary files /dev/null and b/demo/hello_blocks/screenshot.gif differ
diff --git a/demo/hello_blocks_decorator/run.ipynb b/demo/hello_blocks_decorator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d15dac1b41e9b210e4240702e0161e8bb28c3e3b
--- /dev/null
+++ b/demo/hello_blocks_decorator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_blocks_decorator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(label=\"Output Box\")\n", " greet_btn = gr.Button(\"Greet\")\n", "\n", " @greet_btn.click(inputs=name, outputs=output)\n", " def greet(name):\n", " return \"Hello \" + name + \"!\"\n", "\n", " \n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_blocks_decorator/run.py b/demo/hello_blocks_decorator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c4e17386c910f358a6c7f38ef7ccdf0b0e48802
--- /dev/null
+++ b/demo/hello_blocks_decorator/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+
+ @greet_btn.click(inputs=name, outputs=output)
+ def greet(name):
+ return "Hello " + name + "!"
+
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/hello_blocks_decorator/screenshot.gif b/demo/hello_blocks_decorator/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..620ec8ff12cfe88fb4140add3558b7129e82fbef
Binary files /dev/null and b/demo/hello_blocks_decorator/screenshot.gif differ
diff --git a/demo/hello_login/run.ipynb b/demo/hello_login/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1e97455d259bc1b9307d5922a57185bd2adfdd37
--- /dev/null
+++ b/demo/hello_login/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_login"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import argparse\n", "import sys\n", "\n", "parser = argparse.ArgumentParser()\n", "parser.add_argument(\"--name\", type=str, default=\"User\")\n", "args, unknown = parser.parse_known_args()\n", "print(sys.argv)\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(f\"# Greetings {args.name}!\")\n", " inp = gr.Textbox()\n", " out = gr.Textbox()\n", "\n", " inp.change(fn=lambda x: x, inputs=inp, outputs=out)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_login/run.py b/demo/hello_login/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..0acefb17bc5c6bef33676f75dd7cca74d32094ba
--- /dev/null
+++ b/demo/hello_login/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+import argparse
+import sys
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--name", type=str, default="User")
+args, unknown = parser.parse_known_args()
+print(sys.argv)
+
+with gr.Blocks() as demo:
+ gr.Markdown(f"# Greetings {args.name}!")
+ inp = gr.Textbox()
+ out = gr.Textbox()
+
+ inp.change(fn=lambda x: x, inputs=inp, outputs=out)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/hello_login/screenshot.png b/demo/hello_login/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..a87e6d83d16cb3d60fa7d7de1e12053891c55a6f
Binary files /dev/null and b/demo/hello_login/screenshot.png differ
diff --git a/demo/hello_world/DESCRIPTION.md b/demo/hello_world/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..e4c1c3944e609e3b05f3e0b7f728c332243ed016
--- /dev/null
+++ b/demo/hello_world/DESCRIPTION.md
@@ -0,0 +1 @@
+The simplest possible Gradio demo. It wraps a 'Hello {name}!' function in an Interface that accepts and returns text.
\ No newline at end of file
diff --git a/demo/hello_world/run.ipynb b/demo/hello_world/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..50237220532894979a39669e35501de883b693de
--- /dev/null
+++ b/demo/hello_world/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_world\n", "### The simplest possible Gradio demo. It wraps a 'Hello {name}!' function in an Interface that accepts and returns text.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name):\n", " return \"Hello \" + name + \"!\"\n", "\n", "demo = gr.Interface(fn=greet, inputs=\"textbox\", outputs=\"textbox\")\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch() "]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_world/run.py b/demo/hello_world/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa488212ecbf992386ad43c22dad063370665867
--- /dev/null
+++ b/demo/hello_world/run.py
@@ -0,0 +1,9 @@
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/hello_world/screenshot.gif b/demo/hello_world/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8b923a09972c54f7c43dd1e328c86bc9aa9a117a
Binary files /dev/null and b/demo/hello_world/screenshot.gif differ
diff --git a/demo/hello_world/screenshot.png b/demo/hello_world/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..962ce78edc7702c2c9ccd1f5dbd27a2ad4a1c6e4
Binary files /dev/null and b/demo/hello_world/screenshot.png differ
diff --git a/demo/hello_world_2/run.ipynb b/demo/hello_world_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..60d1dcb1153e7a65f39444f4258255600f55b396
--- /dev/null
+++ b/demo/hello_world_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_world_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name, intensity):\n", " return \"Hello \" * intensity + name + \"!\"\n", "\n", "demo = gr.Interface(\n", " fn=greet,\n", " inputs=[\"text\", gr.Slider(value=2, minimum=1, maximum=10)],\n", " outputs=[gr.Textbox(label=\"greeting\", lines=3)],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_world_2/run.py b/demo/hello_world_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0c906c8667745dd2830a2b92d556dacf128ac47
--- /dev/null
+++ b/demo/hello_world_2/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+def greet(name, intensity):
+ return "Hello " * intensity + name + "!"
+
+demo = gr.Interface(
+ fn=greet,
+ inputs=["text", gr.Slider(value=2, minimum=1, maximum=10)],
+ outputs=[gr.Textbox(label="greeting", lines=3)],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/hello_world_2/screenshot.gif b/demo/hello_world_2/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d99ef184d9cf1ab18e86d6356a900f031d5c83f6
--- /dev/null
+++ b/demo/hello_world_2/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:97269daef7203ef7727cba3e0f5a90afa060219692ba535c06818fdc8f11fe06
+size 1121749
diff --git a/demo/hello_world_3/run.ipynb b/demo/hello_world_3/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d28fb265daf53523e5087a88313d34fc14d428d3
--- /dev/null
+++ b/demo/hello_world_3/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_world_3"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name, is_morning, temperature):\n", " salutation = \"Good morning\" if is_morning else \"Good evening\"\n", " greeting = f\"{salutation} {name}. It is {temperature} degrees today\"\n", " celsius = (temperature - 32) * 5 / 9\n", " return greeting, round(celsius, 2)\n", "\n", "demo = gr.Interface(\n", " fn=greet,\n", " inputs=[\"text\", \"checkbox\", gr.Slider(0, 100)],\n", " outputs=[\"text\", \"number\"],\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_world_3/run.py b/demo/hello_world_3/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbf93b959140a14f39b818ec61e3db5eacc9739d
--- /dev/null
+++ b/demo/hello_world_3/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+def greet(name, is_morning, temperature):
+ salutation = "Good morning" if is_morning else "Good evening"
+ greeting = f"{salutation} {name}. It is {temperature} degrees today"
+ celsius = (temperature - 32) * 5 / 9
+ return greeting, round(celsius, 2)
+
+demo = gr.Interface(
+ fn=greet,
+ inputs=["text", "checkbox", gr.Slider(0, 100)],
+ outputs=["text", "number"],
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/hello_world_3/screenshot.gif b/demo/hello_world_3/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..44d8ed04cc1cfc1a334cdbcdbf7f45eac0b3ef8f
Binary files /dev/null and b/demo/hello_world_3/screenshot.gif differ
diff --git a/demo/hello_world_4/run.ipynb b/demo/hello_world_4/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e8a8385b502da3b9e8ee1432e7dbf2873dba790c
--- /dev/null
+++ b/demo/hello_world_4/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: hello_world_4"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def greet(name, intensity):\n", " return \"Hello \" * intensity + name + \"!\"\n", "\n", "demo = gr.Interface(\n", " fn=greet,\n", " inputs=[\"text\", \"slider\"],\n", " outputs=[\"text\"],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/hello_world_4/run.py b/demo/hello_world_4/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..09b7f55c238abd3f92aed97e154d0da1ef7b0f09
--- /dev/null
+++ b/demo/hello_world_4/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+def greet(name, intensity):
+ return "Hello " * intensity + name + "!"
+
+demo = gr.Interface(
+ fn=greet,
+ inputs=["text", "slider"],
+ outputs=["text"],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/hello_world_4/screenshot.gif b/demo/hello_world_4/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..26d476990b973e81deeb752106ebf714d609aa10
--- /dev/null
+++ b/demo/hello_world_4/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4024abacd2debd54ea47017c6680f217c52fb7ccad2b05144ed3002aa6c8e75a
+size 1341573
diff --git a/demo/highlightedtext_component/run.ipynb b/demo/highlightedtext_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..65444e7dc31c87098d41d13607f3178cdfdde593
--- /dev/null
+++ b/demo/highlightedtext_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: highlightedtext_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.HighlightedText(\n", " combine_adjacent=True,\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/highlightedtext_component/run.py b/demo/highlightedtext_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd3fda76d4ef53ec2364908e8c08d13c23321eaf
--- /dev/null
+++ b/demo/highlightedtext_component/run.py
@@ -0,0 +1,8 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HighlightedText(
+ combine_adjacent=True,
+ )
+
+demo.launch()
diff --git a/demo/html_component/run.ipynb b/demo/html_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..61e3aa494e4ca3f054fdde9fd3166e7ed19ebec1
--- /dev/null
+++ b/demo/html_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: html_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.HTML(value=\" This example was written in HTML
\")\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/html_component/run.py b/demo/html_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c3f533d9c4993764ae3701900fb4dd6b12aecf8c
--- /dev/null
+++ b/demo/html_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML(value="This example was written in HTML
")
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/image-simple/cheetah.jpg b/demo/image-simple/cheetah.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d1fde62d026aeb594fd6c989bc893da13e68b9dc
Binary files /dev/null and b/demo/image-simple/cheetah.jpg differ
diff --git a/demo/image-simple/run.ipynb b/demo/image-simple/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1a91f41e96aa742e81feb8352b1fd7094a428710
--- /dev/null
+++ b/demo/image-simple/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image-simple"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image-simple/cheetah.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def image(im):\n", " return im\n", "\n", "\n", "with gr.Blocks() as demo:\n", " im = gr.Image()\n", " im2 = gr.Image()\n", " btn = gr.Button()\n", " btn.click(lambda x: x, outputs=im2, inputs=im)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image-simple/run.py b/demo/image-simple/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff406f0d0b7bec0d4c3422e2cb31decc0ab7c53e
--- /dev/null
+++ b/demo/image-simple/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+
+def image(im):
+ return im
+
+
+with gr.Blocks() as demo:
+ im = gr.Image()
+ im2 = gr.Image()
+ btn = gr.Button()
+ btn.click(lambda x: x, outputs=im2, inputs=im)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_classification/DESCRIPTION.md b/demo/image_classification/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..7b0ce5034235b310b439e8317614e4c52ee81d1c
--- /dev/null
+++ b/demo/image_classification/DESCRIPTION.md
@@ -0,0 +1 @@
+Simple image classification in Pytorch with Gradio's Image input and Label output.
\ No newline at end of file
diff --git a/demo/image_classification/cheetah.jpg b/demo/image_classification/cheetah.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d1fde62d026aeb594fd6c989bc893da13e68b9dc
Binary files /dev/null and b/demo/image_classification/cheetah.jpg differ
diff --git a/demo/image_classification/requirements.txt b/demo/image_classification/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..37f700a78ecad7bea22172702e640797d7136a17
--- /dev/null
+++ b/demo/image_classification/requirements.txt
@@ -0,0 +1,2 @@
+torch
+torchvision
\ No newline at end of file
diff --git a/demo/image_classification/run.ipynb b/demo/image_classification/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..97e4ed4974cc795b89ace6580938b5814592621c
--- /dev/null
+++ b/demo/image_classification/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_classification\n", "### Simple image classification in Pytorch with Gradio's Image input and Label output.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch torchvision"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image_classification/cheetah.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "import requests\n", "from torchvision import transforms\n", "\n", "model = torch.hub.load('pytorch/vision:v0.6.0', 'resnet18', pretrained=True).eval()\n", "response = requests.get(\"https://git.io/JJkYN\")\n", "labels = response.text.split(\"\\n\")\n", "\n", "def predict(inp):\n", " inp = transforms.ToTensor()(inp).unsqueeze(0)\n", " with torch.no_grad():\n", " prediction = torch.nn.functional.softmax(model(inp)[0], dim=0)\n", " confidences = {labels[i]: float(prediction[i]) for i in range(1000)} \n", " return confidences\n", "\n", "demo = gr.Interface(fn=predict, \n", " inputs=gr.Image(type=\"pil\"),\n", " outputs=gr.Label(num_top_classes=3),\n", " examples=[[\"cheetah.jpg\"]],\n", " )\n", " \n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_classification/run.py b/demo/image_classification/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..454f94c12369c8da02ed0b44816ed24f34f9f4f4
--- /dev/null
+++ b/demo/image_classification/run.py
@@ -0,0 +1,23 @@
+import gradio as gr
+import torch
+import requests
+from torchvision import transforms
+
+model = torch.hub.load('pytorch/vision:v0.6.0', 'resnet18', pretrained=True).eval()
+response = requests.get("https://git.io/JJkYN")
+labels = response.text.split("\n")
+
+def predict(inp):
+ inp = transforms.ToTensor()(inp).unsqueeze(0)
+ with torch.no_grad():
+ prediction = torch.nn.functional.softmax(model(inp)[0], dim=0)
+ confidences = {labels[i]: float(prediction[i]) for i in range(1000)}
+ return confidences
+
+demo = gr.Interface(fn=predict,
+ inputs=gr.Image(type="pil"),
+ outputs=gr.Label(num_top_classes=3),
+ examples=[["cheetah.jpg"]],
+ )
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/image_classifier/files/imagenet_labels.json b/demo/image_classifier/files/imagenet_labels.json
new file mode 100644
index 0000000000000000000000000000000000000000..fa059ceeab5d18ab9882df2983b92e8270373e39
--- /dev/null
+++ b/demo/image_classifier/files/imagenet_labels.json
@@ -0,0 +1,1000 @@
+["tench",
+ "goldfish",
+ "great white shark",
+ "tiger shark",
+ "hammerhead shark",
+ "electric ray",
+ "stingray",
+ "cock",
+ "hen",
+ "ostrich",
+ "brambling",
+ "goldfinch",
+ "house finch",
+ "junco",
+ "indigo bunting",
+ "American robin",
+ "bulbul",
+ "jay",
+ "magpie",
+ "chickadee",
+ "American dipper",
+ "kite",
+ "bald eagle",
+ "vulture",
+ "great grey owl",
+ "fire salamander",
+ "smooth newt",
+ "newt",
+ "spotted salamander",
+ "axolotl",
+ "American bullfrog",
+ "tree frog",
+ "tailed frog",
+ "loggerhead sea turtle",
+ "leatherback sea turtle",
+ "mud turtle",
+ "terrapin",
+ "box turtle",
+ "banded gecko",
+ "green iguana",
+ "Carolina anole",
+ "desert grassland whiptail lizard",
+ "agama",
+ "frilled-necked lizard",
+ "alligator lizard",
+ "Gila monster",
+ "European green lizard",
+ "chameleon",
+ "Komodo dragon",
+ "Nile crocodile",
+ "American alligator",
+ "triceratops",
+ "worm snake",
+ "ring-necked snake",
+ "eastern hog-nosed snake",
+ "smooth green snake",
+ "kingsnake",
+ "garter snake",
+ "water snake",
+ "vine snake",
+ "night snake",
+ "boa constrictor",
+ "African rock python",
+ "Indian cobra",
+ "green mamba",
+ "sea snake",
+ "Saharan horned viper",
+ "eastern diamondback rattlesnake",
+ "sidewinder",
+ "trilobite",
+ "harvestman",
+ "scorpion",
+ "yellow garden spider",
+ "barn spider",
+ "European garden spider",
+ "southern black widow",
+ "tarantula",
+ "wolf spider",
+ "tick",
+ "centipede",
+ "black grouse",
+ "ptarmigan",
+ "ruffed grouse",
+ "prairie grouse",
+ "peacock",
+ "quail",
+ "partridge",
+ "grey parrot",
+ "macaw",
+ "sulphur-crested cockatoo",
+ "lorikeet",
+ "coucal",
+ "bee eater",
+ "hornbill",
+ "hummingbird",
+ "jacamar",
+ "toucan",
+ "duck",
+ "red-breasted merganser",
+ "goose",
+ "black swan",
+ "tusker",
+ "echidna",
+ "platypus",
+ "wallaby",
+ "koala",
+ "wombat",
+ "jellyfish",
+ "sea anemone",
+ "brain coral",
+ "flatworm",
+ "nematode",
+ "conch",
+ "snail",
+ "slug",
+ "sea slug",
+ "chiton",
+ "chambered nautilus",
+ "Dungeness crab",
+ "rock crab",
+ "fiddler crab",
+ "red king crab",
+ "American lobster",
+ "spiny lobster",
+ "crayfish",
+ "hermit crab",
+ "isopod",
+ "white stork",
+ "black stork",
+ "spoonbill",
+ "flamingo",
+ "little blue heron",
+ "great egret",
+ "bittern",
+ "crane (bird)",
+ "limpkin",
+ "common gallinule",
+ "American coot",
+ "bustard",
+ "ruddy turnstone",
+ "dunlin",
+ "common redshank",
+ "dowitcher",
+ "oystercatcher",
+ "pelican",
+ "king penguin",
+ "albatross",
+ "grey whale",
+ "killer whale",
+ "dugong",
+ "sea lion",
+ "Chihuahua",
+ "Japanese Chin",
+ "Maltese",
+ "Pekingese",
+ "Shih Tzu",
+ "King Charles Spaniel",
+ "Papillon",
+ "toy terrier",
+ "Rhodesian Ridgeback",
+ "Afghan Hound",
+ "Basset Hound",
+ "Beagle",
+ "Bloodhound",
+ "Bluetick Coonhound",
+ "Black and Tan Coonhound",
+ "Treeing Walker Coonhound",
+ "English foxhound",
+ "Redbone Coonhound",
+ "borzoi",
+ "Irish Wolfhound",
+ "Italian Greyhound",
+ "Whippet",
+ "Ibizan Hound",
+ "Norwegian Elkhound",
+ "Otterhound",
+ "Saluki",
+ "Scottish Deerhound",
+ "Weimaraner",
+ "Staffordshire Bull Terrier",
+ "American Staffordshire Terrier",
+ "Bedlington Terrier",
+ "Border Terrier",
+ "Kerry Blue Terrier",
+ "Irish Terrier",
+ "Norfolk Terrier",
+ "Norwich Terrier",
+ "Yorkshire Terrier",
+ "Wire Fox Terrier",
+ "Lakeland Terrier",
+ "Sealyham Terrier",
+ "Airedale Terrier",
+ "Cairn Terrier",
+ "Australian Terrier",
+ "Dandie Dinmont Terrier",
+ "Boston Terrier",
+ "Miniature Schnauzer",
+ "Giant Schnauzer",
+ "Standard Schnauzer",
+ "Scottish Terrier",
+ "Tibetan Terrier",
+ "Australian Silky Terrier",
+ "Soft-coated Wheaten Terrier",
+ "West Highland White Terrier",
+ "Lhasa Apso",
+ "Flat-Coated Retriever",
+ "Curly-coated Retriever",
+ "Golden Retriever",
+ "Labrador Retriever",
+ "Chesapeake Bay Retriever",
+ "German Shorthaired Pointer",
+ "Vizsla",
+ "English Setter",
+ "Irish Setter",
+ "Gordon Setter",
+ "Brittany",
+ "Clumber Spaniel",
+ "English Springer Spaniel",
+ "Welsh Springer Spaniel",
+ "Cocker Spaniels",
+ "Sussex Spaniel",
+ "Irish Water Spaniel",
+ "Kuvasz",
+ "Schipperke",
+ "Groenendael",
+ "Malinois",
+ "Briard",
+ "Australian Kelpie",
+ "Komondor",
+ "Old English Sheepdog",
+ "Shetland Sheepdog",
+ "collie",
+ "Border Collie",
+ "Bouvier des Flandres",
+ "Rottweiler",
+ "German Shepherd Dog",
+ "Dobermann",
+ "Miniature Pinscher",
+ "Greater Swiss Mountain Dog",
+ "Bernese Mountain Dog",
+ "Appenzeller Sennenhund",
+ "Entlebucher Sennenhund",
+ "Boxer",
+ "Bullmastiff",
+ "Tibetan Mastiff",
+ "French Bulldog",
+ "Great Dane",
+ "St. Bernard",
+ "husky",
+ "Alaskan Malamute",
+ "Siberian Husky",
+ "Dalmatian",
+ "Affenpinscher",
+ "Basenji",
+ "pug",
+ "Leonberger",
+ "Newfoundland",
+ "Pyrenean Mountain Dog",
+ "Samoyed",
+ "Pomeranian",
+ "Chow Chow",
+ "Keeshond",
+ "Griffon Bruxellois",
+ "Pembroke Welsh Corgi",
+ "Cardigan Welsh Corgi",
+ "Toy Poodle",
+ "Miniature Poodle",
+ "Standard Poodle",
+ "Mexican hairless dog",
+ "grey wolf",
+ "Alaskan tundra wolf",
+ "red wolf",
+ "coyote",
+ "dingo",
+ "dhole",
+ "African wild dog",
+ "hyena",
+ "red fox",
+ "kit fox",
+ "Arctic fox",
+ "grey fox",
+ "tabby cat",
+ "tiger cat",
+ "Persian cat",
+ "Siamese cat",
+ "Egyptian Mau",
+ "cougar",
+ "lynx",
+ "leopard",
+ "snow leopard",
+ "jaguar",
+ "lion",
+ "tiger",
+ "cheetah",
+ "brown bear",
+ "American black bear",
+ "polar bear",
+ "sloth bear",
+ "mongoose",
+ "meerkat",
+ "tiger beetle",
+ "ladybug",
+ "ground beetle",
+ "longhorn beetle",
+ "leaf beetle",
+ "dung beetle",
+ "rhinoceros beetle",
+ "weevil",
+ "fly",
+ "bee",
+ "ant",
+ "grasshopper",
+ "cricket",
+ "stick insect",
+ "cockroach",
+ "mantis",
+ "cicada",
+ "leafhopper",
+ "lacewing",
+ "dragonfly",
+ "damselfly",
+ "red admiral",
+ "ringlet",
+ "monarch butterfly",
+ "small white",
+ "sulphur butterfly",
+ "gossamer-winged butterfly",
+ "starfish",
+ "sea urchin",
+ "sea cucumber",
+ "cottontail rabbit",
+ "hare",
+ "Angora rabbit",
+ "hamster",
+ "porcupine",
+ "fox squirrel",
+ "marmot",
+ "beaver",
+ "guinea pig",
+ "common sorrel",
+ "zebra",
+ "pig",
+ "wild boar",
+ "warthog",
+ "hippopotamus",
+ "ox",
+ "water buffalo",
+ "bison",
+ "ram",
+ "bighorn sheep",
+ "Alpine ibex",
+ "hartebeest",
+ "impala",
+ "gazelle",
+ "dromedary",
+ "llama",
+ "weasel",
+ "mink",
+ "European polecat",
+ "black-footed ferret",
+ "otter",
+ "skunk",
+ "badger",
+ "armadillo",
+ "three-toed sloth",
+ "orangutan",
+ "gorilla",
+ "chimpanzee",
+ "gibbon",
+ "siamang",
+ "guenon",
+ "patas monkey",
+ "baboon",
+ "macaque",
+ "langur",
+ "black-and-white colobus",
+ "proboscis monkey",
+ "marmoset",
+ "white-headed capuchin",
+ "howler monkey",
+ "titi",
+ "Geoffroy's spider monkey",
+ "common squirrel monkey",
+ "ring-tailed lemur",
+ "indri",
+ "Asian elephant",
+ "African bush elephant",
+ "red panda",
+ "giant panda",
+ "snoek",
+ "eel",
+ "coho salmon",
+ "rock beauty",
+ "clownfish",
+ "sturgeon",
+ "garfish",
+ "lionfish",
+ "pufferfish",
+ "abacus",
+ "abaya",
+ "academic gown",
+ "accordion",
+ "acoustic guitar",
+ "aircraft carrier",
+ "airliner",
+ "airship",
+ "altar",
+ "ambulance",
+ "amphibious vehicle",
+ "analog clock",
+ "apiary",
+ "apron",
+ "waste container",
+ "assault rifle",
+ "backpack",
+ "bakery",
+ "balance beam",
+ "balloon",
+ "ballpoint pen",
+ "Band-Aid",
+ "banjo",
+ "baluster",
+ "barbell",
+ "barber chair",
+ "barbershop",
+ "barn",
+ "barometer",
+ "barrel",
+ "wheelbarrow",
+ "baseball",
+ "basketball",
+ "bassinet",
+ "bassoon",
+ "swimming cap",
+ "bath towel",
+ "bathtub",
+ "station wagon",
+ "lighthouse",
+ "beaker",
+ "military cap",
+ "beer bottle",
+ "beer glass",
+ "bell-cot",
+ "bib",
+ "tandem bicycle",
+ "bikini",
+ "ring binder",
+ "binoculars",
+ "birdhouse",
+ "boathouse",
+ "bobsleigh",
+ "bolo tie",
+ "poke bonnet",
+ "bookcase",
+ "bookstore",
+ "bottle cap",
+ "bow",
+ "bow tie",
+ "brass",
+ "bra",
+ "breakwater",
+ "breastplate",
+ "broom",
+ "bucket",
+ "buckle",
+ "bulletproof vest",
+ "high-speed train",
+ "butcher shop",
+ "taxicab",
+ "cauldron",
+ "candle",
+ "cannon",
+ "canoe",
+ "can opener",
+ "cardigan",
+ "car mirror",
+ "carousel",
+ "tool kit",
+ "carton",
+ "car wheel",
+ "automated teller machine",
+ "cassette",
+ "cassette player",
+ "castle",
+ "catamaran",
+ "CD player",
+ "cello",
+ "mobile phone",
+ "chain",
+ "chain-link fence",
+ "chain mail",
+ "chainsaw",
+ "chest",
+ "chiffonier",
+ "chime",
+ "china cabinet",
+ "Christmas stocking",
+ "church",
+ "movie theater",
+ "cleaver",
+ "cliff dwelling",
+ "cloak",
+ "clogs",
+ "cocktail shaker",
+ "coffee mug",
+ "coffeemaker",
+ "coil",
+ "combination lock",
+ "computer keyboard",
+ "confectionery store",
+ "container ship",
+ "convertible",
+ "corkscrew",
+ "cornet",
+ "cowboy boot",
+ "cowboy hat",
+ "cradle",
+ "crane (machine)",
+ "crash helmet",
+ "crate",
+ "infant bed",
+ "Crock Pot",
+ "croquet ball",
+ "crutch",
+ "cuirass",
+ "dam",
+ "desk",
+ "desktop computer",
+ "rotary dial telephone",
+ "diaper",
+ "digital clock",
+ "digital watch",
+ "dining table",
+ "dishcloth",
+ "dishwasher",
+ "disc brake",
+ "dock",
+ "dog sled",
+ "dome",
+ "doormat",
+ "drilling rig",
+ "drum",
+ "drumstick",
+ "dumbbell",
+ "Dutch oven",
+ "electric fan",
+ "electric guitar",
+ "electric locomotive",
+ "entertainment center",
+ "envelope",
+ "espresso machine",
+ "face powder",
+ "feather boa",
+ "filing cabinet",
+ "fireboat",
+ "fire engine",
+ "fire screen sheet",
+ "flagpole",
+ "flute",
+ "folding chair",
+ "football helmet",
+ "forklift",
+ "fountain",
+ "fountain pen",
+ "four-poster bed",
+ "freight car",
+ "French horn",
+ "frying pan",
+ "fur coat",
+ "garbage truck",
+ "gas mask",
+ "gas pump",
+ "goblet",
+ "go-kart",
+ "golf ball",
+ "golf cart",
+ "gondola",
+ "gong",
+ "gown",
+ "grand piano",
+ "greenhouse",
+ "grille",
+ "grocery store",
+ "guillotine",
+ "barrette",
+ "hair spray",
+ "half-track",
+ "hammer",
+ "hamper",
+ "hair dryer",
+ "hand-held computer",
+ "handkerchief",
+ "hard disk drive",
+ "harmonica",
+ "harp",
+ "harvester",
+ "hatchet",
+ "holster",
+ "home theater",
+ "honeycomb",
+ "hook",
+ "hoop skirt",
+ "horizontal bar",
+ "horse-drawn vehicle",
+ "hourglass",
+ "iPod",
+ "clothes iron",
+ "jack-o'-lantern",
+ "jeans",
+ "jeep",
+ "T-shirt",
+ "jigsaw puzzle",
+ "pulled rickshaw",
+ "joystick",
+ "kimono",
+ "knee pad",
+ "knot",
+ "lab coat",
+ "ladle",
+ "lampshade",
+ "laptop computer",
+ "lawn mower",
+ "lens cap",
+ "paper knife",
+ "library",
+ "lifeboat",
+ "lighter",
+ "limousine",
+ "ocean liner",
+ "lipstick",
+ "slip-on shoe",
+ "lotion",
+ "speaker",
+ "loupe",
+ "sawmill",
+ "magnetic compass",
+ "mail bag",
+ "mailbox",
+ "tights",
+ "tank suit",
+ "manhole cover",
+ "maraca",
+ "marimba",
+ "mask",
+ "match",
+ "maypole",
+ "maze",
+ "measuring cup",
+ "medicine chest",
+ "megalith",
+ "microphone",
+ "microwave oven",
+ "military uniform",
+ "milk can",
+ "minibus",
+ "miniskirt",
+ "minivan",
+ "missile",
+ "mitten",
+ "mixing bowl",
+ "mobile home",
+ "Model T",
+ "modem",
+ "monastery",
+ "monitor",
+ "moped",
+ "mortar",
+ "square academic cap",
+ "mosque",
+ "mosquito net",
+ "scooter",
+ "mountain bike",
+ "tent",
+ "computer mouse",
+ "mousetrap",
+ "moving van",
+ "muzzle",
+ "nail",
+ "neck brace",
+ "necklace",
+ "nipple",
+ "notebook computer",
+ "obelisk",
+ "oboe",
+ "ocarina",
+ "odometer",
+ "oil filter",
+ "organ",
+ "oscilloscope",
+ "overskirt",
+ "bullock cart",
+ "oxygen mask",
+ "packet",
+ "paddle",
+ "paddle wheel",
+ "padlock",
+ "paintbrush",
+ "pajamas",
+ "palace",
+ "pan flute",
+ "paper towel",
+ "parachute",
+ "parallel bars",
+ "park bench",
+ "parking meter",
+ "passenger car",
+ "patio",
+ "payphone",
+ "pedestal",
+ "pencil case",
+ "pencil sharpener",
+ "perfume",
+ "Petri dish",
+ "photocopier",
+ "plectrum",
+ "Pickelhaube",
+ "picket fence",
+ "pickup truck",
+ "pier",
+ "piggy bank",
+ "pill bottle",
+ "pillow",
+ "ping-pong ball",
+ "pinwheel",
+ "pirate ship",
+ "pitcher",
+ "hand plane",
+ "planetarium",
+ "plastic bag",
+ "plate rack",
+ "plow",
+ "plunger",
+ "Polaroid camera",
+ "pole",
+ "police van",
+ "poncho",
+ "billiard table",
+ "soda bottle",
+ "pot",
+ "potter's wheel",
+ "power drill",
+ "prayer rug",
+ "printer",
+ "prison",
+ "projectile",
+ "projector",
+ "hockey puck",
+ "punching bag",
+ "purse",
+ "quill",
+ "quilt",
+ "race car",
+ "racket",
+ "radiator",
+ "radio",
+ "radio telescope",
+ "rain barrel",
+ "recreational vehicle",
+ "reel",
+ "reflex camera",
+ "refrigerator",
+ "remote control",
+ "restaurant",
+ "revolver",
+ "rifle",
+ "rocking chair",
+ "rotisserie",
+ "eraser",
+ "rugby ball",
+ "ruler",
+ "running shoe",
+ "safe",
+ "safety pin",
+ "salt shaker",
+ "sandal",
+ "sarong",
+ "saxophone",
+ "scabbard",
+ "weighing scale",
+ "school bus",
+ "schooner",
+ "scoreboard",
+ "CRT screen",
+ "screw",
+ "screwdriver",
+ "seat belt",
+ "sewing machine",
+ "shield",
+ "shoe store",
+ "shoji",
+ "shopping basket",
+ "shopping cart",
+ "shovel",
+ "shower cap",
+ "shower curtain",
+ "ski",
+ "ski mask",
+ "sleeping bag",
+ "slide rule",
+ "sliding door",
+ "slot machine",
+ "snorkel",
+ "snowmobile",
+ "snowplow",
+ "soap dispenser",
+ "soccer ball",
+ "sock",
+ "solar thermal collector",
+ "sombrero",
+ "soup bowl",
+ "space bar",
+ "space heater",
+ "space shuttle",
+ "spatula",
+ "motorboat",
+ "spider web",
+ "spindle",
+ "sports car",
+ "spotlight",
+ "stage",
+ "steam locomotive",
+ "through arch bridge",
+ "steel drum",
+ "stethoscope",
+ "scarf",
+ "stone wall",
+ "stopwatch",
+ "stove",
+ "strainer",
+ "tram",
+ "stretcher",
+ "couch",
+ "stupa",
+ "submarine",
+ "suit",
+ "sundial",
+ "sunglass",
+ "sunglasses",
+ "sunscreen",
+ "suspension bridge",
+ "mop",
+ "sweatshirt",
+ "swimsuit",
+ "swing",
+ "switch",
+ "syringe",
+ "table lamp",
+ "tank",
+ "tape player",
+ "teapot",
+ "teddy bear",
+ "television",
+ "tennis ball",
+ "thatched roof",
+ "front curtain",
+ "thimble",
+ "threshing machine",
+ "throne",
+ "tile roof",
+ "toaster",
+ "tobacco shop",
+ "toilet seat",
+ "torch",
+ "totem pole",
+ "tow truck",
+ "toy store",
+ "tractor",
+ "semi-trailer truck",
+ "tray",
+ "trench coat",
+ "tricycle",
+ "trimaran",
+ "tripod",
+ "triumphal arch",
+ "trolleybus",
+ "trombone",
+ "tub",
+ "turnstile",
+ "typewriter keyboard",
+ "umbrella",
+ "unicycle",
+ "upright piano",
+ "vacuum cleaner",
+ "vase",
+ "vault",
+ "velvet",
+ "vending machine",
+ "vestment",
+ "viaduct",
+ "violin",
+ "volleyball",
+ "waffle iron",
+ "wall clock",
+ "wallet",
+ "wardrobe",
+ "military aircraft",
+ "sink",
+ "washing machine",
+ "water bottle",
+ "water jug",
+ "water tower",
+ "whiskey jug",
+ "whistle",
+ "wig",
+ "window screen",
+ "window shade",
+ "Windsor tie",
+ "wine bottle",
+ "wing",
+ "wok",
+ "wooden spoon",
+ "wool",
+ "split-rail fence",
+ "shipwreck",
+ "yawl",
+ "yurt",
+ "website",
+ "comic book",
+ "crossword",
+ "traffic sign",
+ "traffic light",
+ "dust jacket",
+ "menu",
+ "plate",
+ "guacamole",
+ "consomme",
+ "hot pot",
+ "trifle",
+ "ice cream",
+ "ice pop",
+ "baguette",
+ "bagel",
+ "pretzel",
+ "cheeseburger",
+ "hot dog",
+ "mashed potato",
+ "cabbage",
+ "broccoli",
+ "cauliflower",
+ "zucchini",
+ "spaghetti squash",
+ "acorn squash",
+ "butternut squash",
+ "cucumber",
+ "artichoke",
+ "bell pepper",
+ "cardoon",
+ "mushroom",
+ "Granny Smith",
+ "strawberry",
+ "orange",
+ "lemon",
+ "fig",
+ "pineapple",
+ "banana",
+ "jackfruit",
+ "custard apple",
+ "pomegranate",
+ "hay",
+ "carbonara",
+ "chocolate syrup",
+ "dough",
+ "meatloaf",
+ "pizza",
+ "pot pie",
+ "burrito",
+ "red wine",
+ "espresso",
+ "cup",
+ "eggnog",
+ "alp",
+ "bubble",
+ "cliff",
+ "coral reef",
+ "geyser",
+ "lakeshore",
+ "promontory",
+ "shoal",
+ "seashore",
+ "valley",
+ "volcano",
+ "baseball player",
+ "bridegroom",
+ "scuba diver",
+ "rapeseed",
+ "daisy",
+ "yellow lady's slipper",
+ "corn",
+ "acorn",
+ "rose hip",
+ "horse chestnut seed",
+ "coral fungus",
+ "agaric",
+ "gyromitra",
+ "stinkhorn mushroom",
+ "earth star",
+ "hen-of-the-woods",
+ "bolete",
+ "ear",
+ "toilet paper"]
\ No newline at end of file
diff --git a/demo/image_classifier/images/cheetah1.jpg b/demo/image_classifier/images/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/image_classifier/images/cheetah1.jpg differ
diff --git a/demo/image_classifier/images/lion.jpg b/demo/image_classifier/images/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/image_classifier/images/lion.jpg differ
diff --git a/demo/image_classifier/requirements.txt b/demo/image_classifier/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c2bbfa1f2b3c72184f27937009c87c54c826806c
--- /dev/null
+++ b/demo/image_classifier/requirements.txt
@@ -0,0 +1,2 @@
+numpy
+tensorflow
\ No newline at end of file
diff --git a/demo/image_classifier/run.ipynb b/demo/image_classifier/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..020f71da17a9a74a89ece2aaaea7535c803b4250
--- /dev/null
+++ b/demo/image_classifier/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_classifier"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy tensorflow"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/imagenet_labels.json https://github.com/gradio-app/gradio/raw/main/demo/image_classifier/files/imagenet_labels.json\n", "os.mkdir('images')\n", "!wget -q -O images/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_classifier/images/cheetah1.jpg\n", "!wget -q -O images/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_classifier/images/lion.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "import requests\n", "import tensorflow as tf\n", "\n", "import gradio as gr\n", "\n", "inception_net = tf.keras.applications.MobileNetV2() # load the model\n", "\n", "# Download human-readable labels for ImageNet.\n", "response = requests.get(\"https://git.io/JJkYN\")\n", "labels = response.text.split(\"\\n\")\n", "\n", "\n", "def classify_image(inp):\n", " inp = inp.reshape((-1, 224, 224, 3))\n", " inp = tf.keras.applications.mobilenet_v2.preprocess_input(inp)\n", " prediction = inception_net.predict(inp).flatten()\n", " return {labels[i]: float(prediction[i]) for i in range(1000)}\n", "\n", "\n", "image = gr.Image(shape=(224, 224))\n", "label = gr.Label(num_top_classes=3)\n", "\n", "demo = gr.Interface(\n", " fn=classify_image,\n", " inputs=image,\n", " outputs=label,\n", " examples=[\n", " os.path.join(os.path.abspath(''), \"images/cheetah1.jpg\"),\n", " os.path.join(os.path.abspath(''), \"images/lion.jpg\")\n", " ]\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", "\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_classifier/run.py b/demo/image_classifier/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e96de59317712ccb41d44e7cb184d639d66e0fb9
--- /dev/null
+++ b/demo/image_classifier/run.py
@@ -0,0 +1,36 @@
+import os
+import requests
+import tensorflow as tf
+
+import gradio as gr
+
+inception_net = tf.keras.applications.MobileNetV2() # load the model
+
+# Download human-readable labels for ImageNet.
+response = requests.get("https://git.io/JJkYN")
+labels = response.text.split("\n")
+
+
+def classify_image(inp):
+ inp = inp.reshape((-1, 224, 224, 3))
+ inp = tf.keras.applications.mobilenet_v2.preprocess_input(inp)
+ prediction = inception_net.predict(inp).flatten()
+ return {labels[i]: float(prediction[i]) for i in range(1000)}
+
+
+image = gr.Image(shape=(224, 224))
+label = gr.Label(num_top_classes=3)
+
+demo = gr.Interface(
+ fn=classify_image,
+ inputs=image,
+ outputs=label,
+ examples=[
+ os.path.join(os.path.dirname(__file__), "images/cheetah1.jpg"),
+ os.path.join(os.path.dirname(__file__), "images/lion.jpg")
+ ]
+ )
+
+if __name__ == "__main__":
+ demo.launch()
+
diff --git a/demo/image_classifier/screenshot.gif b/demo/image_classifier/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8f4a3a2e5199d41c1a50c6cae37449c26eaf42af
Binary files /dev/null and b/demo/image_classifier/screenshot.gif differ
diff --git a/demo/image_classifier/screenshot.png b/demo/image_classifier/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..306825e94e4600903c92d64855bb88373440ada5
Binary files /dev/null and b/demo/image_classifier/screenshot.png differ
diff --git a/demo/image_classifier_2/files/imagenet_labels.json b/demo/image_classifier_2/files/imagenet_labels.json
new file mode 100644
index 0000000000000000000000000000000000000000..fa059ceeab5d18ab9882df2983b92e8270373e39
--- /dev/null
+++ b/demo/image_classifier_2/files/imagenet_labels.json
@@ -0,0 +1,1000 @@
+["tench",
+ "goldfish",
+ "great white shark",
+ "tiger shark",
+ "hammerhead shark",
+ "electric ray",
+ "stingray",
+ "cock",
+ "hen",
+ "ostrich",
+ "brambling",
+ "goldfinch",
+ "house finch",
+ "junco",
+ "indigo bunting",
+ "American robin",
+ "bulbul",
+ "jay",
+ "magpie",
+ "chickadee",
+ "American dipper",
+ "kite",
+ "bald eagle",
+ "vulture",
+ "great grey owl",
+ "fire salamander",
+ "smooth newt",
+ "newt",
+ "spotted salamander",
+ "axolotl",
+ "American bullfrog",
+ "tree frog",
+ "tailed frog",
+ "loggerhead sea turtle",
+ "leatherback sea turtle",
+ "mud turtle",
+ "terrapin",
+ "box turtle",
+ "banded gecko",
+ "green iguana",
+ "Carolina anole",
+ "desert grassland whiptail lizard",
+ "agama",
+ "frilled-necked lizard",
+ "alligator lizard",
+ "Gila monster",
+ "European green lizard",
+ "chameleon",
+ "Komodo dragon",
+ "Nile crocodile",
+ "American alligator",
+ "triceratops",
+ "worm snake",
+ "ring-necked snake",
+ "eastern hog-nosed snake",
+ "smooth green snake",
+ "kingsnake",
+ "garter snake",
+ "water snake",
+ "vine snake",
+ "night snake",
+ "boa constrictor",
+ "African rock python",
+ "Indian cobra",
+ "green mamba",
+ "sea snake",
+ "Saharan horned viper",
+ "eastern diamondback rattlesnake",
+ "sidewinder",
+ "trilobite",
+ "harvestman",
+ "scorpion",
+ "yellow garden spider",
+ "barn spider",
+ "European garden spider",
+ "southern black widow",
+ "tarantula",
+ "wolf spider",
+ "tick",
+ "centipede",
+ "black grouse",
+ "ptarmigan",
+ "ruffed grouse",
+ "prairie grouse",
+ "peacock",
+ "quail",
+ "partridge",
+ "grey parrot",
+ "macaw",
+ "sulphur-crested cockatoo",
+ "lorikeet",
+ "coucal",
+ "bee eater",
+ "hornbill",
+ "hummingbird",
+ "jacamar",
+ "toucan",
+ "duck",
+ "red-breasted merganser",
+ "goose",
+ "black swan",
+ "tusker",
+ "echidna",
+ "platypus",
+ "wallaby",
+ "koala",
+ "wombat",
+ "jellyfish",
+ "sea anemone",
+ "brain coral",
+ "flatworm",
+ "nematode",
+ "conch",
+ "snail",
+ "slug",
+ "sea slug",
+ "chiton",
+ "chambered nautilus",
+ "Dungeness crab",
+ "rock crab",
+ "fiddler crab",
+ "red king crab",
+ "American lobster",
+ "spiny lobster",
+ "crayfish",
+ "hermit crab",
+ "isopod",
+ "white stork",
+ "black stork",
+ "spoonbill",
+ "flamingo",
+ "little blue heron",
+ "great egret",
+ "bittern",
+ "crane (bird)",
+ "limpkin",
+ "common gallinule",
+ "American coot",
+ "bustard",
+ "ruddy turnstone",
+ "dunlin",
+ "common redshank",
+ "dowitcher",
+ "oystercatcher",
+ "pelican",
+ "king penguin",
+ "albatross",
+ "grey whale",
+ "killer whale",
+ "dugong",
+ "sea lion",
+ "Chihuahua",
+ "Japanese Chin",
+ "Maltese",
+ "Pekingese",
+ "Shih Tzu",
+ "King Charles Spaniel",
+ "Papillon",
+ "toy terrier",
+ "Rhodesian Ridgeback",
+ "Afghan Hound",
+ "Basset Hound",
+ "Beagle",
+ "Bloodhound",
+ "Bluetick Coonhound",
+ "Black and Tan Coonhound",
+ "Treeing Walker Coonhound",
+ "English foxhound",
+ "Redbone Coonhound",
+ "borzoi",
+ "Irish Wolfhound",
+ "Italian Greyhound",
+ "Whippet",
+ "Ibizan Hound",
+ "Norwegian Elkhound",
+ "Otterhound",
+ "Saluki",
+ "Scottish Deerhound",
+ "Weimaraner",
+ "Staffordshire Bull Terrier",
+ "American Staffordshire Terrier",
+ "Bedlington Terrier",
+ "Border Terrier",
+ "Kerry Blue Terrier",
+ "Irish Terrier",
+ "Norfolk Terrier",
+ "Norwich Terrier",
+ "Yorkshire Terrier",
+ "Wire Fox Terrier",
+ "Lakeland Terrier",
+ "Sealyham Terrier",
+ "Airedale Terrier",
+ "Cairn Terrier",
+ "Australian Terrier",
+ "Dandie Dinmont Terrier",
+ "Boston Terrier",
+ "Miniature Schnauzer",
+ "Giant Schnauzer",
+ "Standard Schnauzer",
+ "Scottish Terrier",
+ "Tibetan Terrier",
+ "Australian Silky Terrier",
+ "Soft-coated Wheaten Terrier",
+ "West Highland White Terrier",
+ "Lhasa Apso",
+ "Flat-Coated Retriever",
+ "Curly-coated Retriever",
+ "Golden Retriever",
+ "Labrador Retriever",
+ "Chesapeake Bay Retriever",
+ "German Shorthaired Pointer",
+ "Vizsla",
+ "English Setter",
+ "Irish Setter",
+ "Gordon Setter",
+ "Brittany",
+ "Clumber Spaniel",
+ "English Springer Spaniel",
+ "Welsh Springer Spaniel",
+ "Cocker Spaniels",
+ "Sussex Spaniel",
+ "Irish Water Spaniel",
+ "Kuvasz",
+ "Schipperke",
+ "Groenendael",
+ "Malinois",
+ "Briard",
+ "Australian Kelpie",
+ "Komondor",
+ "Old English Sheepdog",
+ "Shetland Sheepdog",
+ "collie",
+ "Border Collie",
+ "Bouvier des Flandres",
+ "Rottweiler",
+ "German Shepherd Dog",
+ "Dobermann",
+ "Miniature Pinscher",
+ "Greater Swiss Mountain Dog",
+ "Bernese Mountain Dog",
+ "Appenzeller Sennenhund",
+ "Entlebucher Sennenhund",
+ "Boxer",
+ "Bullmastiff",
+ "Tibetan Mastiff",
+ "French Bulldog",
+ "Great Dane",
+ "St. Bernard",
+ "husky",
+ "Alaskan Malamute",
+ "Siberian Husky",
+ "Dalmatian",
+ "Affenpinscher",
+ "Basenji",
+ "pug",
+ "Leonberger",
+ "Newfoundland",
+ "Pyrenean Mountain Dog",
+ "Samoyed",
+ "Pomeranian",
+ "Chow Chow",
+ "Keeshond",
+ "Griffon Bruxellois",
+ "Pembroke Welsh Corgi",
+ "Cardigan Welsh Corgi",
+ "Toy Poodle",
+ "Miniature Poodle",
+ "Standard Poodle",
+ "Mexican hairless dog",
+ "grey wolf",
+ "Alaskan tundra wolf",
+ "red wolf",
+ "coyote",
+ "dingo",
+ "dhole",
+ "African wild dog",
+ "hyena",
+ "red fox",
+ "kit fox",
+ "Arctic fox",
+ "grey fox",
+ "tabby cat",
+ "tiger cat",
+ "Persian cat",
+ "Siamese cat",
+ "Egyptian Mau",
+ "cougar",
+ "lynx",
+ "leopard",
+ "snow leopard",
+ "jaguar",
+ "lion",
+ "tiger",
+ "cheetah",
+ "brown bear",
+ "American black bear",
+ "polar bear",
+ "sloth bear",
+ "mongoose",
+ "meerkat",
+ "tiger beetle",
+ "ladybug",
+ "ground beetle",
+ "longhorn beetle",
+ "leaf beetle",
+ "dung beetle",
+ "rhinoceros beetle",
+ "weevil",
+ "fly",
+ "bee",
+ "ant",
+ "grasshopper",
+ "cricket",
+ "stick insect",
+ "cockroach",
+ "mantis",
+ "cicada",
+ "leafhopper",
+ "lacewing",
+ "dragonfly",
+ "damselfly",
+ "red admiral",
+ "ringlet",
+ "monarch butterfly",
+ "small white",
+ "sulphur butterfly",
+ "gossamer-winged butterfly",
+ "starfish",
+ "sea urchin",
+ "sea cucumber",
+ "cottontail rabbit",
+ "hare",
+ "Angora rabbit",
+ "hamster",
+ "porcupine",
+ "fox squirrel",
+ "marmot",
+ "beaver",
+ "guinea pig",
+ "common sorrel",
+ "zebra",
+ "pig",
+ "wild boar",
+ "warthog",
+ "hippopotamus",
+ "ox",
+ "water buffalo",
+ "bison",
+ "ram",
+ "bighorn sheep",
+ "Alpine ibex",
+ "hartebeest",
+ "impala",
+ "gazelle",
+ "dromedary",
+ "llama",
+ "weasel",
+ "mink",
+ "European polecat",
+ "black-footed ferret",
+ "otter",
+ "skunk",
+ "badger",
+ "armadillo",
+ "three-toed sloth",
+ "orangutan",
+ "gorilla",
+ "chimpanzee",
+ "gibbon",
+ "siamang",
+ "guenon",
+ "patas monkey",
+ "baboon",
+ "macaque",
+ "langur",
+ "black-and-white colobus",
+ "proboscis monkey",
+ "marmoset",
+ "white-headed capuchin",
+ "howler monkey",
+ "titi",
+ "Geoffroy's spider monkey",
+ "common squirrel monkey",
+ "ring-tailed lemur",
+ "indri",
+ "Asian elephant",
+ "African bush elephant",
+ "red panda",
+ "giant panda",
+ "snoek",
+ "eel",
+ "coho salmon",
+ "rock beauty",
+ "clownfish",
+ "sturgeon",
+ "garfish",
+ "lionfish",
+ "pufferfish",
+ "abacus",
+ "abaya",
+ "academic gown",
+ "accordion",
+ "acoustic guitar",
+ "aircraft carrier",
+ "airliner",
+ "airship",
+ "altar",
+ "ambulance",
+ "amphibious vehicle",
+ "analog clock",
+ "apiary",
+ "apron",
+ "waste container",
+ "assault rifle",
+ "backpack",
+ "bakery",
+ "balance beam",
+ "balloon",
+ "ballpoint pen",
+ "Band-Aid",
+ "banjo",
+ "baluster",
+ "barbell",
+ "barber chair",
+ "barbershop",
+ "barn",
+ "barometer",
+ "barrel",
+ "wheelbarrow",
+ "baseball",
+ "basketball",
+ "bassinet",
+ "bassoon",
+ "swimming cap",
+ "bath towel",
+ "bathtub",
+ "station wagon",
+ "lighthouse",
+ "beaker",
+ "military cap",
+ "beer bottle",
+ "beer glass",
+ "bell-cot",
+ "bib",
+ "tandem bicycle",
+ "bikini",
+ "ring binder",
+ "binoculars",
+ "birdhouse",
+ "boathouse",
+ "bobsleigh",
+ "bolo tie",
+ "poke bonnet",
+ "bookcase",
+ "bookstore",
+ "bottle cap",
+ "bow",
+ "bow tie",
+ "brass",
+ "bra",
+ "breakwater",
+ "breastplate",
+ "broom",
+ "bucket",
+ "buckle",
+ "bulletproof vest",
+ "high-speed train",
+ "butcher shop",
+ "taxicab",
+ "cauldron",
+ "candle",
+ "cannon",
+ "canoe",
+ "can opener",
+ "cardigan",
+ "car mirror",
+ "carousel",
+ "tool kit",
+ "carton",
+ "car wheel",
+ "automated teller machine",
+ "cassette",
+ "cassette player",
+ "castle",
+ "catamaran",
+ "CD player",
+ "cello",
+ "mobile phone",
+ "chain",
+ "chain-link fence",
+ "chain mail",
+ "chainsaw",
+ "chest",
+ "chiffonier",
+ "chime",
+ "china cabinet",
+ "Christmas stocking",
+ "church",
+ "movie theater",
+ "cleaver",
+ "cliff dwelling",
+ "cloak",
+ "clogs",
+ "cocktail shaker",
+ "coffee mug",
+ "coffeemaker",
+ "coil",
+ "combination lock",
+ "computer keyboard",
+ "confectionery store",
+ "container ship",
+ "convertible",
+ "corkscrew",
+ "cornet",
+ "cowboy boot",
+ "cowboy hat",
+ "cradle",
+ "crane (machine)",
+ "crash helmet",
+ "crate",
+ "infant bed",
+ "Crock Pot",
+ "croquet ball",
+ "crutch",
+ "cuirass",
+ "dam",
+ "desk",
+ "desktop computer",
+ "rotary dial telephone",
+ "diaper",
+ "digital clock",
+ "digital watch",
+ "dining table",
+ "dishcloth",
+ "dishwasher",
+ "disc brake",
+ "dock",
+ "dog sled",
+ "dome",
+ "doormat",
+ "drilling rig",
+ "drum",
+ "drumstick",
+ "dumbbell",
+ "Dutch oven",
+ "electric fan",
+ "electric guitar",
+ "electric locomotive",
+ "entertainment center",
+ "envelope",
+ "espresso machine",
+ "face powder",
+ "feather boa",
+ "filing cabinet",
+ "fireboat",
+ "fire engine",
+ "fire screen sheet",
+ "flagpole",
+ "flute",
+ "folding chair",
+ "football helmet",
+ "forklift",
+ "fountain",
+ "fountain pen",
+ "four-poster bed",
+ "freight car",
+ "French horn",
+ "frying pan",
+ "fur coat",
+ "garbage truck",
+ "gas mask",
+ "gas pump",
+ "goblet",
+ "go-kart",
+ "golf ball",
+ "golf cart",
+ "gondola",
+ "gong",
+ "gown",
+ "grand piano",
+ "greenhouse",
+ "grille",
+ "grocery store",
+ "guillotine",
+ "barrette",
+ "hair spray",
+ "half-track",
+ "hammer",
+ "hamper",
+ "hair dryer",
+ "hand-held computer",
+ "handkerchief",
+ "hard disk drive",
+ "harmonica",
+ "harp",
+ "harvester",
+ "hatchet",
+ "holster",
+ "home theater",
+ "honeycomb",
+ "hook",
+ "hoop skirt",
+ "horizontal bar",
+ "horse-drawn vehicle",
+ "hourglass",
+ "iPod",
+ "clothes iron",
+ "jack-o'-lantern",
+ "jeans",
+ "jeep",
+ "T-shirt",
+ "jigsaw puzzle",
+ "pulled rickshaw",
+ "joystick",
+ "kimono",
+ "knee pad",
+ "knot",
+ "lab coat",
+ "ladle",
+ "lampshade",
+ "laptop computer",
+ "lawn mower",
+ "lens cap",
+ "paper knife",
+ "library",
+ "lifeboat",
+ "lighter",
+ "limousine",
+ "ocean liner",
+ "lipstick",
+ "slip-on shoe",
+ "lotion",
+ "speaker",
+ "loupe",
+ "sawmill",
+ "magnetic compass",
+ "mail bag",
+ "mailbox",
+ "tights",
+ "tank suit",
+ "manhole cover",
+ "maraca",
+ "marimba",
+ "mask",
+ "match",
+ "maypole",
+ "maze",
+ "measuring cup",
+ "medicine chest",
+ "megalith",
+ "microphone",
+ "microwave oven",
+ "military uniform",
+ "milk can",
+ "minibus",
+ "miniskirt",
+ "minivan",
+ "missile",
+ "mitten",
+ "mixing bowl",
+ "mobile home",
+ "Model T",
+ "modem",
+ "monastery",
+ "monitor",
+ "moped",
+ "mortar",
+ "square academic cap",
+ "mosque",
+ "mosquito net",
+ "scooter",
+ "mountain bike",
+ "tent",
+ "computer mouse",
+ "mousetrap",
+ "moving van",
+ "muzzle",
+ "nail",
+ "neck brace",
+ "necklace",
+ "nipple",
+ "notebook computer",
+ "obelisk",
+ "oboe",
+ "ocarina",
+ "odometer",
+ "oil filter",
+ "organ",
+ "oscilloscope",
+ "overskirt",
+ "bullock cart",
+ "oxygen mask",
+ "packet",
+ "paddle",
+ "paddle wheel",
+ "padlock",
+ "paintbrush",
+ "pajamas",
+ "palace",
+ "pan flute",
+ "paper towel",
+ "parachute",
+ "parallel bars",
+ "park bench",
+ "parking meter",
+ "passenger car",
+ "patio",
+ "payphone",
+ "pedestal",
+ "pencil case",
+ "pencil sharpener",
+ "perfume",
+ "Petri dish",
+ "photocopier",
+ "plectrum",
+ "Pickelhaube",
+ "picket fence",
+ "pickup truck",
+ "pier",
+ "piggy bank",
+ "pill bottle",
+ "pillow",
+ "ping-pong ball",
+ "pinwheel",
+ "pirate ship",
+ "pitcher",
+ "hand plane",
+ "planetarium",
+ "plastic bag",
+ "plate rack",
+ "plow",
+ "plunger",
+ "Polaroid camera",
+ "pole",
+ "police van",
+ "poncho",
+ "billiard table",
+ "soda bottle",
+ "pot",
+ "potter's wheel",
+ "power drill",
+ "prayer rug",
+ "printer",
+ "prison",
+ "projectile",
+ "projector",
+ "hockey puck",
+ "punching bag",
+ "purse",
+ "quill",
+ "quilt",
+ "race car",
+ "racket",
+ "radiator",
+ "radio",
+ "radio telescope",
+ "rain barrel",
+ "recreational vehicle",
+ "reel",
+ "reflex camera",
+ "refrigerator",
+ "remote control",
+ "restaurant",
+ "revolver",
+ "rifle",
+ "rocking chair",
+ "rotisserie",
+ "eraser",
+ "rugby ball",
+ "ruler",
+ "running shoe",
+ "safe",
+ "safety pin",
+ "salt shaker",
+ "sandal",
+ "sarong",
+ "saxophone",
+ "scabbard",
+ "weighing scale",
+ "school bus",
+ "schooner",
+ "scoreboard",
+ "CRT screen",
+ "screw",
+ "screwdriver",
+ "seat belt",
+ "sewing machine",
+ "shield",
+ "shoe store",
+ "shoji",
+ "shopping basket",
+ "shopping cart",
+ "shovel",
+ "shower cap",
+ "shower curtain",
+ "ski",
+ "ski mask",
+ "sleeping bag",
+ "slide rule",
+ "sliding door",
+ "slot machine",
+ "snorkel",
+ "snowmobile",
+ "snowplow",
+ "soap dispenser",
+ "soccer ball",
+ "sock",
+ "solar thermal collector",
+ "sombrero",
+ "soup bowl",
+ "space bar",
+ "space heater",
+ "space shuttle",
+ "spatula",
+ "motorboat",
+ "spider web",
+ "spindle",
+ "sports car",
+ "spotlight",
+ "stage",
+ "steam locomotive",
+ "through arch bridge",
+ "steel drum",
+ "stethoscope",
+ "scarf",
+ "stone wall",
+ "stopwatch",
+ "stove",
+ "strainer",
+ "tram",
+ "stretcher",
+ "couch",
+ "stupa",
+ "submarine",
+ "suit",
+ "sundial",
+ "sunglass",
+ "sunglasses",
+ "sunscreen",
+ "suspension bridge",
+ "mop",
+ "sweatshirt",
+ "swimsuit",
+ "swing",
+ "switch",
+ "syringe",
+ "table lamp",
+ "tank",
+ "tape player",
+ "teapot",
+ "teddy bear",
+ "television",
+ "tennis ball",
+ "thatched roof",
+ "front curtain",
+ "thimble",
+ "threshing machine",
+ "throne",
+ "tile roof",
+ "toaster",
+ "tobacco shop",
+ "toilet seat",
+ "torch",
+ "totem pole",
+ "tow truck",
+ "toy store",
+ "tractor",
+ "semi-trailer truck",
+ "tray",
+ "trench coat",
+ "tricycle",
+ "trimaran",
+ "tripod",
+ "triumphal arch",
+ "trolleybus",
+ "trombone",
+ "tub",
+ "turnstile",
+ "typewriter keyboard",
+ "umbrella",
+ "unicycle",
+ "upright piano",
+ "vacuum cleaner",
+ "vase",
+ "vault",
+ "velvet",
+ "vending machine",
+ "vestment",
+ "viaduct",
+ "violin",
+ "volleyball",
+ "waffle iron",
+ "wall clock",
+ "wallet",
+ "wardrobe",
+ "military aircraft",
+ "sink",
+ "washing machine",
+ "water bottle",
+ "water jug",
+ "water tower",
+ "whiskey jug",
+ "whistle",
+ "wig",
+ "window screen",
+ "window shade",
+ "Windsor tie",
+ "wine bottle",
+ "wing",
+ "wok",
+ "wooden spoon",
+ "wool",
+ "split-rail fence",
+ "shipwreck",
+ "yawl",
+ "yurt",
+ "website",
+ "comic book",
+ "crossword",
+ "traffic sign",
+ "traffic light",
+ "dust jacket",
+ "menu",
+ "plate",
+ "guacamole",
+ "consomme",
+ "hot pot",
+ "trifle",
+ "ice cream",
+ "ice pop",
+ "baguette",
+ "bagel",
+ "pretzel",
+ "cheeseburger",
+ "hot dog",
+ "mashed potato",
+ "cabbage",
+ "broccoli",
+ "cauliflower",
+ "zucchini",
+ "spaghetti squash",
+ "acorn squash",
+ "butternut squash",
+ "cucumber",
+ "artichoke",
+ "bell pepper",
+ "cardoon",
+ "mushroom",
+ "Granny Smith",
+ "strawberry",
+ "orange",
+ "lemon",
+ "fig",
+ "pineapple",
+ "banana",
+ "jackfruit",
+ "custard apple",
+ "pomegranate",
+ "hay",
+ "carbonara",
+ "chocolate syrup",
+ "dough",
+ "meatloaf",
+ "pizza",
+ "pot pie",
+ "burrito",
+ "red wine",
+ "espresso",
+ "cup",
+ "eggnog",
+ "alp",
+ "bubble",
+ "cliff",
+ "coral reef",
+ "geyser",
+ "lakeshore",
+ "promontory",
+ "shoal",
+ "seashore",
+ "valley",
+ "volcano",
+ "baseball player",
+ "bridegroom",
+ "scuba diver",
+ "rapeseed",
+ "daisy",
+ "yellow lady's slipper",
+ "corn",
+ "acorn",
+ "rose hip",
+ "horse chestnut seed",
+ "coral fungus",
+ "agaric",
+ "gyromitra",
+ "stinkhorn mushroom",
+ "earth star",
+ "hen-of-the-woods",
+ "bolete",
+ "ear",
+ "toilet paper"]
\ No newline at end of file
diff --git a/demo/image_classifier_2/requirements.txt b/demo/image_classifier_2/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2ab187b1e35179bc3f56ab7cdd30df60b7b95a54
--- /dev/null
+++ b/demo/image_classifier_2/requirements.txt
@@ -0,0 +1,3 @@
+pillow
+torch
+torchvision
\ No newline at end of file
diff --git a/demo/image_classifier_2/run.ipynb b/demo/image_classifier_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..907f57b3b75a71ee92b4ac9dd3e001c9ffad95d9
--- /dev/null
+++ b/demo/image_classifier_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_classifier_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pillow torch torchvision"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/imagenet_labels.json https://github.com/gradio-app/gradio/raw/main/demo/image_classifier_2/files/imagenet_labels.json"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import requests\n", "import torch\n", "from PIL import Image\n", "from torchvision import transforms\n", "\n", "import gradio as gr\n", "\n", "model = torch.hub.load(\"pytorch/vision:v0.6.0\", \"resnet18\", pretrained=True).eval()\n", "\n", "# Download human-readable labels for ImageNet.\n", "response = requests.get(\"https://git.io/JJkYN\")\n", "labels = response.text.split(\"\\n\")\n", "\n", "\n", "def predict(inp):\n", " inp = Image.fromarray(inp.astype(\"uint8\"), \"RGB\")\n", " inp = transforms.ToTensor()(inp).unsqueeze(0)\n", " with torch.no_grad():\n", " prediction = torch.nn.functional.softmax(model(inp)[0], dim=0)\n", " return {labels[i]: float(prediction[i]) for i in range(1000)}\n", "\n", "\n", "inputs = gr.Image()\n", "outputs = gr.Label(num_top_classes=3)\n", "\n", "demo = gr.Interface(fn=predict, inputs=inputs, outputs=outputs)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_classifier_2/run.py b/demo/image_classifier_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d378b8fe44af4d8f1d875db8399e61e928c2eaa9
--- /dev/null
+++ b/demo/image_classifier_2/run.py
@@ -0,0 +1,29 @@
+import requests
+import torch
+from PIL import Image
+from torchvision import transforms
+
+import gradio as gr
+
+model = torch.hub.load("pytorch/vision:v0.6.0", "resnet18", pretrained=True).eval()
+
+# Download human-readable labels for ImageNet.
+response = requests.get("https://git.io/JJkYN")
+labels = response.text.split("\n")
+
+
+def predict(inp):
+ inp = Image.fromarray(inp.astype("uint8"), "RGB")
+ inp = transforms.ToTensor()(inp).unsqueeze(0)
+ with torch.no_grad():
+ prediction = torch.nn.functional.softmax(model(inp)[0], dim=0)
+ return {labels[i]: float(prediction[i]) for i in range(1000)}
+
+
+inputs = gr.Image()
+outputs = gr.Label(num_top_classes=3)
+
+demo = gr.Interface(fn=predict, inputs=inputs, outputs=outputs)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_classifier_interface_load/cheetah1.jpeg b/demo/image_classifier_interface_load/cheetah1.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/image_classifier_interface_load/cheetah1.jpeg differ
diff --git a/demo/image_classifier_interface_load/cheetah1.jpg b/demo/image_classifier_interface_load/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/image_classifier_interface_load/cheetah1.jpg differ
diff --git a/demo/image_classifier_interface_load/lion.jpg b/demo/image_classifier_interface_load/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/image_classifier_interface_load/lion.jpg differ
diff --git a/demo/image_classifier_interface_load/run.ipynb b/demo/image_classifier_interface_load/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d2aa59dacc2289b0acdfd52a4452584d0908102b
--- /dev/null
+++ b/demo/image_classifier_interface_load/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_classifier_interface_load"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image_classifier_interface_load/cheetah1.jpeg\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image_classifier_interface_load/cheetah1.jpg\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image_classifier_interface_load/lion.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pathlib\n", "\n", "current_dir = pathlib.Path(__file__).parent\n", "\n", "images = [str(current_dir / \"cheetah1.jpeg\"), str(current_dir / \"cheetah1.jpg\"), str(current_dir / \"lion.jpg\")]\n", "\n", "\n", "img_classifier = gr.load(\n", " \"models/google/vit-base-patch16-224\", examples=images, cache_examples=False\n", ")\n", "\n", "\n", "def func(img, text):\n", " return img_classifier(img), text\n", "\n", "\n", "using_img_classifier_as_function = gr.Interface(\n", " func,\n", " [gr.Image(type=\"filepath\"), \"text\"],\n", " [\"label\", \"text\"],\n", " examples=[\n", " [str(current_dir / \"cheetah1.jpeg\"), None],\n", " [str(current_dir / \"cheetah1.jpg\"), \"cheetah\"],\n", " [str(current_dir / \"lion.jpg\"), \"lion\"],\n", " ],\n", " cache_examples=False,\n", ")\n", "demo = gr.TabbedInterface([using_img_classifier_as_function, img_classifier])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_classifier_interface_load/run.py b/demo/image_classifier_interface_load/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..86d8dc8bc8def369abc8cba6b97d4b1f18b17f74
--- /dev/null
+++ b/demo/image_classifier_interface_load/run.py
@@ -0,0 +1,32 @@
+import gradio as gr
+import pathlib
+
+current_dir = pathlib.Path(__file__).parent
+
+images = [str(current_dir / "cheetah1.jpeg"), str(current_dir / "cheetah1.jpg"), str(current_dir / "lion.jpg")]
+
+
+img_classifier = gr.load(
+ "models/google/vit-base-patch16-224", examples=images, cache_examples=False
+)
+
+
+def func(img, text):
+ return img_classifier(img), text
+
+
+using_img_classifier_as_function = gr.Interface(
+ func,
+ [gr.Image(type="filepath"), "text"],
+ ["label", "text"],
+ examples=[
+ [str(current_dir / "cheetah1.jpeg"), None],
+ [str(current_dir / "cheetah1.jpg"), "cheetah"],
+ [str(current_dir / "lion.jpg"), "lion"],
+ ],
+ cache_examples=False,
+)
+demo = gr.TabbedInterface([using_img_classifier_as_function, img_classifier])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/image_component/run.ipynb b/demo/image_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ef0fbc57f94dd470cd333eb0f644299aa0c1dc70
--- /dev/null
+++ b/demo/image_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Image()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_component/run.py b/demo/image_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e18292d68e2e3a8fee4035ce7539c14bc13f61f7
--- /dev/null
+++ b/demo/image_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Image()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/image_component_events/run.ipynb b/demo/image_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..2503558f731c89a50e7d477eabe22cc6b860d332
--- /dev/null
+++ b/demo/image_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def test_select_is_defined(n, evt: gr.SelectData):\n", " assert isinstance(evt.index, list)\n", " assert isinstance(evt.index[0], int)\n", " return n + 1\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_img = gr.Image(type=\"filepath\", label=\"Input Image\", sources=[\"upload\", \"clipboard\"])\n", " with gr.Column():\n", " output_img = gr.Image(type=\"filepath\", label=\"Output Image\", sources=[\"upload\", \"clipboard\"])\n", " with gr.Column():\n", " num_change = gr.Number(label=\"# Change Events\", value=0)\n", " num_load = gr.Number(label=\"# Upload Events\", value=0)\n", " num_change_o = gr.Number(label=\"# Change Events Output\", value=0)\n", " num_clear = gr.Number(label=\"# Clear Events\", value=0)\n", " num_select = gr.Number(label=\"# Select Events\", value=0)\n", " input_img.upload(lambda s, n: (s, n + 1), [input_img, num_load], [output_img, num_load])\n", " input_img.change(lambda n: n + 1, num_change, num_change)\n", " input_img.clear(lambda n: n + 1, num_clear, num_clear)\n", " output_img.change(lambda n: n + 1, num_change_o, num_change_o)\n", " output_img.select(test_select_is_defined, num_select, num_select)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_component_events/run.py b/demo/image_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5376b7e016837fa596246f0c9d758cb3a739c82
--- /dev/null
+++ b/demo/image_component_events/run.py
@@ -0,0 +1,28 @@
+import gradio as gr
+
+def test_select_is_defined(n, evt: gr.SelectData):
+ assert isinstance(evt.index, list)
+ assert isinstance(evt.index[0], int)
+ return n + 1
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ input_img = gr.Image(type="filepath", label="Input Image", sources=["upload", "clipboard"])
+ with gr.Column():
+ output_img = gr.Image(type="filepath", label="Output Image", sources=["upload", "clipboard"])
+ with gr.Column():
+ num_change = gr.Number(label="# Change Events", value=0)
+ num_load = gr.Number(label="# Upload Events", value=0)
+ num_change_o = gr.Number(label="# Change Events Output", value=0)
+ num_clear = gr.Number(label="# Clear Events", value=0)
+ num_select = gr.Number(label="# Select Events", value=0)
+ input_img.upload(lambda s, n: (s, n + 1), [input_img, num_load], [output_img, num_load])
+ input_img.change(lambda n: n + 1, num_change, num_change)
+ input_img.clear(lambda n: n + 1, num_clear, num_clear)
+ output_img.change(lambda n: n + 1, num_change_o, num_change_o)
+ output_img.select(test_select_is_defined, num_select, num_select)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/image_editor/cheetah.jpg b/demo/image_editor/cheetah.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d1fde62d026aeb594fd6c989bc893da13e68b9dc
Binary files /dev/null and b/demo/image_editor/cheetah.jpg differ
diff --git a/demo/image_editor/run.ipynb b/demo/image_editor/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..de3e91092ec93000c90deecc34f6831624c4deb2
--- /dev/null
+++ b/demo/image_editor/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_editor"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/image_editor/cheetah.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "\n", "def sleep(im):\n", " time.sleep(5)\n", " return [im[\"background\"], im[\"layers\"][0], im[\"layers\"][1], im[\"composite\"]]\n", "\n", "\n", "with gr.Blocks() as demo:\n", " im = gr.ImageEditor(\n", " type=\"pil\",\n", " crop_size=\"1:1\",\n", " )\n", "\n", " with gr.Group():\n", " with gr.Row():\n", " im_out_1 = gr.Image(type=\"pil\")\n", " im_out_2 = gr.Image(type=\"pil\")\n", " im_out_3 = gr.Image(type=\"pil\")\n", " im_out_4 = gr.Image(type=\"pil\")\n", "\n", " btn = gr.Button()\n", " im.change(sleep, outputs=[im_out_1, im_out_2, im_out_3, im_out_4], inputs=im)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_editor/run.py b/demo/image_editor/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..365c9056f532fdcda773d60a312dc03971febbf1
--- /dev/null
+++ b/demo/image_editor/run.py
@@ -0,0 +1,27 @@
+import gradio as gr
+import time
+
+
+def sleep(im):
+ time.sleep(5)
+ return [im["background"], im["layers"][0], im["layers"][1], im["composite"]]
+
+
+with gr.Blocks() as demo:
+ im = gr.ImageEditor(
+ type="pil",
+ crop_size="1:1",
+ )
+
+ with gr.Group():
+ with gr.Row():
+ im_out_1 = gr.Image(type="pil")
+ im_out_2 = gr.Image(type="pil")
+ im_out_3 = gr.Image(type="pil")
+ im_out_4 = gr.Image(type="pil")
+
+ btn = gr.Button()
+ im.change(sleep, outputs=[im_out_1, im_out_2, im_out_3, im_out_4], inputs=im)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_mod/images/cheetah1.jpg b/demo/image_mod/images/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/image_mod/images/cheetah1.jpg differ
diff --git a/demo/image_mod/images/lion.jpg b/demo/image_mod/images/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/image_mod/images/lion.jpg differ
diff --git a/demo/image_mod/images/logo.png b/demo/image_mod/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f1df7156f0a690a2415903061e19c20e24adac4
Binary files /dev/null and b/demo/image_mod/images/logo.png differ
diff --git a/demo/image_mod/images/tower.jpg b/demo/image_mod/images/tower.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..aec3fa94eedf13f6e0c4ef56e4f669a3dba59fd8
Binary files /dev/null and b/demo/image_mod/images/tower.jpg differ
diff --git a/demo/image_mod/run.ipynb b/demo/image_mod/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b7b80afe2b6002f17caec5f92df12d8a633678bb
--- /dev/null
+++ b/demo/image_mod/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_mod"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('images')\n", "!wget -q -O images/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_mod/images/cheetah1.jpg\n", "!wget -q -O images/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_mod/images/lion.jpg\n", "!wget -q -O images/logo.png https://github.com/gradio-app/gradio/raw/main/demo/image_mod/images/logo.png\n", "!wget -q -O images/tower.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_mod/images/tower.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def image_mod(image):\n", " return image.rotate(45)\n", "\n", "\n", "demo = gr.Interface(\n", " image_mod,\n", " gr.Image(type=\"pil\"),\n", " \"image\",\n", " flagging_options=[\"blurry\", \"incorrect\", \"other\"],\n", " examples=[\n", " os.path.join(os.path.abspath(''), \"images/cheetah1.jpg\"),\n", " os.path.join(os.path.abspath(''), \"images/lion.jpg\"),\n", " os.path.join(os.path.abspath(''), \"images/logo.png\"),\n", " os.path.join(os.path.abspath(''), \"images/tower.jpg\"),\n", " ],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_mod/run.py b/demo/image_mod/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..88bfaf63f07f7280023bf16fa91afff65e103c2e
--- /dev/null
+++ b/demo/image_mod/run.py
@@ -0,0 +1,23 @@
+import gradio as gr
+import os
+
+
+def image_mod(image):
+ return image.rotate(45)
+
+
+demo = gr.Interface(
+ image_mod,
+ gr.Image(type="pil"),
+ "image",
+ flagging_options=["blurry", "incorrect", "other"],
+ examples=[
+ os.path.join(os.path.dirname(__file__), "images/cheetah1.jpg"),
+ os.path.join(os.path.dirname(__file__), "images/lion.jpg"),
+ os.path.join(os.path.dirname(__file__), "images/logo.png"),
+ os.path.join(os.path.dirname(__file__), "images/tower.jpg"),
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_mod/screenshot.png b/demo/image_mod/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..07939d98debb9d571a75ba02e2948cf75afeb65a
--- /dev/null
+++ b/demo/image_mod/screenshot.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f9e12c6742252fc970c3983e6691050d55034d40d1b553b93a94eb9b5c94c6e9
+size 1108299
diff --git a/demo/image_mod_default_image/images/cheetah1.jpg b/demo/image_mod_default_image/images/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/image_mod_default_image/images/cheetah1.jpg differ
diff --git a/demo/image_mod_default_image/images/lion.jpg b/demo/image_mod_default_image/images/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/image_mod_default_image/images/lion.jpg differ
diff --git a/demo/image_mod_default_image/images/logo.png b/demo/image_mod_default_image/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f1df7156f0a690a2415903061e19c20e24adac4
Binary files /dev/null and b/demo/image_mod_default_image/images/logo.png differ
diff --git a/demo/image_mod_default_image/run.ipynb b/demo/image_mod_default_image/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9e2befb5bcd57b4b97df17b25c33644eb942dab2
--- /dev/null
+++ b/demo/image_mod_default_image/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_mod_default_image"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('images')\n", "!wget -q -O images/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_mod_default_image/images/cheetah1.jpg\n", "!wget -q -O images/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/image_mod_default_image/images/lion.jpg\n", "!wget -q -O images/logo.png https://github.com/gradio-app/gradio/raw/main/demo/image_mod_default_image/images/logo.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def image_mod(image):\n", " return image.rotate(45)\n", "\n", "\n", "cheetah = os.path.join(os.path.abspath(''), \"images/cheetah1.jpg\")\n", "\n", "demo = gr.Interface(image_mod, gr.Image(type=\"pil\", value=cheetah), \"image\",\n", " flagging_options=[\"blurry\", \"incorrect\", \"other\"], examples=[\n", " os.path.join(os.path.abspath(''), \"images/lion.jpg\"),\n", " os.path.join(os.path.abspath(''), \"images/logo.png\")\n", " ])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_mod_default_image/run.py b/demo/image_mod_default_image/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c2ad1f8be43b53d179254cb9a0cadcb4c11378b3
--- /dev/null
+++ b/demo/image_mod_default_image/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+import os
+
+
+def image_mod(image):
+ return image.rotate(45)
+
+
+cheetah = os.path.join(os.path.dirname(__file__), "images/cheetah1.jpg")
+
+demo = gr.Interface(image_mod, gr.Image(type="pil", value=cheetah), "image",
+ flagging_options=["blurry", "incorrect", "other"], examples=[
+ os.path.join(os.path.dirname(__file__), "images/lion.jpg"),
+ os.path.join(os.path.dirname(__file__), "images/logo.png")
+ ])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_segmentation/DESCRIPTION.md b/demo/image_segmentation/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..dbba2ae29e4ed391bfd1681fb2fe7d0efcb34222
--- /dev/null
+++ b/demo/image_segmentation/DESCRIPTION.md
@@ -0,0 +1 @@
+Simple image segmentation using gradio's AnnotatedImage component.
\ No newline at end of file
diff --git a/demo/image_segmentation/run.ipynb b/demo/image_segmentation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ac39c2862e509bcadc97ace2367edf2a8672e98e
--- /dev/null
+++ b/demo/image_segmentation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_segmentation\n", "### Simple image segmentation using gradio's AnnotatedImage component.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import random\n", "\n", "with gr.Blocks() as demo:\n", " section_labels = [\n", " \"apple\",\n", " \"banana\",\n", " \"carrot\",\n", " \"donut\",\n", " \"eggplant\",\n", " \"fish\",\n", " \"grapes\",\n", " \"hamburger\",\n", " \"ice cream\",\n", " \"juice\",\n", " ]\n", "\n", " with gr.Row():\n", " num_boxes = gr.Slider(0, 5, 2, step=1, label=\"Number of boxes\")\n", " num_segments = gr.Slider(0, 5, 1, step=1, label=\"Number of segments\")\n", "\n", " with gr.Row():\n", " img_input = gr.Image()\n", " img_output = gr.AnnotatedImage(\n", " color_map={\"banana\": \"#a89a00\", \"carrot\": \"#ffae00\"}\n", " )\n", "\n", " section_btn = gr.Button(\"Identify Sections\")\n", " selected_section = gr.Textbox(label=\"Selected Section\")\n", "\n", " def section(img, num_boxes, num_segments):\n", " sections = []\n", " for a in range(num_boxes):\n", " x = random.randint(0, img.shape[1])\n", " y = random.randint(0, img.shape[0])\n", " w = random.randint(0, img.shape[1] - x)\n", " h = random.randint(0, img.shape[0] - y)\n", " sections.append(((x, y, x + w, y + h), section_labels[a]))\n", " for b in range(num_segments):\n", " x = random.randint(0, img.shape[1])\n", " y = random.randint(0, img.shape[0])\n", " r = random.randint(0, min(x, y, img.shape[1] - x, img.shape[0] - y))\n", " mask = np.zeros(img.shape[:2])\n", " for i in range(img.shape[0]):\n", " for j in range(img.shape[1]):\n", " dist_square = (i - y) ** 2 + (j - x) ** 2\n", " if dist_square < r**2:\n", " mask[i, j] = round((r**2 - dist_square) / r**2 * 4) / 4\n", " sections.append((mask, section_labels[b + num_boxes]))\n", " return (img, sections)\n", "\n", " section_btn.click(section, [img_input, num_boxes, num_segments], img_output)\n", "\n", " def select_section(evt: gr.SelectData):\n", " return section_labels[evt.index]\n", "\n", " img_output.select(select_section, None, selected_section)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_segmentation/run.py b/demo/image_segmentation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..af3793f3217683102683eeb9a559bdff92a57066
--- /dev/null
+++ b/demo/image_segmentation/run.py
@@ -0,0 +1,61 @@
+import gradio as gr
+import numpy as np
+import random
+
+with gr.Blocks() as demo:
+ section_labels = [
+ "apple",
+ "banana",
+ "carrot",
+ "donut",
+ "eggplant",
+ "fish",
+ "grapes",
+ "hamburger",
+ "ice cream",
+ "juice",
+ ]
+
+ with gr.Row():
+ num_boxes = gr.Slider(0, 5, 2, step=1, label="Number of boxes")
+ num_segments = gr.Slider(0, 5, 1, step=1, label="Number of segments")
+
+ with gr.Row():
+ img_input = gr.Image()
+ img_output = gr.AnnotatedImage(
+ color_map={"banana": "#a89a00", "carrot": "#ffae00"}
+ )
+
+ section_btn = gr.Button("Identify Sections")
+ selected_section = gr.Textbox(label="Selected Section")
+
+ def section(img, num_boxes, num_segments):
+ sections = []
+ for a in range(num_boxes):
+ x = random.randint(0, img.shape[1])
+ y = random.randint(0, img.shape[0])
+ w = random.randint(0, img.shape[1] - x)
+ h = random.randint(0, img.shape[0] - y)
+ sections.append(((x, y, x + w, y + h), section_labels[a]))
+ for b in range(num_segments):
+ x = random.randint(0, img.shape[1])
+ y = random.randint(0, img.shape[0])
+ r = random.randint(0, min(x, y, img.shape[1] - x, img.shape[0] - y))
+ mask = np.zeros(img.shape[:2])
+ for i in range(img.shape[0]):
+ for j in range(img.shape[1]):
+ dist_square = (i - y) ** 2 + (j - x) ** 2
+ if dist_square < r**2:
+ mask[i, j] = round((r**2 - dist_square) / r**2 * 4) / 4
+ sections.append((mask, section_labels[b + num_boxes]))
+ return (img, sections)
+
+ section_btn.click(section, [img_input, num_boxes, num_segments], img_output)
+
+ def select_section(evt: gr.SelectData):
+ return section_labels[evt.index]
+
+ img_output.select(select_section, None, selected_section)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/image_selections/run.ipynb b/demo/image_selections/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d39daa8b59bdd9c64cdf2546e01f790cabbf0299
--- /dev/null
+++ b/demo/image_selections/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: image_selections"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "\n", "with gr.Blocks() as demo:\n", " tolerance = gr.Slider(label=\"Tolerance\", info=\"How different colors can be in a segment.\", minimum=0, maximum=256*3, value=50)\n", " with gr.Row():\n", " input_img = gr.Image(label=\"Input\")\n", " output_img = gr.Image(label=\"Selected Segment\")\n", "\n", " def get_select_coords(img, tolerance, evt: gr.SelectData):\n", " visited_pixels = set()\n", " pixels_in_queue = set()\n", " pixels_in_segment = set()\n", " start_pixel = img[evt.index[1], evt.index[0]]\n", " pixels_in_queue.add((evt.index[1], evt.index[0]))\n", " while len(pixels_in_queue) > 0:\n", " pixel = pixels_in_queue.pop()\n", " visited_pixels.add(pixel)\n", " neighbors = []\n", " if pixel[0] > 0:\n", " neighbors.append((pixel[0] - 1, pixel[1]))\n", " if pixel[0] < img.shape[0] - 1:\n", " neighbors.append((pixel[0] + 1, pixel[1]))\n", " if pixel[1] > 0:\n", " neighbors.append((pixel[0], pixel[1] - 1))\n", " if pixel[1] < img.shape[1] - 1:\n", " neighbors.append((pixel[0], pixel[1] + 1))\n", " for neighbor in neighbors:\n", " if neighbor in visited_pixels:\n", " continue\n", " neighbor_pixel = img[neighbor[0], neighbor[1]]\n", " if np.abs(neighbor_pixel - start_pixel).sum() < tolerance:\n", " pixels_in_queue.add(neighbor)\n", " pixels_in_segment.add(neighbor)\n", "\n", " out = img.copy() * 0.2\n", " out = out.astype(np.uint8)\n", " for pixel in pixels_in_segment:\n", " out[pixel[0], pixel[1]] = img[pixel[0], pixel[1]]\n", " return out\n", " \n", " input_img.select(get_select_coords, [input_img, tolerance], output_img)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/image_selections/run.py b/demo/image_selections/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa9a8f72092140f0abdd3522ecc5f3e30ce154f2
--- /dev/null
+++ b/demo/image_selections/run.py
@@ -0,0 +1,45 @@
+import gradio as gr
+import numpy as np
+
+with gr.Blocks() as demo:
+ tolerance = gr.Slider(label="Tolerance", info="How different colors can be in a segment.", minimum=0, maximum=256*3, value=50)
+ with gr.Row():
+ input_img = gr.Image(label="Input")
+ output_img = gr.Image(label="Selected Segment")
+
+ def get_select_coords(img, tolerance, evt: gr.SelectData):
+ visited_pixels = set()
+ pixels_in_queue = set()
+ pixels_in_segment = set()
+ start_pixel = img[evt.index[1], evt.index[0]]
+ pixels_in_queue.add((evt.index[1], evt.index[0]))
+ while len(pixels_in_queue) > 0:
+ pixel = pixels_in_queue.pop()
+ visited_pixels.add(pixel)
+ neighbors = []
+ if pixel[0] > 0:
+ neighbors.append((pixel[0] - 1, pixel[1]))
+ if pixel[0] < img.shape[0] - 1:
+ neighbors.append((pixel[0] + 1, pixel[1]))
+ if pixel[1] > 0:
+ neighbors.append((pixel[0], pixel[1] - 1))
+ if pixel[1] < img.shape[1] - 1:
+ neighbors.append((pixel[0], pixel[1] + 1))
+ for neighbor in neighbors:
+ if neighbor in visited_pixels:
+ continue
+ neighbor_pixel = img[neighbor[0], neighbor[1]]
+ if np.abs(neighbor_pixel - start_pixel).sum() < tolerance:
+ pixels_in_queue.add(neighbor)
+ pixels_in_segment.add(neighbor)
+
+ out = img.copy() * 0.2
+ out = out.astype(np.uint8)
+ for pixel in pixels_in_segment:
+ out[pixel[0], pixel[1]] = img[pixel[0], pixel[1]]
+ return out
+
+ input_img.select(get_select_coords, [input_img, tolerance], output_img)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/imageeditor_component/run.ipynb b/demo/imageeditor_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..531bee33d3162bcfa88ae4b16ed6231b804e4e6f
--- /dev/null
+++ b/demo/imageeditor_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: imageeditor_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.ImageEditor()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/imageeditor_component/run.py b/demo/imageeditor_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..03276def23187a6c0af0405dde10bca4f893bc72
--- /dev/null
+++ b/demo/imageeditor_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.ImageEditor()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/input_output/run.ipynb b/demo/input_output/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c59f54523bbc0cf22363bc2515a6f01cd98bb0e5
--- /dev/null
+++ b/demo/input_output/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: input_output"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def image_mod(text):\n", " return text[::-1]\n", "\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " text = gr.Textbox(label=\"Input-Output\")\n", " btn = gr.Button(\"Run\")\n", " btn.click(image_mod, text, text)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/input_output/run.py b/demo/input_output/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a09c05fc514335919f2cfa7330b15cebf10bbe82
--- /dev/null
+++ b/demo/input_output/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+
+def image_mod(text):
+ return text[::-1]
+
+
+demo = gr.Blocks()
+
+with demo:
+ text = gr.Textbox(label="Input-Output")
+ btn = gr.Button("Run")
+ btn.click(image_mod, text, text)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/interface_random_slider/run.ipynb b/demo/interface_random_slider/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dcdef26f3983bbd6d3a66fdbe9392d209ed20cc8
--- /dev/null
+++ b/demo/interface_random_slider/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: interface_random_slider"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def func(slider_1, slider_2, *args):\n", " return slider_1 + slider_2 * 5\n", "\n", "\n", "demo = gr.Interface(\n", " func,\n", " [\n", " gr.Slider(minimum=1.5, maximum=250000.89, randomize=True, label=\"Random Big Range\"),\n", " gr.Slider(minimum=-1, maximum=1, randomize=True, step=0.05, label=\"Random only multiple of 0.05 allowed\"),\n", " gr.Slider(minimum=0, maximum=1, randomize=True, step=0.25, label=\"Random only multiples of 0.25 allowed\"),\n", " gr.Slider(minimum=-100, maximum=100, randomize=True, step=3, label=\"Random between -100 and 100 step 3\"),\n", " gr.Slider(minimum=-100, maximum=100, randomize=True, label=\"Random between -100 and 100\"),\n", " gr.Slider(value=0.25, minimum=5, maximum=30, step=-1),\n", " ],\n", " \"number\",\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/interface_random_slider/run.py b/demo/interface_random_slider/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d199f706615434773b48cbd1c7f6fcb199eba0f
--- /dev/null
+++ b/demo/interface_random_slider/run.py
@@ -0,0 +1,22 @@
+import gradio as gr
+
+
+def func(slider_1, slider_2, *args):
+ return slider_1 + slider_2 * 5
+
+
+demo = gr.Interface(
+ func,
+ [
+ gr.Slider(minimum=1.5, maximum=250000.89, randomize=True, label="Random Big Range"),
+ gr.Slider(minimum=-1, maximum=1, randomize=True, step=0.05, label="Random only multiple of 0.05 allowed"),
+ gr.Slider(minimum=0, maximum=1, randomize=True, step=0.25, label="Random only multiples of 0.25 allowed"),
+ gr.Slider(minimum=-100, maximum=100, randomize=True, step=3, label="Random between -100 and 100 step 3"),
+ gr.Slider(minimum=-100, maximum=100, randomize=True, label="Random between -100 and 100"),
+ gr.Slider(value=0.25, minimum=5, maximum=30, step=-1),
+ ],
+ "number",
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/interface_state/run.ipynb b/demo/interface_state/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c6bed438c6b29568756c2b581bd5ac1cad4a447e
--- /dev/null
+++ b/demo/interface_state/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: interface_state"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def store_message(message: str, history: list[str]):\n", " output = {\n", " \"Current messages\": message,\n", " \"Previous messages\": history[::-1]\n", " }\n", " history.append(message)\n", " return output, history\n", "\n", "demo = gr.Interface(fn=store_message, \n", " inputs=[\"textbox\", gr.State(value=[])], \n", " outputs=[\"json\", gr.State()])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/interface_state/run.py b/demo/interface_state/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..bca48f17ad9adce8b3aa80c4902289afd011527e
--- /dev/null
+++ b/demo/interface_state/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+def store_message(message: str, history: list[str]):
+ output = {
+ "Current messages": message,
+ "Previous messages": history[::-1]
+ }
+ history.append(message)
+ return output, history
+
+demo = gr.Interface(fn=store_message,
+ inputs=["textbox", gr.State(value=[])],
+ outputs=["json", gr.State()])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/interface_with_additional_inputs/run.ipynb b/demo/interface_with_additional_inputs/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9d3ad0922d3ac027750cc97ee89de6b43f871812
--- /dev/null
+++ b/demo/interface_with_additional_inputs/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: interface_with_additional_inputs"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def generate_fake_image(prompt, seed, initial_image=None):\n", " return f\"Used seed: {seed}\", \"https://dummyimage.com/300/09f.png\"\n", "\n", "\n", "demo = gr.Interface(\n", " generate_fake_image,\n", " inputs=[\"textbox\"],\n", " outputs=[\"textbox\", \"image\"],\n", " additional_inputs=[\n", " gr.Slider(0, 1000),\n", " \"image\"\n", " ]\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", "\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/interface_with_additional_inputs/run.py b/demo/interface_with_additional_inputs/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5c4bd14c7546cf024eb680077f4c8ef62c3c25e
--- /dev/null
+++ b/demo/interface_with_additional_inputs/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+
+def generate_fake_image(prompt, seed, initial_image=None):
+ return f"Used seed: {seed}", "https://dummyimage.com/300/09f.png"
+
+
+demo = gr.Interface(
+ generate_fake_image,
+ inputs=["textbox"],
+ outputs=["textbox", "image"],
+ additional_inputs=[
+ gr.Slider(0, 1000),
+ "image"
+ ]
+)
+
+if __name__ == "__main__":
+ demo.launch()
+
diff --git a/demo/json_component/run.ipynb b/demo/json_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c0959b07eddfbdcd8d6b95c8cbabe62d8d639502
--- /dev/null
+++ b/demo/json_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: json_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.JSON(value={\"Key 1\": \"Value 1\", \"Key 2\": {\"Key 3\": \"Value 2\", \"Key 4\": \"Value 3\"}, \"Key 5\": [\"Item 1\", \"Item 2\", \"Item 3\"]})\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/json_component/run.py b/demo/json_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3fcd5ea9b6eaf0dfb87ed885e970560e2c41360
--- /dev/null
+++ b/demo/json_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.JSON(value={"Key 1": "Value 1", "Key 2": {"Key 3": "Value 2", "Key 4": "Value 3"}, "Key 5": ["Item 1", "Item 2", "Item 3"]})
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/kitchen_sink/files/cantina.wav b/demo/kitchen_sink/files/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/kitchen_sink/files/cantina.wav differ
diff --git a/demo/kitchen_sink/files/cheetah1.jpg b/demo/kitchen_sink/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/kitchen_sink/files/cheetah1.jpg differ
diff --git a/demo/kitchen_sink/files/lion.jpg b/demo/kitchen_sink/files/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/kitchen_sink/files/lion.jpg differ
diff --git a/demo/kitchen_sink/files/logo.png b/demo/kitchen_sink/files/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f1df7156f0a690a2415903061e19c20e24adac4
Binary files /dev/null and b/demo/kitchen_sink/files/logo.png differ
diff --git a/demo/kitchen_sink/files/time.csv b/demo/kitchen_sink/files/time.csv
new file mode 100644
index 0000000000000000000000000000000000000000..ddb2035c4ed0377f54ee1602fff9f05ba5daa2db
--- /dev/null
+++ b/demo/kitchen_sink/files/time.csv
@@ -0,0 +1,8 @@
+time,value,price
+1,1,4
+2,3,8
+3,6,12
+4,10,16
+5,15,20
+6,21,24
+7,28,28
\ No newline at end of file
diff --git a/demo/kitchen_sink/files/titanic.csv b/demo/kitchen_sink/files/titanic.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5cc466e97cf12f155d19b9f717425214075d0b7a
--- /dev/null
+++ b/demo/kitchen_sink/files/titanic.csv
@@ -0,0 +1,892 @@
+PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
+1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
+2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
+3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
+4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
+5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
+6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
+7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
+8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
+9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
+10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
+11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
+12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
+13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
+14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S
+15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S
+16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S
+17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q
+18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S
+19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S
+20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C
+21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S
+22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S
+23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q
+24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S
+25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S
+26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S
+27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C
+28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S
+29,1,3,"O'Dwyer, Miss. Ellen ""Nellie""",female,,0,0,330959,7.8792,,Q
+30,0,3,"Todoroff, Mr. Lalio",male,,0,0,349216,7.8958,,S
+31,0,1,"Uruchurtu, Don. Manuel E",male,40,0,0,PC 17601,27.7208,,C
+32,1,1,"Spencer, Mrs. William Augustus (Marie Eugenie)",female,,1,0,PC 17569,146.5208,B78,C
+33,1,3,"Glynn, Miss. Mary Agatha",female,,0,0,335677,7.75,,Q
+34,0,2,"Wheadon, Mr. Edward H",male,66,0,0,C.A. 24579,10.5,,S
+35,0,1,"Meyer, Mr. Edgar Joseph",male,28,1,0,PC 17604,82.1708,,C
+36,0,1,"Holverson, Mr. Alexander Oskar",male,42,1,0,113789,52,,S
+37,1,3,"Mamee, Mr. Hanna",male,,0,0,2677,7.2292,,C
+38,0,3,"Cann, Mr. Ernest Charles",male,21,0,0,A./5. 2152,8.05,,S
+39,0,3,"Vander Planke, Miss. Augusta Maria",female,18,2,0,345764,18,,S
+40,1,3,"Nicola-Yarred, Miss. Jamila",female,14,1,0,2651,11.2417,,C
+41,0,3,"Ahlin, Mrs. Johan (Johanna Persdotter Larsson)",female,40,1,0,7546,9.475,,S
+42,0,2,"Turpin, Mrs. William John Robert (Dorothy Ann Wonnacott)",female,27,1,0,11668,21,,S
+43,0,3,"Kraeff, Mr. Theodor",male,,0,0,349253,7.8958,,C
+44,1,2,"Laroche, Miss. Simonne Marie Anne Andree",female,3,1,2,SC/Paris 2123,41.5792,,C
+45,1,3,"Devaney, Miss. Margaret Delia",female,19,0,0,330958,7.8792,,Q
+46,0,3,"Rogers, Mr. William John",male,,0,0,S.C./A.4. 23567,8.05,,S
+47,0,3,"Lennon, Mr. Denis",male,,1,0,370371,15.5,,Q
+48,1,3,"O'Driscoll, Miss. Bridget",female,,0,0,14311,7.75,,Q
+49,0,3,"Samaan, Mr. Youssef",male,,2,0,2662,21.6792,,C
+50,0,3,"Arnold-Franchi, Mrs. Josef (Josefine Franchi)",female,18,1,0,349237,17.8,,S
+51,0,3,"Panula, Master. Juha Niilo",male,7,4,1,3101295,39.6875,,S
+52,0,3,"Nosworthy, Mr. Richard Cater",male,21,0,0,A/4. 39886,7.8,,S
+53,1,1,"Harper, Mrs. Henry Sleeper (Myna Haxtun)",female,49,1,0,PC 17572,76.7292,D33,C
+54,1,2,"Faunthorpe, Mrs. Lizzie (Elizabeth Anne Wilkinson)",female,29,1,0,2926,26,,S
+55,0,1,"Ostby, Mr. Engelhart Cornelius",male,65,0,1,113509,61.9792,B30,C
+56,1,1,"Woolner, Mr. Hugh",male,,0,0,19947,35.5,C52,S
+57,1,2,"Rugg, Miss. Emily",female,21,0,0,C.A. 31026,10.5,,S
+58,0,3,"Novel, Mr. Mansouer",male,28.5,0,0,2697,7.2292,,C
+59,1,2,"West, Miss. Constance Mirium",female,5,1,2,C.A. 34651,27.75,,S
+60,0,3,"Goodwin, Master. William Frederick",male,11,5,2,CA 2144,46.9,,S
+61,0,3,"Sirayanian, Mr. Orsen",male,22,0,0,2669,7.2292,,C
+62,1,1,"Icard, Miss. Amelie",female,38,0,0,113572,80,B28,
+63,0,1,"Harris, Mr. Henry Birkhardt",male,45,1,0,36973,83.475,C83,S
+64,0,3,"Skoog, Master. Harald",male,4,3,2,347088,27.9,,S
+65,0,1,"Stewart, Mr. Albert A",male,,0,0,PC 17605,27.7208,,C
+66,1,3,"Moubarek, Master. Gerios",male,,1,1,2661,15.2458,,C
+67,1,2,"Nye, Mrs. (Elizabeth Ramell)",female,29,0,0,C.A. 29395,10.5,F33,S
+68,0,3,"Crease, Mr. Ernest James",male,19,0,0,S.P. 3464,8.1583,,S
+69,1,3,"Andersson, Miss. Erna Alexandra",female,17,4,2,3101281,7.925,,S
+70,0,3,"Kink, Mr. Vincenz",male,26,2,0,315151,8.6625,,S
+71,0,2,"Jenkin, Mr. Stephen Curnow",male,32,0,0,C.A. 33111,10.5,,S
+72,0,3,"Goodwin, Miss. Lillian Amy",female,16,5,2,CA 2144,46.9,,S
+73,0,2,"Hood, Mr. Ambrose Jr",male,21,0,0,S.O.C. 14879,73.5,,S
+74,0,3,"Chronopoulos, Mr. Apostolos",male,26,1,0,2680,14.4542,,C
+75,1,3,"Bing, Mr. Lee",male,32,0,0,1601,56.4958,,S
+76,0,3,"Moen, Mr. Sigurd Hansen",male,25,0,0,348123,7.65,F G73,S
+77,0,3,"Staneff, Mr. Ivan",male,,0,0,349208,7.8958,,S
+78,0,3,"Moutal, Mr. Rahamin Haim",male,,0,0,374746,8.05,,S
+79,1,2,"Caldwell, Master. Alden Gates",male,0.83,0,2,248738,29,,S
+80,1,3,"Dowdell, Miss. Elizabeth",female,30,0,0,364516,12.475,,S
+81,0,3,"Waelens, Mr. Achille",male,22,0,0,345767,9,,S
+82,1,3,"Sheerlinck, Mr. Jan Baptist",male,29,0,0,345779,9.5,,S
+83,1,3,"McDermott, Miss. Brigdet Delia",female,,0,0,330932,7.7875,,Q
+84,0,1,"Carrau, Mr. Francisco M",male,28,0,0,113059,47.1,,S
+85,1,2,"Ilett, Miss. Bertha",female,17,0,0,SO/C 14885,10.5,,S
+86,1,3,"Backstrom, Mrs. Karl Alfred (Maria Mathilda Gustafsson)",female,33,3,0,3101278,15.85,,S
+87,0,3,"Ford, Mr. William Neal",male,16,1,3,W./C. 6608,34.375,,S
+88,0,3,"Slocovski, Mr. Selman Francis",male,,0,0,SOTON/OQ 392086,8.05,,S
+89,1,1,"Fortune, Miss. Mabel Helen",female,23,3,2,19950,263,C23 C25 C27,S
+90,0,3,"Celotti, Mr. Francesco",male,24,0,0,343275,8.05,,S
+91,0,3,"Christmann, Mr. Emil",male,29,0,0,343276,8.05,,S
+92,0,3,"Andreasson, Mr. Paul Edvin",male,20,0,0,347466,7.8542,,S
+93,0,1,"Chaffee, Mr. Herbert Fuller",male,46,1,0,W.E.P. 5734,61.175,E31,S
+94,0,3,"Dean, Mr. Bertram Frank",male,26,1,2,C.A. 2315,20.575,,S
+95,0,3,"Coxon, Mr. Daniel",male,59,0,0,364500,7.25,,S
+96,0,3,"Shorney, Mr. Charles Joseph",male,,0,0,374910,8.05,,S
+97,0,1,"Goldschmidt, Mr. George B",male,71,0,0,PC 17754,34.6542,A5,C
+98,1,1,"Greenfield, Mr. William Bertram",male,23,0,1,PC 17759,63.3583,D10 D12,C
+99,1,2,"Doling, Mrs. John T (Ada Julia Bone)",female,34,0,1,231919,23,,S
+100,0,2,"Kantor, Mr. Sinai",male,34,1,0,244367,26,,S
+101,0,3,"Petranec, Miss. Matilda",female,28,0,0,349245,7.8958,,S
+102,0,3,"Petroff, Mr. Pastcho (""Pentcho"")",male,,0,0,349215,7.8958,,S
+103,0,1,"White, Mr. Richard Frasar",male,21,0,1,35281,77.2875,D26,S
+104,0,3,"Johansson, Mr. Gustaf Joel",male,33,0,0,7540,8.6542,,S
+105,0,3,"Gustafsson, Mr. Anders Vilhelm",male,37,2,0,3101276,7.925,,S
+106,0,3,"Mionoff, Mr. Stoytcho",male,28,0,0,349207,7.8958,,S
+107,1,3,"Salkjelsvik, Miss. Anna Kristine",female,21,0,0,343120,7.65,,S
+108,1,3,"Moss, Mr. Albert Johan",male,,0,0,312991,7.775,,S
+109,0,3,"Rekic, Mr. Tido",male,38,0,0,349249,7.8958,,S
+110,1,3,"Moran, Miss. Bertha",female,,1,0,371110,24.15,,Q
+111,0,1,"Porter, Mr. Walter Chamberlain",male,47,0,0,110465,52,C110,S
+112,0,3,"Zabour, Miss. Hileni",female,14.5,1,0,2665,14.4542,,C
+113,0,3,"Barton, Mr. David John",male,22,0,0,324669,8.05,,S
+114,0,3,"Jussila, Miss. Katriina",female,20,1,0,4136,9.825,,S
+115,0,3,"Attalah, Miss. Malake",female,17,0,0,2627,14.4583,,C
+116,0,3,"Pekoniemi, Mr. Edvard",male,21,0,0,STON/O 2. 3101294,7.925,,S
+117,0,3,"Connors, Mr. Patrick",male,70.5,0,0,370369,7.75,,Q
+118,0,2,"Turpin, Mr. William John Robert",male,29,1,0,11668,21,,S
+119,0,1,"Baxter, Mr. Quigg Edmond",male,24,0,1,PC 17558,247.5208,B58 B60,C
+120,0,3,"Andersson, Miss. Ellis Anna Maria",female,2,4,2,347082,31.275,,S
+121,0,2,"Hickman, Mr. Stanley George",male,21,2,0,S.O.C. 14879,73.5,,S
+122,0,3,"Moore, Mr. Leonard Charles",male,,0,0,A4. 54510,8.05,,S
+123,0,2,"Nasser, Mr. Nicholas",male,32.5,1,0,237736,30.0708,,C
+124,1,2,"Webber, Miss. Susan",female,32.5,0,0,27267,13,E101,S
+125,0,1,"White, Mr. Percival Wayland",male,54,0,1,35281,77.2875,D26,S
+126,1,3,"Nicola-Yarred, Master. Elias",male,12,1,0,2651,11.2417,,C
+127,0,3,"McMahon, Mr. Martin",male,,0,0,370372,7.75,,Q
+128,1,3,"Madsen, Mr. Fridtjof Arne",male,24,0,0,C 17369,7.1417,,S
+129,1,3,"Peter, Miss. Anna",female,,1,1,2668,22.3583,F E69,C
+130,0,3,"Ekstrom, Mr. Johan",male,45,0,0,347061,6.975,,S
+131,0,3,"Drazenoic, Mr. Jozef",male,33,0,0,349241,7.8958,,C
+132,0,3,"Coelho, Mr. Domingos Fernandeo",male,20,0,0,SOTON/O.Q. 3101307,7.05,,S
+133,0,3,"Robins, Mrs. Alexander A (Grace Charity Laury)",female,47,1,0,A/5. 3337,14.5,,S
+134,1,2,"Weisz, Mrs. Leopold (Mathilde Francoise Pede)",female,29,1,0,228414,26,,S
+135,0,2,"Sobey, Mr. Samuel James Hayden",male,25,0,0,C.A. 29178,13,,S
+136,0,2,"Richard, Mr. Emile",male,23,0,0,SC/PARIS 2133,15.0458,,C
+137,1,1,"Newsom, Miss. Helen Monypeny",female,19,0,2,11752,26.2833,D47,S
+138,0,1,"Futrelle, Mr. Jacques Heath",male,37,1,0,113803,53.1,C123,S
+139,0,3,"Osen, Mr. Olaf Elon",male,16,0,0,7534,9.2167,,S
+140,0,1,"Giglio, Mr. Victor",male,24,0,0,PC 17593,79.2,B86,C
+141,0,3,"Boulos, Mrs. Joseph (Sultana)",female,,0,2,2678,15.2458,,C
+142,1,3,"Nysten, Miss. Anna Sofia",female,22,0,0,347081,7.75,,S
+143,1,3,"Hakkarainen, Mrs. Pekka Pietari (Elin Matilda Dolck)",female,24,1,0,STON/O2. 3101279,15.85,,S
+144,0,3,"Burke, Mr. Jeremiah",male,19,0,0,365222,6.75,,Q
+145,0,2,"Andrew, Mr. Edgardo Samuel",male,18,0,0,231945,11.5,,S
+146,0,2,"Nicholls, Mr. Joseph Charles",male,19,1,1,C.A. 33112,36.75,,S
+147,1,3,"Andersson, Mr. August Edvard (""Wennerstrom"")",male,27,0,0,350043,7.7958,,S
+148,0,3,"Ford, Miss. Robina Maggie ""Ruby""",female,9,2,2,W./C. 6608,34.375,,S
+149,0,2,"Navratil, Mr. Michel (""Louis M Hoffman"")",male,36.5,0,2,230080,26,F2,S
+150,0,2,"Byles, Rev. Thomas Roussel Davids",male,42,0,0,244310,13,,S
+151,0,2,"Bateman, Rev. Robert James",male,51,0,0,S.O.P. 1166,12.525,,S
+152,1,1,"Pears, Mrs. Thomas (Edith Wearne)",female,22,1,0,113776,66.6,C2,S
+153,0,3,"Meo, Mr. Alfonzo",male,55.5,0,0,A.5. 11206,8.05,,S
+154,0,3,"van Billiard, Mr. Austin Blyler",male,40.5,0,2,A/5. 851,14.5,,S
+155,0,3,"Olsen, Mr. Ole Martin",male,,0,0,Fa 265302,7.3125,,S
+156,0,1,"Williams, Mr. Charles Duane",male,51,0,1,PC 17597,61.3792,,C
+157,1,3,"Gilnagh, Miss. Katherine ""Katie""",female,16,0,0,35851,7.7333,,Q
+158,0,3,"Corn, Mr. Harry",male,30,0,0,SOTON/OQ 392090,8.05,,S
+159,0,3,"Smiljanic, Mr. Mile",male,,0,0,315037,8.6625,,S
+160,0,3,"Sage, Master. Thomas Henry",male,,8,2,CA. 2343,69.55,,S
+161,0,3,"Cribb, Mr. John Hatfield",male,44,0,1,371362,16.1,,S
+162,1,2,"Watt, Mrs. James (Elizabeth ""Bessie"" Inglis Milne)",female,40,0,0,C.A. 33595,15.75,,S
+163,0,3,"Bengtsson, Mr. John Viktor",male,26,0,0,347068,7.775,,S
+164,0,3,"Calic, Mr. Jovo",male,17,0,0,315093,8.6625,,S
+165,0,3,"Panula, Master. Eino Viljami",male,1,4,1,3101295,39.6875,,S
+166,1,3,"Goldsmith, Master. Frank John William ""Frankie""",male,9,0,2,363291,20.525,,S
+167,1,1,"Chibnall, Mrs. (Edith Martha Bowerman)",female,,0,1,113505,55,E33,S
+168,0,3,"Skoog, Mrs. William (Anna Bernhardina Karlsson)",female,45,1,4,347088,27.9,,S
+169,0,1,"Baumann, Mr. John D",male,,0,0,PC 17318,25.925,,S
+170,0,3,"Ling, Mr. Lee",male,28,0,0,1601,56.4958,,S
+171,0,1,"Van der hoef, Mr. Wyckoff",male,61,0,0,111240,33.5,B19,S
+172,0,3,"Rice, Master. Arthur",male,4,4,1,382652,29.125,,Q
+173,1,3,"Johnson, Miss. Eleanor Ileen",female,1,1,1,347742,11.1333,,S
+174,0,3,"Sivola, Mr. Antti Wilhelm",male,21,0,0,STON/O 2. 3101280,7.925,,S
+175,0,1,"Smith, Mr. James Clinch",male,56,0,0,17764,30.6958,A7,C
+176,0,3,"Klasen, Mr. Klas Albin",male,18,1,1,350404,7.8542,,S
+177,0,3,"Lefebre, Master. Henry Forbes",male,,3,1,4133,25.4667,,S
+178,0,1,"Isham, Miss. Ann Elizabeth",female,50,0,0,PC 17595,28.7125,C49,C
+179,0,2,"Hale, Mr. Reginald",male,30,0,0,250653,13,,S
+180,0,3,"Leonard, Mr. Lionel",male,36,0,0,LINE,0,,S
+181,0,3,"Sage, Miss. Constance Gladys",female,,8,2,CA. 2343,69.55,,S
+182,0,2,"Pernot, Mr. Rene",male,,0,0,SC/PARIS 2131,15.05,,C
+183,0,3,"Asplund, Master. Clarence Gustaf Hugo",male,9,4,2,347077,31.3875,,S
+184,1,2,"Becker, Master. Richard F",male,1,2,1,230136,39,F4,S
+185,1,3,"Kink-Heilmann, Miss. Luise Gretchen",female,4,0,2,315153,22.025,,S
+186,0,1,"Rood, Mr. Hugh Roscoe",male,,0,0,113767,50,A32,S
+187,1,3,"O'Brien, Mrs. Thomas (Johanna ""Hannah"" Godfrey)",female,,1,0,370365,15.5,,Q
+188,1,1,"Romaine, Mr. Charles Hallace (""Mr C Rolmane"")",male,45,0,0,111428,26.55,,S
+189,0,3,"Bourke, Mr. John",male,40,1,1,364849,15.5,,Q
+190,0,3,"Turcin, Mr. Stjepan",male,36,0,0,349247,7.8958,,S
+191,1,2,"Pinsky, Mrs. (Rosa)",female,32,0,0,234604,13,,S
+192,0,2,"Carbines, Mr. William",male,19,0,0,28424,13,,S
+193,1,3,"Andersen-Jensen, Miss. Carla Christine Nielsine",female,19,1,0,350046,7.8542,,S
+194,1,2,"Navratil, Master. Michel M",male,3,1,1,230080,26,F2,S
+195,1,1,"Brown, Mrs. James Joseph (Margaret Tobin)",female,44,0,0,PC 17610,27.7208,B4,C
+196,1,1,"Lurette, Miss. Elise",female,58,0,0,PC 17569,146.5208,B80,C
+197,0,3,"Mernagh, Mr. Robert",male,,0,0,368703,7.75,,Q
+198,0,3,"Olsen, Mr. Karl Siegwart Andreas",male,42,0,1,4579,8.4042,,S
+199,1,3,"Madigan, Miss. Margaret ""Maggie""",female,,0,0,370370,7.75,,Q
+200,0,2,"Yrois, Miss. Henriette (""Mrs Harbeck"")",female,24,0,0,248747,13,,S
+201,0,3,"Vande Walle, Mr. Nestor Cyriel",male,28,0,0,345770,9.5,,S
+202,0,3,"Sage, Mr. Frederick",male,,8,2,CA. 2343,69.55,,S
+203,0,3,"Johanson, Mr. Jakob Alfred",male,34,0,0,3101264,6.4958,,S
+204,0,3,"Youseff, Mr. Gerious",male,45.5,0,0,2628,7.225,,C
+205,1,3,"Cohen, Mr. Gurshon ""Gus""",male,18,0,0,A/5 3540,8.05,,S
+206,0,3,"Strom, Miss. Telma Matilda",female,2,0,1,347054,10.4625,G6,S
+207,0,3,"Backstrom, Mr. Karl Alfred",male,32,1,0,3101278,15.85,,S
+208,1,3,"Albimona, Mr. Nassef Cassem",male,26,0,0,2699,18.7875,,C
+209,1,3,"Carr, Miss. Helen ""Ellen""",female,16,0,0,367231,7.75,,Q
+210,1,1,"Blank, Mr. Henry",male,40,0,0,112277,31,A31,C
+211,0,3,"Ali, Mr. Ahmed",male,24,0,0,SOTON/O.Q. 3101311,7.05,,S
+212,1,2,"Cameron, Miss. Clear Annie",female,35,0,0,F.C.C. 13528,21,,S
+213,0,3,"Perkin, Mr. John Henry",male,22,0,0,A/5 21174,7.25,,S
+214,0,2,"Givard, Mr. Hans Kristensen",male,30,0,0,250646,13,,S
+215,0,3,"Kiernan, Mr. Philip",male,,1,0,367229,7.75,,Q
+216,1,1,"Newell, Miss. Madeleine",female,31,1,0,35273,113.275,D36,C
+217,1,3,"Honkanen, Miss. Eliina",female,27,0,0,STON/O2. 3101283,7.925,,S
+218,0,2,"Jacobsohn, Mr. Sidney Samuel",male,42,1,0,243847,27,,S
+219,1,1,"Bazzani, Miss. Albina",female,32,0,0,11813,76.2917,D15,C
+220,0,2,"Harris, Mr. Walter",male,30,0,0,W/C 14208,10.5,,S
+221,1,3,"Sunderland, Mr. Victor Francis",male,16,0,0,SOTON/OQ 392089,8.05,,S
+222,0,2,"Bracken, Mr. James H",male,27,0,0,220367,13,,S
+223,0,3,"Green, Mr. George Henry",male,51,0,0,21440,8.05,,S
+224,0,3,"Nenkoff, Mr. Christo",male,,0,0,349234,7.8958,,S
+225,1,1,"Hoyt, Mr. Frederick Maxfield",male,38,1,0,19943,90,C93,S
+226,0,3,"Berglund, Mr. Karl Ivar Sven",male,22,0,0,PP 4348,9.35,,S
+227,1,2,"Mellors, Mr. William John",male,19,0,0,SW/PP 751,10.5,,S
+228,0,3,"Lovell, Mr. John Hall (""Henry"")",male,20.5,0,0,A/5 21173,7.25,,S
+229,0,2,"Fahlstrom, Mr. Arne Jonas",male,18,0,0,236171,13,,S
+230,0,3,"Lefebre, Miss. Mathilde",female,,3,1,4133,25.4667,,S
+231,1,1,"Harris, Mrs. Henry Birkhardt (Irene Wallach)",female,35,1,0,36973,83.475,C83,S
+232,0,3,"Larsson, Mr. Bengt Edvin",male,29,0,0,347067,7.775,,S
+233,0,2,"Sjostedt, Mr. Ernst Adolf",male,59,0,0,237442,13.5,,S
+234,1,3,"Asplund, Miss. Lillian Gertrud",female,5,4,2,347077,31.3875,,S
+235,0,2,"Leyson, Mr. Robert William Norman",male,24,0,0,C.A. 29566,10.5,,S
+236,0,3,"Harknett, Miss. Alice Phoebe",female,,0,0,W./C. 6609,7.55,,S
+237,0,2,"Hold, Mr. Stephen",male,44,1,0,26707,26,,S
+238,1,2,"Collyer, Miss. Marjorie ""Lottie""",female,8,0,2,C.A. 31921,26.25,,S
+239,0,2,"Pengelly, Mr. Frederick William",male,19,0,0,28665,10.5,,S
+240,0,2,"Hunt, Mr. George Henry",male,33,0,0,SCO/W 1585,12.275,,S
+241,0,3,"Zabour, Miss. Thamine",female,,1,0,2665,14.4542,,C
+242,1,3,"Murphy, Miss. Katherine ""Kate""",female,,1,0,367230,15.5,,Q
+243,0,2,"Coleridge, Mr. Reginald Charles",male,29,0,0,W./C. 14263,10.5,,S
+244,0,3,"Maenpaa, Mr. Matti Alexanteri",male,22,0,0,STON/O 2. 3101275,7.125,,S
+245,0,3,"Attalah, Mr. Sleiman",male,30,0,0,2694,7.225,,C
+246,0,1,"Minahan, Dr. William Edward",male,44,2,0,19928,90,C78,Q
+247,0,3,"Lindahl, Miss. Agda Thorilda Viktoria",female,25,0,0,347071,7.775,,S
+248,1,2,"Hamalainen, Mrs. William (Anna)",female,24,0,2,250649,14.5,,S
+249,1,1,"Beckwith, Mr. Richard Leonard",male,37,1,1,11751,52.5542,D35,S
+250,0,2,"Carter, Rev. Ernest Courtenay",male,54,1,0,244252,26,,S
+251,0,3,"Reed, Mr. James George",male,,0,0,362316,7.25,,S
+252,0,3,"Strom, Mrs. Wilhelm (Elna Matilda Persson)",female,29,1,1,347054,10.4625,G6,S
+253,0,1,"Stead, Mr. William Thomas",male,62,0,0,113514,26.55,C87,S
+254,0,3,"Lobb, Mr. William Arthur",male,30,1,0,A/5. 3336,16.1,,S
+255,0,3,"Rosblom, Mrs. Viktor (Helena Wilhelmina)",female,41,0,2,370129,20.2125,,S
+256,1,3,"Touma, Mrs. Darwis (Hanne Youssef Razi)",female,29,0,2,2650,15.2458,,C
+257,1,1,"Thorne, Mrs. Gertrude Maybelle",female,,0,0,PC 17585,79.2,,C
+258,1,1,"Cherry, Miss. Gladys",female,30,0,0,110152,86.5,B77,S
+259,1,1,"Ward, Miss. Anna",female,35,0,0,PC 17755,512.3292,,C
+260,1,2,"Parrish, Mrs. (Lutie Davis)",female,50,0,1,230433,26,,S
+261,0,3,"Smith, Mr. Thomas",male,,0,0,384461,7.75,,Q
+262,1,3,"Asplund, Master. Edvin Rojj Felix",male,3,4,2,347077,31.3875,,S
+263,0,1,"Taussig, Mr. Emil",male,52,1,1,110413,79.65,E67,S
+264,0,1,"Harrison, Mr. William",male,40,0,0,112059,0,B94,S
+265,0,3,"Henry, Miss. Delia",female,,0,0,382649,7.75,,Q
+266,0,2,"Reeves, Mr. David",male,36,0,0,C.A. 17248,10.5,,S
+267,0,3,"Panula, Mr. Ernesti Arvid",male,16,4,1,3101295,39.6875,,S
+268,1,3,"Persson, Mr. Ernst Ulrik",male,25,1,0,347083,7.775,,S
+269,1,1,"Graham, Mrs. William Thompson (Edith Junkins)",female,58,0,1,PC 17582,153.4625,C125,S
+270,1,1,"Bissette, Miss. Amelia",female,35,0,0,PC 17760,135.6333,C99,S
+271,0,1,"Cairns, Mr. Alexander",male,,0,0,113798,31,,S
+272,1,3,"Tornquist, Mr. William Henry",male,25,0,0,LINE,0,,S
+273,1,2,"Mellinger, Mrs. (Elizabeth Anne Maidment)",female,41,0,1,250644,19.5,,S
+274,0,1,"Natsch, Mr. Charles H",male,37,0,1,PC 17596,29.7,C118,C
+275,1,3,"Healy, Miss. Hanora ""Nora""",female,,0,0,370375,7.75,,Q
+276,1,1,"Andrews, Miss. Kornelia Theodosia",female,63,1,0,13502,77.9583,D7,S
+277,0,3,"Lindblom, Miss. Augusta Charlotta",female,45,0,0,347073,7.75,,S
+278,0,2,"Parkes, Mr. Francis ""Frank""",male,,0,0,239853,0,,S
+279,0,3,"Rice, Master. Eric",male,7,4,1,382652,29.125,,Q
+280,1,3,"Abbott, Mrs. Stanton (Rosa Hunt)",female,35,1,1,C.A. 2673,20.25,,S
+281,0,3,"Duane, Mr. Frank",male,65,0,0,336439,7.75,,Q
+282,0,3,"Olsson, Mr. Nils Johan Goransson",male,28,0,0,347464,7.8542,,S
+283,0,3,"de Pelsmaeker, Mr. Alfons",male,16,0,0,345778,9.5,,S
+284,1,3,"Dorking, Mr. Edward Arthur",male,19,0,0,A/5. 10482,8.05,,S
+285,0,1,"Smith, Mr. Richard William",male,,0,0,113056,26,A19,S
+286,0,3,"Stankovic, Mr. Ivan",male,33,0,0,349239,8.6625,,C
+287,1,3,"de Mulder, Mr. Theodore",male,30,0,0,345774,9.5,,S
+288,0,3,"Naidenoff, Mr. Penko",male,22,0,0,349206,7.8958,,S
+289,1,2,"Hosono, Mr. Masabumi",male,42,0,0,237798,13,,S
+290,1,3,"Connolly, Miss. Kate",female,22,0,0,370373,7.75,,Q
+291,1,1,"Barber, Miss. Ellen ""Nellie""",female,26,0,0,19877,78.85,,S
+292,1,1,"Bishop, Mrs. Dickinson H (Helen Walton)",female,19,1,0,11967,91.0792,B49,C
+293,0,2,"Levy, Mr. Rene Jacques",male,36,0,0,SC/Paris 2163,12.875,D,C
+294,0,3,"Haas, Miss. Aloisia",female,24,0,0,349236,8.85,,S
+295,0,3,"Mineff, Mr. Ivan",male,24,0,0,349233,7.8958,,S
+296,0,1,"Lewy, Mr. Ervin G",male,,0,0,PC 17612,27.7208,,C
+297,0,3,"Hanna, Mr. Mansour",male,23.5,0,0,2693,7.2292,,C
+298,0,1,"Allison, Miss. Helen Loraine",female,2,1,2,113781,151.55,C22 C26,S
+299,1,1,"Saalfeld, Mr. Adolphe",male,,0,0,19988,30.5,C106,S
+300,1,1,"Baxter, Mrs. James (Helene DeLaudeniere Chaput)",female,50,0,1,PC 17558,247.5208,B58 B60,C
+301,1,3,"Kelly, Miss. Anna Katherine ""Annie Kate""",female,,0,0,9234,7.75,,Q
+302,1,3,"McCoy, Mr. Bernard",male,,2,0,367226,23.25,,Q
+303,0,3,"Johnson, Mr. William Cahoone Jr",male,19,0,0,LINE,0,,S
+304,1,2,"Keane, Miss. Nora A",female,,0,0,226593,12.35,E101,Q
+305,0,3,"Williams, Mr. Howard Hugh ""Harry""",male,,0,0,A/5 2466,8.05,,S
+306,1,1,"Allison, Master. Hudson Trevor",male,0.92,1,2,113781,151.55,C22 C26,S
+307,1,1,"Fleming, Miss. Margaret",female,,0,0,17421,110.8833,,C
+308,1,1,"Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)",female,17,1,0,PC 17758,108.9,C65,C
+309,0,2,"Abelson, Mr. Samuel",male,30,1,0,P/PP 3381,24,,C
+310,1,1,"Francatelli, Miss. Laura Mabel",female,30,0,0,PC 17485,56.9292,E36,C
+311,1,1,"Hays, Miss. Margaret Bechstein",female,24,0,0,11767,83.1583,C54,C
+312,1,1,"Ryerson, Miss. Emily Borie",female,18,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+313,0,2,"Lahtinen, Mrs. William (Anna Sylfven)",female,26,1,1,250651,26,,S
+314,0,3,"Hendekovic, Mr. Ignjac",male,28,0,0,349243,7.8958,,S
+315,0,2,"Hart, Mr. Benjamin",male,43,1,1,F.C.C. 13529,26.25,,S
+316,1,3,"Nilsson, Miss. Helmina Josefina",female,26,0,0,347470,7.8542,,S
+317,1,2,"Kantor, Mrs. Sinai (Miriam Sternin)",female,24,1,0,244367,26,,S
+318,0,2,"Moraweck, Dr. Ernest",male,54,0,0,29011,14,,S
+319,1,1,"Wick, Miss. Mary Natalie",female,31,0,2,36928,164.8667,C7,S
+320,1,1,"Spedden, Mrs. Frederic Oakley (Margaretta Corning Stone)",female,40,1,1,16966,134.5,E34,C
+321,0,3,"Dennis, Mr. Samuel",male,22,0,0,A/5 21172,7.25,,S
+322,0,3,"Danoff, Mr. Yoto",male,27,0,0,349219,7.8958,,S
+323,1,2,"Slayter, Miss. Hilda Mary",female,30,0,0,234818,12.35,,Q
+324,1,2,"Caldwell, Mrs. Albert Francis (Sylvia Mae Harbaugh)",female,22,1,1,248738,29,,S
+325,0,3,"Sage, Mr. George John Jr",male,,8,2,CA. 2343,69.55,,S
+326,1,1,"Young, Miss. Marie Grice",female,36,0,0,PC 17760,135.6333,C32,C
+327,0,3,"Nysveen, Mr. Johan Hansen",male,61,0,0,345364,6.2375,,S
+328,1,2,"Ball, Mrs. (Ada E Hall)",female,36,0,0,28551,13,D,S
+329,1,3,"Goldsmith, Mrs. Frank John (Emily Alice Brown)",female,31,1,1,363291,20.525,,S
+330,1,1,"Hippach, Miss. Jean Gertrude",female,16,0,1,111361,57.9792,B18,C
+331,1,3,"McCoy, Miss. Agnes",female,,2,0,367226,23.25,,Q
+332,0,1,"Partner, Mr. Austen",male,45.5,0,0,113043,28.5,C124,S
+333,0,1,"Graham, Mr. George Edward",male,38,0,1,PC 17582,153.4625,C91,S
+334,0,3,"Vander Planke, Mr. Leo Edmondus",male,16,2,0,345764,18,,S
+335,1,1,"Frauenthal, Mrs. Henry William (Clara Heinsheimer)",female,,1,0,PC 17611,133.65,,S
+336,0,3,"Denkoff, Mr. Mitto",male,,0,0,349225,7.8958,,S
+337,0,1,"Pears, Mr. Thomas Clinton",male,29,1,0,113776,66.6,C2,S
+338,1,1,"Burns, Miss. Elizabeth Margaret",female,41,0,0,16966,134.5,E40,C
+339,1,3,"Dahl, Mr. Karl Edwart",male,45,0,0,7598,8.05,,S
+340,0,1,"Blackwell, Mr. Stephen Weart",male,45,0,0,113784,35.5,T,S
+341,1,2,"Navratil, Master. Edmond Roger",male,2,1,1,230080,26,F2,S
+342,1,1,"Fortune, Miss. Alice Elizabeth",female,24,3,2,19950,263,C23 C25 C27,S
+343,0,2,"Collander, Mr. Erik Gustaf",male,28,0,0,248740,13,,S
+344,0,2,"Sedgwick, Mr. Charles Frederick Waddington",male,25,0,0,244361,13,,S
+345,0,2,"Fox, Mr. Stanley Hubert",male,36,0,0,229236,13,,S
+346,1,2,"Brown, Miss. Amelia ""Mildred""",female,24,0,0,248733,13,F33,S
+347,1,2,"Smith, Miss. Marion Elsie",female,40,0,0,31418,13,,S
+348,1,3,"Davison, Mrs. Thomas Henry (Mary E Finck)",female,,1,0,386525,16.1,,S
+349,1,3,"Coutts, Master. William Loch ""William""",male,3,1,1,C.A. 37671,15.9,,S
+350,0,3,"Dimic, Mr. Jovan",male,42,0,0,315088,8.6625,,S
+351,0,3,"Odahl, Mr. Nils Martin",male,23,0,0,7267,9.225,,S
+352,0,1,"Williams-Lambert, Mr. Fletcher Fellows",male,,0,0,113510,35,C128,S
+353,0,3,"Elias, Mr. Tannous",male,15,1,1,2695,7.2292,,C
+354,0,3,"Arnold-Franchi, Mr. Josef",male,25,1,0,349237,17.8,,S
+355,0,3,"Yousif, Mr. Wazli",male,,0,0,2647,7.225,,C
+356,0,3,"Vanden Steen, Mr. Leo Peter",male,28,0,0,345783,9.5,,S
+357,1,1,"Bowerman, Miss. Elsie Edith",female,22,0,1,113505,55,E33,S
+358,0,2,"Funk, Miss. Annie Clemmer",female,38,0,0,237671,13,,S
+359,1,3,"McGovern, Miss. Mary",female,,0,0,330931,7.8792,,Q
+360,1,3,"Mockler, Miss. Helen Mary ""Ellie""",female,,0,0,330980,7.8792,,Q
+361,0,3,"Skoog, Mr. Wilhelm",male,40,1,4,347088,27.9,,S
+362,0,2,"del Carlo, Mr. Sebastiano",male,29,1,0,SC/PARIS 2167,27.7208,,C
+363,0,3,"Barbara, Mrs. (Catherine David)",female,45,0,1,2691,14.4542,,C
+364,0,3,"Asim, Mr. Adola",male,35,0,0,SOTON/O.Q. 3101310,7.05,,S
+365,0,3,"O'Brien, Mr. Thomas",male,,1,0,370365,15.5,,Q
+366,0,3,"Adahl, Mr. Mauritz Nils Martin",male,30,0,0,C 7076,7.25,,S
+367,1,1,"Warren, Mrs. Frank Manley (Anna Sophia Atkinson)",female,60,1,0,110813,75.25,D37,C
+368,1,3,"Moussa, Mrs. (Mantoura Boulos)",female,,0,0,2626,7.2292,,C
+369,1,3,"Jermyn, Miss. Annie",female,,0,0,14313,7.75,,Q
+370,1,1,"Aubart, Mme. Leontine Pauline",female,24,0,0,PC 17477,69.3,B35,C
+371,1,1,"Harder, Mr. George Achilles",male,25,1,0,11765,55.4417,E50,C
+372,0,3,"Wiklund, Mr. Jakob Alfred",male,18,1,0,3101267,6.4958,,S
+373,0,3,"Beavan, Mr. William Thomas",male,19,0,0,323951,8.05,,S
+374,0,1,"Ringhini, Mr. Sante",male,22,0,0,PC 17760,135.6333,,C
+375,0,3,"Palsson, Miss. Stina Viola",female,3,3,1,349909,21.075,,S
+376,1,1,"Meyer, Mrs. Edgar Joseph (Leila Saks)",female,,1,0,PC 17604,82.1708,,C
+377,1,3,"Landergren, Miss. Aurora Adelia",female,22,0,0,C 7077,7.25,,S
+378,0,1,"Widener, Mr. Harry Elkins",male,27,0,2,113503,211.5,C82,C
+379,0,3,"Betros, Mr. Tannous",male,20,0,0,2648,4.0125,,C
+380,0,3,"Gustafsson, Mr. Karl Gideon",male,19,0,0,347069,7.775,,S
+381,1,1,"Bidois, Miss. Rosalie",female,42,0,0,PC 17757,227.525,,C
+382,1,3,"Nakid, Miss. Maria (""Mary"")",female,1,0,2,2653,15.7417,,C
+383,0,3,"Tikkanen, Mr. Juho",male,32,0,0,STON/O 2. 3101293,7.925,,S
+384,1,1,"Holverson, Mrs. Alexander Oskar (Mary Aline Towner)",female,35,1,0,113789,52,,S
+385,0,3,"Plotcharsky, Mr. Vasil",male,,0,0,349227,7.8958,,S
+386,0,2,"Davies, Mr. Charles Henry",male,18,0,0,S.O.C. 14879,73.5,,S
+387,0,3,"Goodwin, Master. Sidney Leonard",male,1,5,2,CA 2144,46.9,,S
+388,1,2,"Buss, Miss. Kate",female,36,0,0,27849,13,,S
+389,0,3,"Sadlier, Mr. Matthew",male,,0,0,367655,7.7292,,Q
+390,1,2,"Lehmann, Miss. Bertha",female,17,0,0,SC 1748,12,,C
+391,1,1,"Carter, Mr. William Ernest",male,36,1,2,113760,120,B96 B98,S
+392,1,3,"Jansson, Mr. Carl Olof",male,21,0,0,350034,7.7958,,S
+393,0,3,"Gustafsson, Mr. Johan Birger",male,28,2,0,3101277,7.925,,S
+394,1,1,"Newell, Miss. Marjorie",female,23,1,0,35273,113.275,D36,C
+395,1,3,"Sandstrom, Mrs. Hjalmar (Agnes Charlotta Bengtsson)",female,24,0,2,PP 9549,16.7,G6,S
+396,0,3,"Johansson, Mr. Erik",male,22,0,0,350052,7.7958,,S
+397,0,3,"Olsson, Miss. Elina",female,31,0,0,350407,7.8542,,S
+398,0,2,"McKane, Mr. Peter David",male,46,0,0,28403,26,,S
+399,0,2,"Pain, Dr. Alfred",male,23,0,0,244278,10.5,,S
+400,1,2,"Trout, Mrs. William H (Jessie L)",female,28,0,0,240929,12.65,,S
+401,1,3,"Niskanen, Mr. Juha",male,39,0,0,STON/O 2. 3101289,7.925,,S
+402,0,3,"Adams, Mr. John",male,26,0,0,341826,8.05,,S
+403,0,3,"Jussila, Miss. Mari Aina",female,21,1,0,4137,9.825,,S
+404,0,3,"Hakkarainen, Mr. Pekka Pietari",male,28,1,0,STON/O2. 3101279,15.85,,S
+405,0,3,"Oreskovic, Miss. Marija",female,20,0,0,315096,8.6625,,S
+406,0,2,"Gale, Mr. Shadrach",male,34,1,0,28664,21,,S
+407,0,3,"Widegren, Mr. Carl/Charles Peter",male,51,0,0,347064,7.75,,S
+408,1,2,"Richards, Master. William Rowe",male,3,1,1,29106,18.75,,S
+409,0,3,"Birkeland, Mr. Hans Martin Monsen",male,21,0,0,312992,7.775,,S
+410,0,3,"Lefebre, Miss. Ida",female,,3,1,4133,25.4667,,S
+411,0,3,"Sdycoff, Mr. Todor",male,,0,0,349222,7.8958,,S
+412,0,3,"Hart, Mr. Henry",male,,0,0,394140,6.8583,,Q
+413,1,1,"Minahan, Miss. Daisy E",female,33,1,0,19928,90,C78,Q
+414,0,2,"Cunningham, Mr. Alfred Fleming",male,,0,0,239853,0,,S
+415,1,3,"Sundman, Mr. Johan Julian",male,44,0,0,STON/O 2. 3101269,7.925,,S
+416,0,3,"Meek, Mrs. Thomas (Annie Louise Rowley)",female,,0,0,343095,8.05,,S
+417,1,2,"Drew, Mrs. James Vivian (Lulu Thorne Christian)",female,34,1,1,28220,32.5,,S
+418,1,2,"Silven, Miss. Lyyli Karoliina",female,18,0,2,250652,13,,S
+419,0,2,"Matthews, Mr. William John",male,30,0,0,28228,13,,S
+420,0,3,"Van Impe, Miss. Catharina",female,10,0,2,345773,24.15,,S
+421,0,3,"Gheorgheff, Mr. Stanio",male,,0,0,349254,7.8958,,C
+422,0,3,"Charters, Mr. David",male,21,0,0,A/5. 13032,7.7333,,Q
+423,0,3,"Zimmerman, Mr. Leo",male,29,0,0,315082,7.875,,S
+424,0,3,"Danbom, Mrs. Ernst Gilbert (Anna Sigrid Maria Brogren)",female,28,1,1,347080,14.4,,S
+425,0,3,"Rosblom, Mr. Viktor Richard",male,18,1,1,370129,20.2125,,S
+426,0,3,"Wiseman, Mr. Phillippe",male,,0,0,A/4. 34244,7.25,,S
+427,1,2,"Clarke, Mrs. Charles V (Ada Maria Winfield)",female,28,1,0,2003,26,,S
+428,1,2,"Phillips, Miss. Kate Florence (""Mrs Kate Louise Phillips Marshall"")",female,19,0,0,250655,26,,S
+429,0,3,"Flynn, Mr. James",male,,0,0,364851,7.75,,Q
+430,1,3,"Pickard, Mr. Berk (Berk Trembisky)",male,32,0,0,SOTON/O.Q. 392078,8.05,E10,S
+431,1,1,"Bjornstrom-Steffansson, Mr. Mauritz Hakan",male,28,0,0,110564,26.55,C52,S
+432,1,3,"Thorneycroft, Mrs. Percival (Florence Kate White)",female,,1,0,376564,16.1,,S
+433,1,2,"Louch, Mrs. Charles Alexander (Alice Adelaide Slow)",female,42,1,0,SC/AH 3085,26,,S
+434,0,3,"Kallio, Mr. Nikolai Erland",male,17,0,0,STON/O 2. 3101274,7.125,,S
+435,0,1,"Silvey, Mr. William Baird",male,50,1,0,13507,55.9,E44,S
+436,1,1,"Carter, Miss. Lucile Polk",female,14,1,2,113760,120,B96 B98,S
+437,0,3,"Ford, Miss. Doolina Margaret ""Daisy""",female,21,2,2,W./C. 6608,34.375,,S
+438,1,2,"Richards, Mrs. Sidney (Emily Hocking)",female,24,2,3,29106,18.75,,S
+439,0,1,"Fortune, Mr. Mark",male,64,1,4,19950,263,C23 C25 C27,S
+440,0,2,"Kvillner, Mr. Johan Henrik Johannesson",male,31,0,0,C.A. 18723,10.5,,S
+441,1,2,"Hart, Mrs. Benjamin (Esther Ada Bloomfield)",female,45,1,1,F.C.C. 13529,26.25,,S
+442,0,3,"Hampe, Mr. Leon",male,20,0,0,345769,9.5,,S
+443,0,3,"Petterson, Mr. Johan Emil",male,25,1,0,347076,7.775,,S
+444,1,2,"Reynaldo, Ms. Encarnacion",female,28,0,0,230434,13,,S
+445,1,3,"Johannesen-Bratthammer, Mr. Bernt",male,,0,0,65306,8.1125,,S
+446,1,1,"Dodge, Master. Washington",male,4,0,2,33638,81.8583,A34,S
+447,1,2,"Mellinger, Miss. Madeleine Violet",female,13,0,1,250644,19.5,,S
+448,1,1,"Seward, Mr. Frederic Kimber",male,34,0,0,113794,26.55,,S
+449,1,3,"Baclini, Miss. Marie Catherine",female,5,2,1,2666,19.2583,,C
+450,1,1,"Peuchen, Major. Arthur Godfrey",male,52,0,0,113786,30.5,C104,S
+451,0,2,"West, Mr. Edwy Arthur",male,36,1,2,C.A. 34651,27.75,,S
+452,0,3,"Hagland, Mr. Ingvald Olai Olsen",male,,1,0,65303,19.9667,,S
+453,0,1,"Foreman, Mr. Benjamin Laventall",male,30,0,0,113051,27.75,C111,C
+454,1,1,"Goldenberg, Mr. Samuel L",male,49,1,0,17453,89.1042,C92,C
+455,0,3,"Peduzzi, Mr. Joseph",male,,0,0,A/5 2817,8.05,,S
+456,1,3,"Jalsevac, Mr. Ivan",male,29,0,0,349240,7.8958,,C
+457,0,1,"Millet, Mr. Francis Davis",male,65,0,0,13509,26.55,E38,S
+458,1,1,"Kenyon, Mrs. Frederick R (Marion)",female,,1,0,17464,51.8625,D21,S
+459,1,2,"Toomey, Miss. Ellen",female,50,0,0,F.C.C. 13531,10.5,,S
+460,0,3,"O'Connor, Mr. Maurice",male,,0,0,371060,7.75,,Q
+461,1,1,"Anderson, Mr. Harry",male,48,0,0,19952,26.55,E12,S
+462,0,3,"Morley, Mr. William",male,34,0,0,364506,8.05,,S
+463,0,1,"Gee, Mr. Arthur H",male,47,0,0,111320,38.5,E63,S
+464,0,2,"Milling, Mr. Jacob Christian",male,48,0,0,234360,13,,S
+465,0,3,"Maisner, Mr. Simon",male,,0,0,A/S 2816,8.05,,S
+466,0,3,"Goncalves, Mr. Manuel Estanslas",male,38,0,0,SOTON/O.Q. 3101306,7.05,,S
+467,0,2,"Campbell, Mr. William",male,,0,0,239853,0,,S
+468,0,1,"Smart, Mr. John Montgomery",male,56,0,0,113792,26.55,,S
+469,0,3,"Scanlan, Mr. James",male,,0,0,36209,7.725,,Q
+470,1,3,"Baclini, Miss. Helene Barbara",female,0.75,2,1,2666,19.2583,,C
+471,0,3,"Keefe, Mr. Arthur",male,,0,0,323592,7.25,,S
+472,0,3,"Cacic, Mr. Luka",male,38,0,0,315089,8.6625,,S
+473,1,2,"West, Mrs. Edwy Arthur (Ada Mary Worth)",female,33,1,2,C.A. 34651,27.75,,S
+474,1,2,"Jerwan, Mrs. Amin S (Marie Marthe Thuillard)",female,23,0,0,SC/AH Basle 541,13.7917,D,C
+475,0,3,"Strandberg, Miss. Ida Sofia",female,22,0,0,7553,9.8375,,S
+476,0,1,"Clifford, Mr. George Quincy",male,,0,0,110465,52,A14,S
+477,0,2,"Renouf, Mr. Peter Henry",male,34,1,0,31027,21,,S
+478,0,3,"Braund, Mr. Lewis Richard",male,29,1,0,3460,7.0458,,S
+479,0,3,"Karlsson, Mr. Nils August",male,22,0,0,350060,7.5208,,S
+480,1,3,"Hirvonen, Miss. Hildur E",female,2,0,1,3101298,12.2875,,S
+481,0,3,"Goodwin, Master. Harold Victor",male,9,5,2,CA 2144,46.9,,S
+482,0,2,"Frost, Mr. Anthony Wood ""Archie""",male,,0,0,239854,0,,S
+483,0,3,"Rouse, Mr. Richard Henry",male,50,0,0,A/5 3594,8.05,,S
+484,1,3,"Turkula, Mrs. (Hedwig)",female,63,0,0,4134,9.5875,,S
+485,1,1,"Bishop, Mr. Dickinson H",male,25,1,0,11967,91.0792,B49,C
+486,0,3,"Lefebre, Miss. Jeannie",female,,3,1,4133,25.4667,,S
+487,1,1,"Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby)",female,35,1,0,19943,90,C93,S
+488,0,1,"Kent, Mr. Edward Austin",male,58,0,0,11771,29.7,B37,C
+489,0,3,"Somerton, Mr. Francis William",male,30,0,0,A.5. 18509,8.05,,S
+490,1,3,"Coutts, Master. Eden Leslie ""Neville""",male,9,1,1,C.A. 37671,15.9,,S
+491,0,3,"Hagland, Mr. Konrad Mathias Reiersen",male,,1,0,65304,19.9667,,S
+492,0,3,"Windelov, Mr. Einar",male,21,0,0,SOTON/OQ 3101317,7.25,,S
+493,0,1,"Molson, Mr. Harry Markland",male,55,0,0,113787,30.5,C30,S
+494,0,1,"Artagaveytia, Mr. Ramon",male,71,0,0,PC 17609,49.5042,,C
+495,0,3,"Stanley, Mr. Edward Roland",male,21,0,0,A/4 45380,8.05,,S
+496,0,3,"Yousseff, Mr. Gerious",male,,0,0,2627,14.4583,,C
+497,1,1,"Eustis, Miss. Elizabeth Mussey",female,54,1,0,36947,78.2667,D20,C
+498,0,3,"Shellard, Mr. Frederick William",male,,0,0,C.A. 6212,15.1,,S
+499,0,1,"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)",female,25,1,2,113781,151.55,C22 C26,S
+500,0,3,"Svensson, Mr. Olof",male,24,0,0,350035,7.7958,,S
+501,0,3,"Calic, Mr. Petar",male,17,0,0,315086,8.6625,,S
+502,0,3,"Canavan, Miss. Mary",female,21,0,0,364846,7.75,,Q
+503,0,3,"O'Sullivan, Miss. Bridget Mary",female,,0,0,330909,7.6292,,Q
+504,0,3,"Laitinen, Miss. Kristina Sofia",female,37,0,0,4135,9.5875,,S
+505,1,1,"Maioni, Miss. Roberta",female,16,0,0,110152,86.5,B79,S
+506,0,1,"Penasco y Castellana, Mr. Victor de Satode",male,18,1,0,PC 17758,108.9,C65,C
+507,1,2,"Quick, Mrs. Frederick Charles (Jane Richards)",female,33,0,2,26360,26,,S
+508,1,1,"Bradley, Mr. George (""George Arthur Brayton"")",male,,0,0,111427,26.55,,S
+509,0,3,"Olsen, Mr. Henry Margido",male,28,0,0,C 4001,22.525,,S
+510,1,3,"Lang, Mr. Fang",male,26,0,0,1601,56.4958,,S
+511,1,3,"Daly, Mr. Eugene Patrick",male,29,0,0,382651,7.75,,Q
+512,0,3,"Webber, Mr. James",male,,0,0,SOTON/OQ 3101316,8.05,,S
+513,1,1,"McGough, Mr. James Robert",male,36,0,0,PC 17473,26.2875,E25,S
+514,1,1,"Rothschild, Mrs. Martin (Elizabeth L. Barrett)",female,54,1,0,PC 17603,59.4,,C
+515,0,3,"Coleff, Mr. Satio",male,24,0,0,349209,7.4958,,S
+516,0,1,"Walker, Mr. William Anderson",male,47,0,0,36967,34.0208,D46,S
+517,1,2,"Lemore, Mrs. (Amelia Milley)",female,34,0,0,C.A. 34260,10.5,F33,S
+518,0,3,"Ryan, Mr. Patrick",male,,0,0,371110,24.15,,Q
+519,1,2,"Angle, Mrs. William A (Florence ""Mary"" Agnes Hughes)",female,36,1,0,226875,26,,S
+520,0,3,"Pavlovic, Mr. Stefo",male,32,0,0,349242,7.8958,,S
+521,1,1,"Perreault, Miss. Anne",female,30,0,0,12749,93.5,B73,S
+522,0,3,"Vovk, Mr. Janko",male,22,0,0,349252,7.8958,,S
+523,0,3,"Lahoud, Mr. Sarkis",male,,0,0,2624,7.225,,C
+524,1,1,"Hippach, Mrs. Louis Albert (Ida Sophia Fischer)",female,44,0,1,111361,57.9792,B18,C
+525,0,3,"Kassem, Mr. Fared",male,,0,0,2700,7.2292,,C
+526,0,3,"Farrell, Mr. James",male,40.5,0,0,367232,7.75,,Q
+527,1,2,"Ridsdale, Miss. Lucy",female,50,0,0,W./C. 14258,10.5,,S
+528,0,1,"Farthing, Mr. John",male,,0,0,PC 17483,221.7792,C95,S
+529,0,3,"Salonen, Mr. Johan Werner",male,39,0,0,3101296,7.925,,S
+530,0,2,"Hocking, Mr. Richard George",male,23,2,1,29104,11.5,,S
+531,1,2,"Quick, Miss. Phyllis May",female,2,1,1,26360,26,,S
+532,0,3,"Toufik, Mr. Nakli",male,,0,0,2641,7.2292,,C
+533,0,3,"Elias, Mr. Joseph Jr",male,17,1,1,2690,7.2292,,C
+534,1,3,"Peter, Mrs. Catherine (Catherine Rizk)",female,,0,2,2668,22.3583,,C
+535,0,3,"Cacic, Miss. Marija",female,30,0,0,315084,8.6625,,S
+536,1,2,"Hart, Miss. Eva Miriam",female,7,0,2,F.C.C. 13529,26.25,,S
+537,0,1,"Butt, Major. Archibald Willingham",male,45,0,0,113050,26.55,B38,S
+538,1,1,"LeRoy, Miss. Bertha",female,30,0,0,PC 17761,106.425,,C
+539,0,3,"Risien, Mr. Samuel Beard",male,,0,0,364498,14.5,,S
+540,1,1,"Frolicher, Miss. Hedwig Margaritha",female,22,0,2,13568,49.5,B39,C
+541,1,1,"Crosby, Miss. Harriet R",female,36,0,2,WE/P 5735,71,B22,S
+542,0,3,"Andersson, Miss. Ingeborg Constanzia",female,9,4,2,347082,31.275,,S
+543,0,3,"Andersson, Miss. Sigrid Elisabeth",female,11,4,2,347082,31.275,,S
+544,1,2,"Beane, Mr. Edward",male,32,1,0,2908,26,,S
+545,0,1,"Douglas, Mr. Walter Donald",male,50,1,0,PC 17761,106.425,C86,C
+546,0,1,"Nicholson, Mr. Arthur Ernest",male,64,0,0,693,26,,S
+547,1,2,"Beane, Mrs. Edward (Ethel Clarke)",female,19,1,0,2908,26,,S
+548,1,2,"Padro y Manent, Mr. Julian",male,,0,0,SC/PARIS 2146,13.8625,,C
+549,0,3,"Goldsmith, Mr. Frank John",male,33,1,1,363291,20.525,,S
+550,1,2,"Davies, Master. John Morgan Jr",male,8,1,1,C.A. 33112,36.75,,S
+551,1,1,"Thayer, Mr. John Borland Jr",male,17,0,2,17421,110.8833,C70,C
+552,0,2,"Sharp, Mr. Percival James R",male,27,0,0,244358,26,,S
+553,0,3,"O'Brien, Mr. Timothy",male,,0,0,330979,7.8292,,Q
+554,1,3,"Leeni, Mr. Fahim (""Philip Zenni"")",male,22,0,0,2620,7.225,,C
+555,1,3,"Ohman, Miss. Velin",female,22,0,0,347085,7.775,,S
+556,0,1,"Wright, Mr. George",male,62,0,0,113807,26.55,,S
+557,1,1,"Duff Gordon, Lady. (Lucille Christiana Sutherland) (""Mrs Morgan"")",female,48,1,0,11755,39.6,A16,C
+558,0,1,"Robbins, Mr. Victor",male,,0,0,PC 17757,227.525,,C
+559,1,1,"Taussig, Mrs. Emil (Tillie Mandelbaum)",female,39,1,1,110413,79.65,E67,S
+560,1,3,"de Messemaeker, Mrs. Guillaume Joseph (Emma)",female,36,1,0,345572,17.4,,S
+561,0,3,"Morrow, Mr. Thomas Rowan",male,,0,0,372622,7.75,,Q
+562,0,3,"Sivic, Mr. Husein",male,40,0,0,349251,7.8958,,S
+563,0,2,"Norman, Mr. Robert Douglas",male,28,0,0,218629,13.5,,S
+564,0,3,"Simmons, Mr. John",male,,0,0,SOTON/OQ 392082,8.05,,S
+565,0,3,"Meanwell, Miss. (Marion Ogden)",female,,0,0,SOTON/O.Q. 392087,8.05,,S
+566,0,3,"Davies, Mr. Alfred J",male,24,2,0,A/4 48871,24.15,,S
+567,0,3,"Stoytcheff, Mr. Ilia",male,19,0,0,349205,7.8958,,S
+568,0,3,"Palsson, Mrs. Nils (Alma Cornelia Berglund)",female,29,0,4,349909,21.075,,S
+569,0,3,"Doharr, Mr. Tannous",male,,0,0,2686,7.2292,,C
+570,1,3,"Jonsson, Mr. Carl",male,32,0,0,350417,7.8542,,S
+571,1,2,"Harris, Mr. George",male,62,0,0,S.W./PP 752,10.5,,S
+572,1,1,"Appleton, Mrs. Edward Dale (Charlotte Lamson)",female,53,2,0,11769,51.4792,C101,S
+573,1,1,"Flynn, Mr. John Irwin (""Irving"")",male,36,0,0,PC 17474,26.3875,E25,S
+574,1,3,"Kelly, Miss. Mary",female,,0,0,14312,7.75,,Q
+575,0,3,"Rush, Mr. Alfred George John",male,16,0,0,A/4. 20589,8.05,,S
+576,0,3,"Patchett, Mr. George",male,19,0,0,358585,14.5,,S
+577,1,2,"Garside, Miss. Ethel",female,34,0,0,243880,13,,S
+578,1,1,"Silvey, Mrs. William Baird (Alice Munger)",female,39,1,0,13507,55.9,E44,S
+579,0,3,"Caram, Mrs. Joseph (Maria Elias)",female,,1,0,2689,14.4583,,C
+580,1,3,"Jussila, Mr. Eiriik",male,32,0,0,STON/O 2. 3101286,7.925,,S
+581,1,2,"Christy, Miss. Julie Rachel",female,25,1,1,237789,30,,S
+582,1,1,"Thayer, Mrs. John Borland (Marian Longstreth Morris)",female,39,1,1,17421,110.8833,C68,C
+583,0,2,"Downton, Mr. William James",male,54,0,0,28403,26,,S
+584,0,1,"Ross, Mr. John Hugo",male,36,0,0,13049,40.125,A10,C
+585,0,3,"Paulner, Mr. Uscher",male,,0,0,3411,8.7125,,C
+586,1,1,"Taussig, Miss. Ruth",female,18,0,2,110413,79.65,E68,S
+587,0,2,"Jarvis, Mr. John Denzil",male,47,0,0,237565,15,,S
+588,1,1,"Frolicher-Stehli, Mr. Maxmillian",male,60,1,1,13567,79.2,B41,C
+589,0,3,"Gilinski, Mr. Eliezer",male,22,0,0,14973,8.05,,S
+590,0,3,"Murdlin, Mr. Joseph",male,,0,0,A./5. 3235,8.05,,S
+591,0,3,"Rintamaki, Mr. Matti",male,35,0,0,STON/O 2. 3101273,7.125,,S
+592,1,1,"Stephenson, Mrs. Walter Bertram (Martha Eustis)",female,52,1,0,36947,78.2667,D20,C
+593,0,3,"Elsbury, Mr. William James",male,47,0,0,A/5 3902,7.25,,S
+594,0,3,"Bourke, Miss. Mary",female,,0,2,364848,7.75,,Q
+595,0,2,"Chapman, Mr. John Henry",male,37,1,0,SC/AH 29037,26,,S
+596,0,3,"Van Impe, Mr. Jean Baptiste",male,36,1,1,345773,24.15,,S
+597,1,2,"Leitch, Miss. Jessie Wills",female,,0,0,248727,33,,S
+598,0,3,"Johnson, Mr. Alfred",male,49,0,0,LINE,0,,S
+599,0,3,"Boulos, Mr. Hanna",male,,0,0,2664,7.225,,C
+600,1,1,"Duff Gordon, Sir. Cosmo Edmund (""Mr Morgan"")",male,49,1,0,PC 17485,56.9292,A20,C
+601,1,2,"Jacobsohn, Mrs. Sidney Samuel (Amy Frances Christy)",female,24,2,1,243847,27,,S
+602,0,3,"Slabenoff, Mr. Petco",male,,0,0,349214,7.8958,,S
+603,0,1,"Harrington, Mr. Charles H",male,,0,0,113796,42.4,,S
+604,0,3,"Torber, Mr. Ernst William",male,44,0,0,364511,8.05,,S
+605,1,1,"Homer, Mr. Harry (""Mr E Haven"")",male,35,0,0,111426,26.55,,C
+606,0,3,"Lindell, Mr. Edvard Bengtsson",male,36,1,0,349910,15.55,,S
+607,0,3,"Karaic, Mr. Milan",male,30,0,0,349246,7.8958,,S
+608,1,1,"Daniel, Mr. Robert Williams",male,27,0,0,113804,30.5,,S
+609,1,2,"Laroche, Mrs. Joseph (Juliette Marie Louise Lafargue)",female,22,1,2,SC/Paris 2123,41.5792,,C
+610,1,1,"Shutes, Miss. Elizabeth W",female,40,0,0,PC 17582,153.4625,C125,S
+611,0,3,"Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren)",female,39,1,5,347082,31.275,,S
+612,0,3,"Jardin, Mr. Jose Neto",male,,0,0,SOTON/O.Q. 3101305,7.05,,S
+613,1,3,"Murphy, Miss. Margaret Jane",female,,1,0,367230,15.5,,Q
+614,0,3,"Horgan, Mr. John",male,,0,0,370377,7.75,,Q
+615,0,3,"Brocklebank, Mr. William Alfred",male,35,0,0,364512,8.05,,S
+616,1,2,"Herman, Miss. Alice",female,24,1,2,220845,65,,S
+617,0,3,"Danbom, Mr. Ernst Gilbert",male,34,1,1,347080,14.4,,S
+618,0,3,"Lobb, Mrs. William Arthur (Cordelia K Stanlick)",female,26,1,0,A/5. 3336,16.1,,S
+619,1,2,"Becker, Miss. Marion Louise",female,4,2,1,230136,39,F4,S
+620,0,2,"Gavey, Mr. Lawrence",male,26,0,0,31028,10.5,,S
+621,0,3,"Yasbeck, Mr. Antoni",male,27,1,0,2659,14.4542,,C
+622,1,1,"Kimball, Mr. Edwin Nelson Jr",male,42,1,0,11753,52.5542,D19,S
+623,1,3,"Nakid, Mr. Sahid",male,20,1,1,2653,15.7417,,C
+624,0,3,"Hansen, Mr. Henry Damsgaard",male,21,0,0,350029,7.8542,,S
+625,0,3,"Bowen, Mr. David John ""Dai""",male,21,0,0,54636,16.1,,S
+626,0,1,"Sutton, Mr. Frederick",male,61,0,0,36963,32.3208,D50,S
+627,0,2,"Kirkland, Rev. Charles Leonard",male,57,0,0,219533,12.35,,Q
+628,1,1,"Longley, Miss. Gretchen Fiske",female,21,0,0,13502,77.9583,D9,S
+629,0,3,"Bostandyeff, Mr. Guentcho",male,26,0,0,349224,7.8958,,S
+630,0,3,"O'Connell, Mr. Patrick D",male,,0,0,334912,7.7333,,Q
+631,1,1,"Barkworth, Mr. Algernon Henry Wilson",male,80,0,0,27042,30,A23,S
+632,0,3,"Lundahl, Mr. Johan Svensson",male,51,0,0,347743,7.0542,,S
+633,1,1,"Stahelin-Maeglin, Dr. Max",male,32,0,0,13214,30.5,B50,C
+634,0,1,"Parr, Mr. William Henry Marsh",male,,0,0,112052,0,,S
+635,0,3,"Skoog, Miss. Mabel",female,9,3,2,347088,27.9,,S
+636,1,2,"Davis, Miss. Mary",female,28,0,0,237668,13,,S
+637,0,3,"Leinonen, Mr. Antti Gustaf",male,32,0,0,STON/O 2. 3101292,7.925,,S
+638,0,2,"Collyer, Mr. Harvey",male,31,1,1,C.A. 31921,26.25,,S
+639,0,3,"Panula, Mrs. Juha (Maria Emilia Ojala)",female,41,0,5,3101295,39.6875,,S
+640,0,3,"Thorneycroft, Mr. Percival",male,,1,0,376564,16.1,,S
+641,0,3,"Jensen, Mr. Hans Peder",male,20,0,0,350050,7.8542,,S
+642,1,1,"Sagesser, Mlle. Emma",female,24,0,0,PC 17477,69.3,B35,C
+643,0,3,"Skoog, Miss. Margit Elizabeth",female,2,3,2,347088,27.9,,S
+644,1,3,"Foo, Mr. Choong",male,,0,0,1601,56.4958,,S
+645,1,3,"Baclini, Miss. Eugenie",female,0.75,2,1,2666,19.2583,,C
+646,1,1,"Harper, Mr. Henry Sleeper",male,48,1,0,PC 17572,76.7292,D33,C
+647,0,3,"Cor, Mr. Liudevit",male,19,0,0,349231,7.8958,,S
+648,1,1,"Simonius-Blumer, Col. Oberst Alfons",male,56,0,0,13213,35.5,A26,C
+649,0,3,"Willey, Mr. Edward",male,,0,0,S.O./P.P. 751,7.55,,S
+650,1,3,"Stanley, Miss. Amy Zillah Elsie",female,23,0,0,CA. 2314,7.55,,S
+651,0,3,"Mitkoff, Mr. Mito",male,,0,0,349221,7.8958,,S
+652,1,2,"Doling, Miss. Elsie",female,18,0,1,231919,23,,S
+653,0,3,"Kalvik, Mr. Johannes Halvorsen",male,21,0,0,8475,8.4333,,S
+654,1,3,"O'Leary, Miss. Hanora ""Norah""",female,,0,0,330919,7.8292,,Q
+655,0,3,"Hegarty, Miss. Hanora ""Nora""",female,18,0,0,365226,6.75,,Q
+656,0,2,"Hickman, Mr. Leonard Mark",male,24,2,0,S.O.C. 14879,73.5,,S
+657,0,3,"Radeff, Mr. Alexander",male,,0,0,349223,7.8958,,S
+658,0,3,"Bourke, Mrs. John (Catherine)",female,32,1,1,364849,15.5,,Q
+659,0,2,"Eitemiller, Mr. George Floyd",male,23,0,0,29751,13,,S
+660,0,1,"Newell, Mr. Arthur Webster",male,58,0,2,35273,113.275,D48,C
+661,1,1,"Frauenthal, Dr. Henry William",male,50,2,0,PC 17611,133.65,,S
+662,0,3,"Badt, Mr. Mohamed",male,40,0,0,2623,7.225,,C
+663,0,1,"Colley, Mr. Edward Pomeroy",male,47,0,0,5727,25.5875,E58,S
+664,0,3,"Coleff, Mr. Peju",male,36,0,0,349210,7.4958,,S
+665,1,3,"Lindqvist, Mr. Eino William",male,20,1,0,STON/O 2. 3101285,7.925,,S
+666,0,2,"Hickman, Mr. Lewis",male,32,2,0,S.O.C. 14879,73.5,,S
+667,0,2,"Butler, Mr. Reginald Fenton",male,25,0,0,234686,13,,S
+668,0,3,"Rommetvedt, Mr. Knud Paust",male,,0,0,312993,7.775,,S
+669,0,3,"Cook, Mr. Jacob",male,43,0,0,A/5 3536,8.05,,S
+670,1,1,"Taylor, Mrs. Elmer Zebley (Juliet Cummins Wright)",female,,1,0,19996,52,C126,S
+671,1,2,"Brown, Mrs. Thomas William Solomon (Elizabeth Catherine Ford)",female,40,1,1,29750,39,,S
+672,0,1,"Davidson, Mr. Thornton",male,31,1,0,F.C. 12750,52,B71,S
+673,0,2,"Mitchell, Mr. Henry Michael",male,70,0,0,C.A. 24580,10.5,,S
+674,1,2,"Wilhelms, Mr. Charles",male,31,0,0,244270,13,,S
+675,0,2,"Watson, Mr. Ennis Hastings",male,,0,0,239856,0,,S
+676,0,3,"Edvardsson, Mr. Gustaf Hjalmar",male,18,0,0,349912,7.775,,S
+677,0,3,"Sawyer, Mr. Frederick Charles",male,24.5,0,0,342826,8.05,,S
+678,1,3,"Turja, Miss. Anna Sofia",female,18,0,0,4138,9.8417,,S
+679,0,3,"Goodwin, Mrs. Frederick (Augusta Tyler)",female,43,1,6,CA 2144,46.9,,S
+680,1,1,"Cardeza, Mr. Thomas Drake Martinez",male,36,0,1,PC 17755,512.3292,B51 B53 B55,C
+681,0,3,"Peters, Miss. Katie",female,,0,0,330935,8.1375,,Q
+682,1,1,"Hassab, Mr. Hammad",male,27,0,0,PC 17572,76.7292,D49,C
+683,0,3,"Olsvigen, Mr. Thor Anderson",male,20,0,0,6563,9.225,,S
+684,0,3,"Goodwin, Mr. Charles Edward",male,14,5,2,CA 2144,46.9,,S
+685,0,2,"Brown, Mr. Thomas William Solomon",male,60,1,1,29750,39,,S
+686,0,2,"Laroche, Mr. Joseph Philippe Lemercier",male,25,1,2,SC/Paris 2123,41.5792,,C
+687,0,3,"Panula, Mr. Jaako Arnold",male,14,4,1,3101295,39.6875,,S
+688,0,3,"Dakic, Mr. Branko",male,19,0,0,349228,10.1708,,S
+689,0,3,"Fischer, Mr. Eberhard Thelander",male,18,0,0,350036,7.7958,,S
+690,1,1,"Madill, Miss. Georgette Alexandra",female,15,0,1,24160,211.3375,B5,S
+691,1,1,"Dick, Mr. Albert Adrian",male,31,1,0,17474,57,B20,S
+692,1,3,"Karun, Miss. Manca",female,4,0,1,349256,13.4167,,C
+693,1,3,"Lam, Mr. Ali",male,,0,0,1601,56.4958,,S
+694,0,3,"Saad, Mr. Khalil",male,25,0,0,2672,7.225,,C
+695,0,1,"Weir, Col. John",male,60,0,0,113800,26.55,,S
+696,0,2,"Chapman, Mr. Charles Henry",male,52,0,0,248731,13.5,,S
+697,0,3,"Kelly, Mr. James",male,44,0,0,363592,8.05,,S
+698,1,3,"Mullens, Miss. Katherine ""Katie""",female,,0,0,35852,7.7333,,Q
+699,0,1,"Thayer, Mr. John Borland",male,49,1,1,17421,110.8833,C68,C
+700,0,3,"Humblen, Mr. Adolf Mathias Nicolai Olsen",male,42,0,0,348121,7.65,F G63,S
+701,1,1,"Astor, Mrs. John Jacob (Madeleine Talmadge Force)",female,18,1,0,PC 17757,227.525,C62 C64,C
+702,1,1,"Silverthorne, Mr. Spencer Victor",male,35,0,0,PC 17475,26.2875,E24,S
+703,0,3,"Barbara, Miss. Saiide",female,18,0,1,2691,14.4542,,C
+704,0,3,"Gallagher, Mr. Martin",male,25,0,0,36864,7.7417,,Q
+705,0,3,"Hansen, Mr. Henrik Juul",male,26,1,0,350025,7.8542,,S
+706,0,2,"Morley, Mr. Henry Samuel (""Mr Henry Marshall"")",male,39,0,0,250655,26,,S
+707,1,2,"Kelly, Mrs. Florence ""Fannie""",female,45,0,0,223596,13.5,,S
+708,1,1,"Calderhead, Mr. Edward Pennington",male,42,0,0,PC 17476,26.2875,E24,S
+709,1,1,"Cleaver, Miss. Alice",female,22,0,0,113781,151.55,,S
+710,1,3,"Moubarek, Master. Halim Gonios (""William George"")",male,,1,1,2661,15.2458,,C
+711,1,1,"Mayne, Mlle. Berthe Antonine (""Mrs de Villiers"")",female,24,0,0,PC 17482,49.5042,C90,C
+712,0,1,"Klaber, Mr. Herman",male,,0,0,113028,26.55,C124,S
+713,1,1,"Taylor, Mr. Elmer Zebley",male,48,1,0,19996,52,C126,S
+714,0,3,"Larsson, Mr. August Viktor",male,29,0,0,7545,9.4833,,S
+715,0,2,"Greenberg, Mr. Samuel",male,52,0,0,250647,13,,S
+716,0,3,"Soholt, Mr. Peter Andreas Lauritz Andersen",male,19,0,0,348124,7.65,F G73,S
+717,1,1,"Endres, Miss. Caroline Louise",female,38,0,0,PC 17757,227.525,C45,C
+718,1,2,"Troutt, Miss. Edwina Celia ""Winnie""",female,27,0,0,34218,10.5,E101,S
+719,0,3,"McEvoy, Mr. Michael",male,,0,0,36568,15.5,,Q
+720,0,3,"Johnson, Mr. Malkolm Joackim",male,33,0,0,347062,7.775,,S
+721,1,2,"Harper, Miss. Annie Jessie ""Nina""",female,6,0,1,248727,33,,S
+722,0,3,"Jensen, Mr. Svend Lauritz",male,17,1,0,350048,7.0542,,S
+723,0,2,"Gillespie, Mr. William Henry",male,34,0,0,12233,13,,S
+724,0,2,"Hodges, Mr. Henry Price",male,50,0,0,250643,13,,S
+725,1,1,"Chambers, Mr. Norman Campbell",male,27,1,0,113806,53.1,E8,S
+726,0,3,"Oreskovic, Mr. Luka",male,20,0,0,315094,8.6625,,S
+727,1,2,"Renouf, Mrs. Peter Henry (Lillian Jefferys)",female,30,3,0,31027,21,,S
+728,1,3,"Mannion, Miss. Margareth",female,,0,0,36866,7.7375,,Q
+729,0,2,"Bryhl, Mr. Kurt Arnold Gottfrid",male,25,1,0,236853,26,,S
+730,0,3,"Ilmakangas, Miss. Pieta Sofia",female,25,1,0,STON/O2. 3101271,7.925,,S
+731,1,1,"Allen, Miss. Elisabeth Walton",female,29,0,0,24160,211.3375,B5,S
+732,0,3,"Hassan, Mr. Houssein G N",male,11,0,0,2699,18.7875,,C
+733,0,2,"Knight, Mr. Robert J",male,,0,0,239855,0,,S
+734,0,2,"Berriman, Mr. William John",male,23,0,0,28425,13,,S
+735,0,2,"Troupiansky, Mr. Moses Aaron",male,23,0,0,233639,13,,S
+736,0,3,"Williams, Mr. Leslie",male,28.5,0,0,54636,16.1,,S
+737,0,3,"Ford, Mrs. Edward (Margaret Ann Watson)",female,48,1,3,W./C. 6608,34.375,,S
+738,1,1,"Lesurer, Mr. Gustave J",male,35,0,0,PC 17755,512.3292,B101,C
+739,0,3,"Ivanoff, Mr. Kanio",male,,0,0,349201,7.8958,,S
+740,0,3,"Nankoff, Mr. Minko",male,,0,0,349218,7.8958,,S
+741,1,1,"Hawksford, Mr. Walter James",male,,0,0,16988,30,D45,S
+742,0,1,"Cavendish, Mr. Tyrell William",male,36,1,0,19877,78.85,C46,S
+743,1,1,"Ryerson, Miss. Susan Parker ""Suzette""",female,21,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+744,0,3,"McNamee, Mr. Neal",male,24,1,0,376566,16.1,,S
+745,1,3,"Stranden, Mr. Juho",male,31,0,0,STON/O 2. 3101288,7.925,,S
+746,0,1,"Crosby, Capt. Edward Gifford",male,70,1,1,WE/P 5735,71,B22,S
+747,0,3,"Abbott, Mr. Rossmore Edward",male,16,1,1,C.A. 2673,20.25,,S
+748,1,2,"Sinkkonen, Miss. Anna",female,30,0,0,250648,13,,S
+749,0,1,"Marvin, Mr. Daniel Warner",male,19,1,0,113773,53.1,D30,S
+750,0,3,"Connaghton, Mr. Michael",male,31,0,0,335097,7.75,,Q
+751,1,2,"Wells, Miss. Joan",female,4,1,1,29103,23,,S
+752,1,3,"Moor, Master. Meier",male,6,0,1,392096,12.475,E121,S
+753,0,3,"Vande Velde, Mr. Johannes Joseph",male,33,0,0,345780,9.5,,S
+754,0,3,"Jonkoff, Mr. Lalio",male,23,0,0,349204,7.8958,,S
+755,1,2,"Herman, Mrs. Samuel (Jane Laver)",female,48,1,2,220845,65,,S
+756,1,2,"Hamalainen, Master. Viljo",male,0.67,1,1,250649,14.5,,S
+757,0,3,"Carlsson, Mr. August Sigfrid",male,28,0,0,350042,7.7958,,S
+758,0,2,"Bailey, Mr. Percy Andrew",male,18,0,0,29108,11.5,,S
+759,0,3,"Theobald, Mr. Thomas Leonard",male,34,0,0,363294,8.05,,S
+760,1,1,"Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)",female,33,0,0,110152,86.5,B77,S
+761,0,3,"Garfirth, Mr. John",male,,0,0,358585,14.5,,S
+762,0,3,"Nirva, Mr. Iisakki Antino Aijo",male,41,0,0,SOTON/O2 3101272,7.125,,S
+763,1,3,"Barah, Mr. Hanna Assi",male,20,0,0,2663,7.2292,,C
+764,1,1,"Carter, Mrs. William Ernest (Lucile Polk)",female,36,1,2,113760,120,B96 B98,S
+765,0,3,"Eklund, Mr. Hans Linus",male,16,0,0,347074,7.775,,S
+766,1,1,"Hogeboom, Mrs. John C (Anna Andrews)",female,51,1,0,13502,77.9583,D11,S
+767,0,1,"Brewe, Dr. Arthur Jackson",male,,0,0,112379,39.6,,C
+768,0,3,"Mangan, Miss. Mary",female,30.5,0,0,364850,7.75,,Q
+769,0,3,"Moran, Mr. Daniel J",male,,1,0,371110,24.15,,Q
+770,0,3,"Gronnestad, Mr. Daniel Danielsen",male,32,0,0,8471,8.3625,,S
+771,0,3,"Lievens, Mr. Rene Aime",male,24,0,0,345781,9.5,,S
+772,0,3,"Jensen, Mr. Niels Peder",male,48,0,0,350047,7.8542,,S
+773,0,2,"Mack, Mrs. (Mary)",female,57,0,0,S.O./P.P. 3,10.5,E77,S
+774,0,3,"Elias, Mr. Dibo",male,,0,0,2674,7.225,,C
+775,1,2,"Hocking, Mrs. Elizabeth (Eliza Needs)",female,54,1,3,29105,23,,S
+776,0,3,"Myhrman, Mr. Pehr Fabian Oliver Malkolm",male,18,0,0,347078,7.75,,S
+777,0,3,"Tobin, Mr. Roger",male,,0,0,383121,7.75,F38,Q
+778,1,3,"Emanuel, Miss. Virginia Ethel",female,5,0,0,364516,12.475,,S
+779,0,3,"Kilgannon, Mr. Thomas J",male,,0,0,36865,7.7375,,Q
+780,1,1,"Robert, Mrs. Edward Scott (Elisabeth Walton McMillan)",female,43,0,1,24160,211.3375,B3,S
+781,1,3,"Ayoub, Miss. Banoura",female,13,0,0,2687,7.2292,,C
+782,1,1,"Dick, Mrs. Albert Adrian (Vera Gillespie)",female,17,1,0,17474,57,B20,S
+783,0,1,"Long, Mr. Milton Clyde",male,29,0,0,113501,30,D6,S
+784,0,3,"Johnston, Mr. Andrew G",male,,1,2,W./C. 6607,23.45,,S
+785,0,3,"Ali, Mr. William",male,25,0,0,SOTON/O.Q. 3101312,7.05,,S
+786,0,3,"Harmer, Mr. Abraham (David Lishin)",male,25,0,0,374887,7.25,,S
+787,1,3,"Sjoblom, Miss. Anna Sofia",female,18,0,0,3101265,7.4958,,S
+788,0,3,"Rice, Master. George Hugh",male,8,4,1,382652,29.125,,Q
+789,1,3,"Dean, Master. Bertram Vere",male,1,1,2,C.A. 2315,20.575,,S
+790,0,1,"Guggenheim, Mr. Benjamin",male,46,0,0,PC 17593,79.2,B82 B84,C
+791,0,3,"Keane, Mr. Andrew ""Andy""",male,,0,0,12460,7.75,,Q
+792,0,2,"Gaskell, Mr. Alfred",male,16,0,0,239865,26,,S
+793,0,3,"Sage, Miss. Stella Anna",female,,8,2,CA. 2343,69.55,,S
+794,0,1,"Hoyt, Mr. William Fisher",male,,0,0,PC 17600,30.6958,,C
+795,0,3,"Dantcheff, Mr. Ristiu",male,25,0,0,349203,7.8958,,S
+796,0,2,"Otter, Mr. Richard",male,39,0,0,28213,13,,S
+797,1,1,"Leader, Dr. Alice (Farnham)",female,49,0,0,17465,25.9292,D17,S
+798,1,3,"Osman, Mrs. Mara",female,31,0,0,349244,8.6833,,S
+799,0,3,"Ibrahim Shawah, Mr. Yousseff",male,30,0,0,2685,7.2292,,C
+800,0,3,"Van Impe, Mrs. Jean Baptiste (Rosalie Paula Govaert)",female,30,1,1,345773,24.15,,S
+801,0,2,"Ponesell, Mr. Martin",male,34,0,0,250647,13,,S
+802,1,2,"Collyer, Mrs. Harvey (Charlotte Annie Tate)",female,31,1,1,C.A. 31921,26.25,,S
+803,1,1,"Carter, Master. William Thornton II",male,11,1,2,113760,120,B96 B98,S
+804,1,3,"Thomas, Master. Assad Alexander",male,0.42,0,1,2625,8.5167,,C
+805,1,3,"Hedman, Mr. Oskar Arvid",male,27,0,0,347089,6.975,,S
+806,0,3,"Johansson, Mr. Karl Johan",male,31,0,0,347063,7.775,,S
+807,0,1,"Andrews, Mr. Thomas Jr",male,39,0,0,112050,0,A36,S
+808,0,3,"Pettersson, Miss. Ellen Natalia",female,18,0,0,347087,7.775,,S
+809,0,2,"Meyer, Mr. August",male,39,0,0,248723,13,,S
+810,1,1,"Chambers, Mrs. Norman Campbell (Bertha Griggs)",female,33,1,0,113806,53.1,E8,S
+811,0,3,"Alexander, Mr. William",male,26,0,0,3474,7.8875,,S
+812,0,3,"Lester, Mr. James",male,39,0,0,A/4 48871,24.15,,S
+813,0,2,"Slemen, Mr. Richard James",male,35,0,0,28206,10.5,,S
+814,0,3,"Andersson, Miss. Ebba Iris Alfrida",female,6,4,2,347082,31.275,,S
+815,0,3,"Tomlin, Mr. Ernest Portage",male,30.5,0,0,364499,8.05,,S
+816,0,1,"Fry, Mr. Richard",male,,0,0,112058,0,B102,S
+817,0,3,"Heininen, Miss. Wendla Maria",female,23,0,0,STON/O2. 3101290,7.925,,S
+818,0,2,"Mallet, Mr. Albert",male,31,1,1,S.C./PARIS 2079,37.0042,,C
+819,0,3,"Holm, Mr. John Fredrik Alexander",male,43,0,0,C 7075,6.45,,S
+820,0,3,"Skoog, Master. Karl Thorsten",male,10,3,2,347088,27.9,,S
+821,1,1,"Hays, Mrs. Charles Melville (Clara Jennings Gregg)",female,52,1,1,12749,93.5,B69,S
+822,1,3,"Lulic, Mr. Nikola",male,27,0,0,315098,8.6625,,S
+823,0,1,"Reuchlin, Jonkheer. John George",male,38,0,0,19972,0,,S
+824,1,3,"Moor, Mrs. (Beila)",female,27,0,1,392096,12.475,E121,S
+825,0,3,"Panula, Master. Urho Abraham",male,2,4,1,3101295,39.6875,,S
+826,0,3,"Flynn, Mr. John",male,,0,0,368323,6.95,,Q
+827,0,3,"Lam, Mr. Len",male,,0,0,1601,56.4958,,S
+828,1,2,"Mallet, Master. Andre",male,1,0,2,S.C./PARIS 2079,37.0042,,C
+829,1,3,"McCormack, Mr. Thomas Joseph",male,,0,0,367228,7.75,,Q
+830,1,1,"Stone, Mrs. George Nelson (Martha Evelyn)",female,62,0,0,113572,80,B28,
+831,1,3,"Yasbeck, Mrs. Antoni (Selini Alexander)",female,15,1,0,2659,14.4542,,C
+832,1,2,"Richards, Master. George Sibley",male,0.83,1,1,29106,18.75,,S
+833,0,3,"Saad, Mr. Amin",male,,0,0,2671,7.2292,,C
+834,0,3,"Augustsson, Mr. Albert",male,23,0,0,347468,7.8542,,S
+835,0,3,"Allum, Mr. Owen George",male,18,0,0,2223,8.3,,S
+836,1,1,"Compton, Miss. Sara Rebecca",female,39,1,1,PC 17756,83.1583,E49,C
+837,0,3,"Pasic, Mr. Jakob",male,21,0,0,315097,8.6625,,S
+838,0,3,"Sirota, Mr. Maurice",male,,0,0,392092,8.05,,S
+839,1,3,"Chip, Mr. Chang",male,32,0,0,1601,56.4958,,S
+840,1,1,"Marechal, Mr. Pierre",male,,0,0,11774,29.7,C47,C
+841,0,3,"Alhomaki, Mr. Ilmari Rudolf",male,20,0,0,SOTON/O2 3101287,7.925,,S
+842,0,2,"Mudd, Mr. Thomas Charles",male,16,0,0,S.O./P.P. 3,10.5,,S
+843,1,1,"Serepeca, Miss. Augusta",female,30,0,0,113798,31,,C
+844,0,3,"Lemberopolous, Mr. Peter L",male,34.5,0,0,2683,6.4375,,C
+845,0,3,"Culumovic, Mr. Jeso",male,17,0,0,315090,8.6625,,S
+846,0,3,"Abbing, Mr. Anthony",male,42,0,0,C.A. 5547,7.55,,S
+847,0,3,"Sage, Mr. Douglas Bullen",male,,8,2,CA. 2343,69.55,,S
+848,0,3,"Markoff, Mr. Marin",male,35,0,0,349213,7.8958,,C
+849,0,2,"Harper, Rev. John",male,28,0,1,248727,33,,S
+850,1,1,"Goldenberg, Mrs. Samuel L (Edwiga Grabowska)",female,,1,0,17453,89.1042,C92,C
+851,0,3,"Andersson, Master. Sigvard Harald Elias",male,4,4,2,347082,31.275,,S
+852,0,3,"Svensson, Mr. Johan",male,74,0,0,347060,7.775,,S
+853,0,3,"Boulos, Miss. Nourelain",female,9,1,1,2678,15.2458,,C
+854,1,1,"Lines, Miss. Mary Conover",female,16,0,1,PC 17592,39.4,D28,S
+855,0,2,"Carter, Mrs. Ernest Courtenay (Lilian Hughes)",female,44,1,0,244252,26,,S
+856,1,3,"Aks, Mrs. Sam (Leah Rosen)",female,18,0,1,392091,9.35,,S
+857,1,1,"Wick, Mrs. George Dennick (Mary Hitchcock)",female,45,1,1,36928,164.8667,,S
+858,1,1,"Daly, Mr. Peter Denis ",male,51,0,0,113055,26.55,E17,S
+859,1,3,"Baclini, Mrs. Solomon (Latifa Qurban)",female,24,0,3,2666,19.2583,,C
+860,0,3,"Razi, Mr. Raihed",male,,0,0,2629,7.2292,,C
+861,0,3,"Hansen, Mr. Claus Peter",male,41,2,0,350026,14.1083,,S
+862,0,2,"Giles, Mr. Frederick Edward",male,21,1,0,28134,11.5,,S
+863,1,1,"Swift, Mrs. Frederick Joel (Margaret Welles Barron)",female,48,0,0,17466,25.9292,D17,S
+864,0,3,"Sage, Miss. Dorothy Edith ""Dolly""",female,,8,2,CA. 2343,69.55,,S
+865,0,2,"Gill, Mr. John William",male,24,0,0,233866,13,,S
+866,1,2,"Bystrom, Mrs. (Karolina)",female,42,0,0,236852,13,,S
+867,1,2,"Duran y More, Miss. Asuncion",female,27,1,0,SC/PARIS 2149,13.8583,,C
+868,0,1,"Roebling, Mr. Washington Augustus II",male,31,0,0,PC 17590,50.4958,A24,S
+869,0,3,"van Melkebeke, Mr. Philemon",male,,0,0,345777,9.5,,S
+870,1,3,"Johnson, Master. Harold Theodor",male,4,1,1,347742,11.1333,,S
+871,0,3,"Balkic, Mr. Cerin",male,26,0,0,349248,7.8958,,S
+872,1,1,"Beckwith, Mrs. Richard Leonard (Sallie Monypeny)",female,47,1,1,11751,52.5542,D35,S
+873,0,1,"Carlsson, Mr. Frans Olof",male,33,0,0,695,5,B51 B53 B55,S
+874,0,3,"Vander Cruyssen, Mr. Victor",male,47,0,0,345765,9,,S
+875,1,2,"Abelson, Mrs. Samuel (Hannah Wizosky)",female,28,1,0,P/PP 3381,24,,C
+876,1,3,"Najib, Miss. Adele Kiamie ""Jane""",female,15,0,0,2667,7.225,,C
+877,0,3,"Gustafsson, Mr. Alfred Ossian",male,20,0,0,7534,9.8458,,S
+878,0,3,"Petroff, Mr. Nedelio",male,19,0,0,349212,7.8958,,S
+879,0,3,"Laleff, Mr. Kristo",male,,0,0,349217,7.8958,,S
+880,1,1,"Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)",female,56,0,1,11767,83.1583,C50,C
+881,1,2,"Shelley, Mrs. William (Imanita Parrish Hall)",female,25,0,1,230433,26,,S
+882,0,3,"Markun, Mr. Johann",male,33,0,0,349257,7.8958,,S
+883,0,3,"Dahlberg, Miss. Gerda Ulrika",female,22,0,0,7552,10.5167,,S
+884,0,2,"Banfield, Mr. Frederick James",male,28,0,0,C.A./SOTON 34068,10.5,,S
+885,0,3,"Sutehall, Mr. Henry Jr",male,25,0,0,SOTON/OQ 392076,7.05,,S
+886,0,3,"Rice, Mrs. William (Margaret Norton)",female,39,0,5,382652,29.125,,Q
+887,0,2,"Montvila, Rev. Juozas",male,27,0,0,211536,13,,S
+888,1,1,"Graham, Miss. Margaret Edith",female,19,0,0,112053,30,B42,S
+889,0,3,"Johnston, Miss. Catherine Helen ""Carrie""",female,,1,2,W./C. 6607,23.45,,S
+890,1,1,"Behr, Mr. Karl Howell",male,26,0,0,111369,30,C148,C
+891,0,3,"Dooley, Mr. Patrick",male,32,0,0,370376,7.75,,Q
diff --git a/demo/kitchen_sink/files/tower.jpg b/demo/kitchen_sink/files/tower.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..aec3fa94eedf13f6e0c4ef56e4f669a3dba59fd8
Binary files /dev/null and b/demo/kitchen_sink/files/tower.jpg differ
diff --git a/demo/kitchen_sink/files/world.mp4 b/demo/kitchen_sink/files/world.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..9bce44c33e275d6107240a1101032a7835fd8eed
--- /dev/null
+++ b/demo/kitchen_sink/files/world.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:71944d7430c461f0cd6e7fd10cee7eb72786352a3678fc7bc0ae3d410f72aece
+size 1570024
diff --git a/demo/kitchen_sink/run.ipynb b/demo/kitchen_sink/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..21dcacd1e6eb588b55dac8385864399eb9f72f03
--- /dev/null
+++ b/demo/kitchen_sink/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: kitchen_sink"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/cantina.wav\n", "!wget -q -O files/cheetah1.jpg https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/cheetah1.jpg\n", "!wget -q -O files/lion.jpg https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/lion.jpg\n", "!wget -q -O files/logo.png https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/logo.png\n", "!wget -q -O files/time.csv https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/time.csv\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/titanic.csv\n", "!wget -q -O files/tower.jpg https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/tower.jpg\n", "!wget -q -O files/world.mp4 https://github.com/gradio-app/gradio/raw/main/demo/kitchen_sink/files/world.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "import json\n", "\n", "import numpy as np\n", "\n", "import gradio as gr\n", "\n", "CHOICES = [\"foo\", \"bar\", \"baz\"]\n", "JSONOBJ = \"\"\"{\"items\":{\"item\":[{\"id\": \"0001\",\"type\": null,\"is_good\": false,\"ppu\": 0.55,\"batters\":{\"batter\":[{ \"id\": \"1001\", \"type\": \"Regular\" },{ \"id\": \"1002\", \"type\": \"Chocolate\" },{ \"id\": \"1003\", \"type\": \"Blueberry\" },{ \"id\": \"1004\", \"type\": \"Devil's Food\" }]},\"topping\":[{ \"id\": \"5001\", \"type\": \"None\" },{ \"id\": \"5002\", \"type\": \"Glazed\" },{ \"id\": \"5005\", \"type\": \"Sugar\" },{ \"id\": \"5007\", \"type\": \"Powdered Sugar\" },{ \"id\": \"5006\", \"type\": \"Chocolate with Sprinkles\" },{ \"id\": \"5003\", \"type\": \"Chocolate\" },{ \"id\": \"5004\", \"type\": \"Maple\" }]}]}}\"\"\"\n", "\n", "\n", "def fn(\n", " text1,\n", " text2,\n", " num,\n", " slider1,\n", " slider2,\n", " single_checkbox,\n", " checkboxes,\n", " radio,\n", " dropdown,\n", " multi_dropdown,\n", " im1,\n", " # im2,\n", " # im3,\n", " im4,\n", " video,\n", " audio1,\n", " audio2,\n", " file,\n", " df1,\n", "):\n", " return (\n", " (text1 if single_checkbox else text2)\n", " + \", selected:\"\n", " + \", \".join(checkboxes), # Text\n", " {\n", " \"positive\": num / (num + slider1 + slider2),\n", " \"negative\": slider1 / (num + slider1 + slider2),\n", " \"neutral\": slider2 / (num + slider1 + slider2),\n", " }, # Label\n", " (audio1[0], np.flipud(audio1[1]))\n", " if audio1 is not None\n", " else os.path.join(os.path.abspath(''), \"files/cantina.wav\"), # Audio\n", " np.flipud(im1)\n", " if im1 is not None\n", " else os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\"), # Image\n", " video\n", " if video is not None\n", " else os.path.join(os.path.abspath(''), \"files/world.mp4\"), # Video\n", " [\n", " (\"The\", \"art\"),\n", " (\"quick brown\", \"adj\"),\n", " (\"fox\", \"nn\"),\n", " (\"jumped\", \"vrb\"),\n", " (\"testing testing testing\", None),\n", " (\"over\", \"prp\"),\n", " (\"the\", \"art\"),\n", " (\"testing\", None),\n", " (\"lazy\", \"adj\"),\n", " (\"dogs\", \"nn\"),\n", " (\".\", \"punc\"),\n", " ]\n", " + [(f\"test {x}\", f\"test {x}\") for x in range(10)], # HighlightedText\n", " # [(\"The testing testing testing\", None), (\"quick brown\", 0.2), (\"fox\", 1), (\"jumped\", -1), (\"testing testing testing\", 0), (\"over\", 0), (\"the\", 0), (\"testing\", 0), (\"lazy\", 1), (\"dogs\", 0), (\".\", 1)] + [(f\"test {x}\", x/10) for x in range(-10, 10)], # HighlightedText\n", " [\n", " (\"The testing testing testing\", None),\n", " (\"over\", 0.6),\n", " (\"the\", 0.2),\n", " (\"testing\", None),\n", " (\"lazy\", -0.1),\n", " (\"dogs\", 0.4),\n", " (\".\", 0),\n", " ]\n", " + [(f\"test\", x / 10) for x in range(-10, 10)], # HighlightedText\n", " json.loads(JSONOBJ), # JSON\n", " \"Click Me: \"\n", " + radio\n", " + \" \", # HTML\n", " os.path.join(os.path.abspath(''), \"files/titanic.csv\"),\n", " df1, # Dataframe\n", " np.random.randint(0, 10, (4, 4)), # Dataframe\n", " )\n", "\n", "\n", "demo = gr.Interface(\n", " fn,\n", " inputs=[\n", " gr.Textbox(value=\"Lorem ipsum\", label=\"Textbox\"),\n", " gr.Textbox(lines=3, placeholder=\"Type here..\", label=\"Textbox 2\"),\n", " gr.Number(label=\"Number\", value=42),\n", " gr.Slider(10, 20, value=15, label=\"Slider: 10 - 20\"),\n", " gr.Slider(maximum=20, step=0.04, label=\"Slider: step @ 0.04\"),\n", " gr.Checkbox(label=\"Checkbox\"),\n", " gr.CheckboxGroup(label=\"CheckboxGroup\", choices=CHOICES, value=CHOICES[0:2]),\n", " gr.Radio(label=\"Radio\", choices=CHOICES, value=CHOICES[2]),\n", " gr.Dropdown(label=\"Dropdown\", choices=CHOICES),\n", " gr.Dropdown(\n", " label=\"Multiselect Dropdown (Max choice: 2)\",\n", " choices=CHOICES,\n", " multiselect=True,\n", " max_choices=2,\n", " ),\n", " gr.Image(label=\"Image\"),\n", " # gr.Image(label=\"Image w/ Cropper\", tool=\"select\"),\n", " # gr.Image(label=\"Sketchpad\", source=\"canvas\"),\n", " gr.Image(label=\"Webcam\", sources=[\"webcam\"]),\n", " gr.Video(label=\"Video\"),\n", " gr.Audio(label=\"Audio\"),\n", " gr.Audio(label=\"Microphone\", sources=[\"microphone\"]),\n", " gr.File(label=\"File\"),\n", " gr.Dataframe(label=\"Dataframe\", headers=[\"Name\", \"Age\", \"Gender\"]),\n", " ],\n", " outputs=[\n", " gr.Textbox(label=\"Textbox\"),\n", " gr.Label(label=\"Label\"),\n", " gr.Audio(label=\"Audio\"),\n", " gr.Image(label=\"Image\"),\n", " gr.Video(label=\"Video\"),\n", " gr.HighlightedText(\n", " label=\"HighlightedText\", color_map={\"punc\": \"pink\", \"test 0\": \"blue\"}\n", " ),\n", " gr.HighlightedText(label=\"HighlightedText\", show_legend=True),\n", " gr.JSON(label=\"JSON\"),\n", " gr.HTML(label=\"HTML\"),\n", " gr.File(label=\"File\"),\n", " gr.Dataframe(label=\"Dataframe\"),\n", " gr.Dataframe(label=\"Numpy\"),\n", " ],\n", " examples=[\n", " [\n", " \"the quick brown fox\",\n", " \"jumps over the lazy dog\",\n", " 10,\n", " 12,\n", " 4,\n", " True,\n", " [\"foo\", \"baz\"],\n", " \"baz\",\n", " \"bar\",\n", " [\"foo\", \"bar\"],\n", " os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\"),\n", " # os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\"),\n", " # os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\"),\n", " os.path.join(os.path.abspath(''), \"files/cheetah1.jpg\"),\n", " os.path.join(os.path.abspath(''), \"files/world.mp4\"),\n", " os.path.join(os.path.abspath(''), \"files/cantina.wav\"),\n", " os.path.join(os.path.abspath(''), \"files/cantina.wav\"),\n", " os.path.join(os.path.abspath(''), \"files/titanic.csv\"),\n", " [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 1, 2], [3, 4, 5, 6]],\n", " ]\n", " ]\n", " * 3,\n", " title=\"Kitchen Sink\",\n", " description=\"Try out all the components!\",\n", " article=\"Learn more about [Gradio](http://gradio.app)\",\n", " cache_examples=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/kitchen_sink/run.py b/demo/kitchen_sink/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b21991baff3d17e7341b895862c321e239c0460
--- /dev/null
+++ b/demo/kitchen_sink/run.py
@@ -0,0 +1,161 @@
+import os
+import json
+
+import numpy as np
+
+import gradio as gr
+
+CHOICES = ["foo", "bar", "baz"]
+JSONOBJ = """{"items":{"item":[{"id": "0001","type": null,"is_good": false,"ppu": 0.55,"batters":{"batter":[{ "id": "1001", "type": "Regular" },{ "id": "1002", "type": "Chocolate" },{ "id": "1003", "type": "Blueberry" },{ "id": "1004", "type": "Devil's Food" }]},"topping":[{ "id": "5001", "type": "None" },{ "id": "5002", "type": "Glazed" },{ "id": "5005", "type": "Sugar" },{ "id": "5007", "type": "Powdered Sugar" },{ "id": "5006", "type": "Chocolate with Sprinkles" },{ "id": "5003", "type": "Chocolate" },{ "id": "5004", "type": "Maple" }]}]}}"""
+
+
+def fn(
+ text1,
+ text2,
+ num,
+ slider1,
+ slider2,
+ single_checkbox,
+ checkboxes,
+ radio,
+ dropdown,
+ multi_dropdown,
+ im1,
+ # im2,
+ # im3,
+ im4,
+ video,
+ audio1,
+ audio2,
+ file,
+ df1,
+):
+ return (
+ (text1 if single_checkbox else text2)
+ + ", selected:"
+ + ", ".join(checkboxes), # Text
+ {
+ "positive": num / (num + slider1 + slider2),
+ "negative": slider1 / (num + slider1 + slider2),
+ "neutral": slider2 / (num + slider1 + slider2),
+ }, # Label
+ (audio1[0], np.flipud(audio1[1]))
+ if audio1 is not None
+ else os.path.join(os.path.dirname(__file__), "files/cantina.wav"), # Audio
+ np.flipud(im1)
+ if im1 is not None
+ else os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg"), # Image
+ video
+ if video is not None
+ else os.path.join(os.path.dirname(__file__), "files/world.mp4"), # Video
+ [
+ ("The", "art"),
+ ("quick brown", "adj"),
+ ("fox", "nn"),
+ ("jumped", "vrb"),
+ ("testing testing testing", None),
+ ("over", "prp"),
+ ("the", "art"),
+ ("testing", None),
+ ("lazy", "adj"),
+ ("dogs", "nn"),
+ (".", "punc"),
+ ]
+ + [(f"test {x}", f"test {x}") for x in range(10)], # HighlightedText
+ # [("The testing testing testing", None), ("quick brown", 0.2), ("fox", 1), ("jumped", -1), ("testing testing testing", 0), ("over", 0), ("the", 0), ("testing", 0), ("lazy", 1), ("dogs", 0), (".", 1)] + [(f"test {x}", x/10) for x in range(-10, 10)], # HighlightedText
+ [
+ ("The testing testing testing", None),
+ ("over", 0.6),
+ ("the", 0.2),
+ ("testing", None),
+ ("lazy", -0.1),
+ ("dogs", 0.4),
+ (".", 0),
+ ]
+ + [(f"test", x / 10) for x in range(-10, 10)], # HighlightedText
+ json.loads(JSONOBJ), # JSON
+ "Click Me: "
+ + radio
+ + " ", # HTML
+ os.path.join(os.path.dirname(__file__), "files/titanic.csv"),
+ df1, # Dataframe
+ np.random.randint(0, 10, (4, 4)), # Dataframe
+ )
+
+
+demo = gr.Interface(
+ fn,
+ inputs=[
+ gr.Textbox(value="Lorem ipsum", label="Textbox"),
+ gr.Textbox(lines=3, placeholder="Type here..", label="Textbox 2"),
+ gr.Number(label="Number", value=42),
+ gr.Slider(10, 20, value=15, label="Slider: 10 - 20"),
+ gr.Slider(maximum=20, step=0.04, label="Slider: step @ 0.04"),
+ gr.Checkbox(label="Checkbox"),
+ gr.CheckboxGroup(label="CheckboxGroup", choices=CHOICES, value=CHOICES[0:2]),
+ gr.Radio(label="Radio", choices=CHOICES, value=CHOICES[2]),
+ gr.Dropdown(label="Dropdown", choices=CHOICES),
+ gr.Dropdown(
+ label="Multiselect Dropdown (Max choice: 2)",
+ choices=CHOICES,
+ multiselect=True,
+ max_choices=2,
+ ),
+ gr.Image(label="Image"),
+ # gr.Image(label="Image w/ Cropper", tool="select"),
+ # gr.Image(label="Sketchpad", source="canvas"),
+ gr.Image(label="Webcam", sources=["webcam"]),
+ gr.Video(label="Video"),
+ gr.Audio(label="Audio"),
+ gr.Audio(label="Microphone", sources=["microphone"]),
+ gr.File(label="File"),
+ gr.Dataframe(label="Dataframe", headers=["Name", "Age", "Gender"]),
+ ],
+ outputs=[
+ gr.Textbox(label="Textbox"),
+ gr.Label(label="Label"),
+ gr.Audio(label="Audio"),
+ gr.Image(label="Image"),
+ gr.Video(label="Video"),
+ gr.HighlightedText(
+ label="HighlightedText", color_map={"punc": "pink", "test 0": "blue"}
+ ),
+ gr.HighlightedText(label="HighlightedText", show_legend=True),
+ gr.JSON(label="JSON"),
+ gr.HTML(label="HTML"),
+ gr.File(label="File"),
+ gr.Dataframe(label="Dataframe"),
+ gr.Dataframe(label="Numpy"),
+ ],
+ examples=[
+ [
+ "the quick brown fox",
+ "jumps over the lazy dog",
+ 10,
+ 12,
+ 4,
+ True,
+ ["foo", "baz"],
+ "baz",
+ "bar",
+ ["foo", "bar"],
+ os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg"),
+ # os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg"),
+ # os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg"),
+ os.path.join(os.path.dirname(__file__), "files/cheetah1.jpg"),
+ os.path.join(os.path.dirname(__file__), "files/world.mp4"),
+ os.path.join(os.path.dirname(__file__), "files/cantina.wav"),
+ os.path.join(os.path.dirname(__file__), "files/cantina.wav"),
+ os.path.join(os.path.dirname(__file__), "files/titanic.csv"),
+ [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 1, 2], [3, 4, 5, 6]],
+ ]
+ ]
+ * 3,
+ title="Kitchen Sink",
+ description="Try out all the components!",
+ article="Learn more about [Gradio](http://gradio.app)",
+ cache_examples=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/kitchen_sink_random/__init__.py b/demo/kitchen_sink_random/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/demo/kitchen_sink_random/constants.py b/demo/kitchen_sink_random/constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..bda41f4f76c8a3749a3ad970f9956d92c5e123b3
--- /dev/null
+++ b/demo/kitchen_sink_random/constants.py
@@ -0,0 +1,68 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import random
+import os
+
+
+def random_plot():
+ start_year = 2020
+ x = np.arange(start_year, start_year + random.randint(0, 10))
+ year_count = x.shape[0]
+ plt_format = "-"
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ series = np.arange(0, year_count, dtype=float)
+ series = series**2
+ series += np.random.rand(year_count)
+ ax.plot(x, series, plt_format)
+ return fig
+
+
+img_dir = os.path.join(os.path.dirname(__file__), "files")
+file_dir = os.path.join(os.path.dirname(__file__), "..", "kitchen_sink", "files")
+model3d_dir = os.path.join(os.path.dirname(__file__), "..", "model3D", "files")
+highlighted_text_output_1 = [
+ {
+ "entity": "I-LOC",
+ "score": 0.9988978,
+ "index": 2,
+ "word": "Chicago",
+ "start": 5,
+ "end": 12,
+ },
+ {
+ "entity": "I-MISC",
+ "score": 0.9958592,
+ "index": 5,
+ "word": "Pakistani",
+ "start": 22,
+ "end": 31,
+ },
+]
+highlighted_text_output_2 = [
+ {
+ "entity": "I-LOC",
+ "score": 0.9988978,
+ "index": 2,
+ "word": "Chicago",
+ "start": 5,
+ "end": 12,
+ },
+ {
+ "entity": "I-LOC",
+ "score": 0.9958592,
+ "index": 5,
+ "word": "Pakistan",
+ "start": 22,
+ "end": 30,
+ },
+]
+
+highlighted_text = "Does Chicago have any Pakistani restaurants"
+
+
+def random_model3d():
+ model_3d = random.choice(
+ [os.path.join(model3d_dir, model) for model in os.listdir(model3d_dir) if model != "source.txt"]
+ )
+ return model_3d
diff --git a/demo/kitchen_sink_random/files/cheetah1.jpeg b/demo/kitchen_sink_random/files/cheetah1.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/kitchen_sink_random/files/cheetah1.jpeg differ
diff --git a/demo/kitchen_sink_random/files/cheetah1.jpg b/demo/kitchen_sink_random/files/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/kitchen_sink_random/files/cheetah1.jpg differ
diff --git a/demo/kitchen_sink_random/files/lion.jpg b/demo/kitchen_sink_random/files/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/demo/kitchen_sink_random/files/lion.jpg differ
diff --git a/demo/kitchen_sink_random/run.py b/demo/kitchen_sink_random/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b4440e94984b8da2d46b6984a78b4f663847165
--- /dev/null
+++ b/demo/kitchen_sink_random/run.py
@@ -0,0 +1,98 @@
+import gradio as gr
+from datetime import datetime
+import random
+import string
+import os
+import pandas as pd
+
+from constants import (
+ file_dir,
+ img_dir,
+ highlighted_text,
+ highlighted_text_output_2,
+ highlighted_text_output_1,
+ random_plot,
+ random_model3d,
+)
+
+
+demo = gr.Interface(
+ lambda *args: args[0],
+ inputs=[
+ gr.Textbox(value=lambda: datetime.now(), label="Current Time"),
+ gr.Number(value=lambda: random.random(), label="Ranom Percentage"),
+ gr.Slider(minimum=-1, maximum=1, randomize=True, label="Slider with randomize"),
+ gr.Slider(
+ minimum=0,
+ maximum=1,
+ value=lambda: random.random(),
+ label="Slider with value func",
+ ),
+ gr.Checkbox(value=lambda: random.random() > 0.5, label="Random Checkbox"),
+ gr.CheckboxGroup(
+ choices=["a", "b", "c", "d"],
+ value=lambda: random.choice(["a", "b", "c", "d"]),
+ label="Random CheckboxGroup",
+ ),
+ gr.Radio(
+ choices=list(string.ascii_lowercase),
+ value=lambda: random.choice(string.ascii_lowercase),
+ ),
+ gr.Dropdown(
+ choices=["a", "b", "c", "d", "e"],
+ value=lambda: random.choice(["a", "b", "c"]),
+ ),
+ gr.Image(
+ value=lambda: random.choice(
+ [os.path.join(img_dir, img) for img in os.listdir(img_dir)]
+ )
+ ),
+ gr.Video(value=lambda: os.path.join(file_dir, "world.mp4")),
+ gr.Audio(value=lambda: os.path.join(file_dir, "cantina.wav")),
+ gr.File(
+ value=lambda: random.choice(
+ [os.path.join(file_dir, img) for img in os.listdir(file_dir)]
+ )
+ ),
+ gr.Dataframe(
+ value=lambda: pd.DataFrame(
+ {"random_number_rows": range(random.randint(0, 10))}
+ )
+ ),
+ gr.State(value=lambda: random.choice(string.ascii_lowercase)),
+ gr.ColorPicker(value=lambda: random.choice(["#000000", "#ff0000", "#0000FF"])),
+ gr.Label(value=lambda: random.choice(["Pedestrian", "Car", "Cyclist"])),
+ gr.HighlightedText(
+ value=lambda: random.choice(
+ [
+ {"text": highlighted_text, "entities": highlighted_text_output_1},
+ {"text": highlighted_text, "entities": highlighted_text_output_2},
+ ]
+ ),
+ ),
+ gr.JSON(value=lambda: random.choice([{"a": 1}, {"b": 2}])),
+ gr.HTML(
+ value=lambda: random.choice(
+ [
+ 'I am red
',
+ 'I am blue
',
+ ]
+ )
+ ),
+ gr.Gallery(
+ value=lambda: [os.path.join(img_dir, img) for img in os.listdir(img_dir)]
+ ),
+ gr.Chatbot(
+ value=lambda: random.choice([[("hello", "hi!")], [("bye", "goodbye!")]])
+ ),
+ gr.Model3D(value=random_model3d),
+ gr.Plot(value=random_plot),
+ gr.Markdown(value=lambda: f"### {random.choice(['Hello', 'Hi', 'Goodbye!'])}"),
+ ],
+ outputs=[
+ gr.State(value=lambda: random.choice(string.ascii_lowercase))
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/label_component/run.ipynb b/demo/label_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c0fdf29ca71de84bc9904e21d35a930f0be75c09
--- /dev/null
+++ b/demo/label_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: label_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Label(value={\"First Label\": 0.7, \"Second Label\": 0.2, \"Third Label\": 0.1})\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/label_component/run.py b/demo/label_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8e9f887c46c93e61d79c77d2c898eec73288182
--- /dev/null
+++ b/demo/label_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Label(value={"First Label": 0.7, "Second Label": 0.2, "Third Label": 0.1})
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/latex/run.ipynb b/demo/latex/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..344513773befaa8306e32e37747144b8708d3ecc
--- /dev/null
+++ b/demo/latex/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: latex"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " r\"\"\"\n", " # Hello World! $\\frac{\\sqrt{x + y}}{4}$ is today's lesson\n", "\n", " ## the $\\sqrt{x + y}$ is first\n", "\n", " Start with $\\frac{\\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.\n", " \n", " There are three formulas to know:\n", " \n", " the first is $\\gamma^2 + \\theta^2 = \\omega^2$\n", " \n", " $\\sqrt{x^2+1}$ is next\n", " \n", " Integral $\\int_{a}^{b} x^2 \\,dx$ is last\n", "\n", " Start typing below to see the output.\n", "\n", " I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/latex/run.py b/demo/latex/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb49ecc596b5a4dec913897095759d4b1876f132
--- /dev/null
+++ b/demo/latex/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ r"""
+ # Hello World! $\frac{\sqrt{x + y}}{4}$ is today's lesson
+
+ ## the $\sqrt{x + y}$ is first
+
+ Start with $\frac{\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.
+
+ There are three formulas to know:
+
+ the first is $\gamma^2 + \theta^2 = \omega^2$
+
+ $\sqrt{x^2+1}$ is next
+
+ Integral $\int_{a}^{b} x^2 \,dx$ is last
+
+ Start typing below to see the output.
+
+ I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.
+ """)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/leaderboard/DESCRIPTION.md b/demo/leaderboard/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..39267b584fec09a88b94170039959ec3ea2f3f58
--- /dev/null
+++ b/demo/leaderboard/DESCRIPTION.md
@@ -0,0 +1 @@
+A simple dashboard ranking spaces by number of likes.
\ No newline at end of file
diff --git a/demo/leaderboard/run.ipynb b/demo/leaderboard/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0780fa5ae2347c3151653d229ae61012e3c6f73c
--- /dev/null
+++ b/demo/leaderboard/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: leaderboard\n", "### A simple dashboard ranking spaces by number of likes.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import requests\n", "import pandas as pd\n", "from huggingface_hub.hf_api import SpaceInfo\n", "path = f\"https://huggingface.co/api/spaces\"\n", "\n", "\n", "def get_blocks_party_spaces():\n", " r = requests.get(path)\n", " d = r.json()\n", " spaces = [SpaceInfo(**x) for x in d]\n", " blocks_spaces = {}\n", " for i in range(0,len(spaces)):\n", " if spaces[i].id.split('/')[0] == 'Gradio-Blocks' and hasattr(spaces[i], 'likes') and spaces[i].id != 'Gradio-Blocks/Leaderboard' and spaces[i].id != 'Gradio-Blocks/README':\n", " blocks_spaces[spaces[i].id]=spaces[i].likes\n", " df = pd.DataFrame(\n", " [{\"Spaces_Name\": Spaces, \"likes\": likes} for Spaces,likes in blocks_spaces.items()])\n", " df = df.sort_values(by=['likes'],ascending=False)\n", " return df\n", "\n", "block = gr.Blocks()\n", "\n", "with block: \n", " gr.Markdown(\"\"\"Leaderboard for the most popular Blocks Event Spaces. To learn more and join, see Blocks Party Event \"\"\")\n", " with gr.Tabs():\n", " with gr.TabItem(\"Blocks Party Leaderboard\"):\n", " with gr.Row():\n", " data = gr.Dataframe(type=\"pandas\")\n", " with gr.Row():\n", " data_run = gr.Button(\"Refresh\")\n", " data_run.click(get_blocks_party_spaces, inputs=None, outputs=data)\n", " # running the function on page load in addition to when the button is clicked\n", " block.load(get_blocks_party_spaces, inputs=None, outputs=data) \n", "\n", "block.launch()\n", "\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/leaderboard/run.py b/demo/leaderboard/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..01948369ec2dd56a2a7d3176c9454e20e7d18d0e
--- /dev/null
+++ b/demo/leaderboard/run.py
@@ -0,0 +1,36 @@
+import gradio as gr
+import requests
+import pandas as pd
+from huggingface_hub.hf_api import SpaceInfo
+path = f"https://huggingface.co/api/spaces"
+
+
+def get_blocks_party_spaces():
+ r = requests.get(path)
+ d = r.json()
+ spaces = [SpaceInfo(**x) for x in d]
+ blocks_spaces = {}
+ for i in range(0,len(spaces)):
+ if spaces[i].id.split('/')[0] == 'Gradio-Blocks' and hasattr(spaces[i], 'likes') and spaces[i].id != 'Gradio-Blocks/Leaderboard' and spaces[i].id != 'Gradio-Blocks/README':
+ blocks_spaces[spaces[i].id]=spaces[i].likes
+ df = pd.DataFrame(
+ [{"Spaces_Name": Spaces, "likes": likes} for Spaces,likes in blocks_spaces.items()])
+ df = df.sort_values(by=['likes'],ascending=False)
+ return df
+
+block = gr.Blocks()
+
+with block:
+ gr.Markdown("""Leaderboard for the most popular Blocks Event Spaces. To learn more and join, see Blocks Party Event """)
+ with gr.Tabs():
+ with gr.TabItem("Blocks Party Leaderboard"):
+ with gr.Row():
+ data = gr.Dataframe(type="pandas")
+ with gr.Row():
+ data_run = gr.Button("Refresh")
+ data_run.click(get_blocks_party_spaces, inputs=None, outputs=data)
+ # running the function on page load in addition to when the button is clicked
+ block.load(get_blocks_party_spaces, inputs=None, outputs=data)
+
+block.launch()
+
diff --git a/demo/line_plot/requirements.txt b/demo/line_plot/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7e0e60ebe2639c9bb9fc78a1be2c2888fed1fafb
--- /dev/null
+++ b/demo/line_plot/requirements.txt
@@ -0,0 +1,2 @@
+vega_datasets
+pandas
\ No newline at end of file
diff --git a/demo/line_plot/run.ipynb b/demo/line_plot/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..10b8606740efa9e80c186f89b9a57d9d8febc5e2
--- /dev/null
+++ b/demo/line_plot/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: line_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "stocks = data.stocks()\n", "gapminder = data.gapminder()\n", "gapminder = gapminder.loc[\n", " gapminder.country.isin([\"Argentina\", \"Australia\", \"Afghanistan\"])\n", "]\n", "climate = data.climate()\n", "seattle_weather = data.seattle_weather()\n", "\n", "## Or generate your own fake data, here's an example for stocks:\n", "#\n", "# import pandas as pd\n", "# import random\n", "#\n", "# stocks = pd.DataFrame(\n", "# {\n", "# \"symbol\": [\n", "# random.choice(\n", "# [\n", "# \"MSFT\",\n", "# \"AAPL\",\n", "# \"AMZN\",\n", "# \"IBM\",\n", "# \"GOOG\",\n", "# ]\n", "# )\n", "# for _ in range(120)\n", "# ],\n", "# \"date\": [\n", "# pd.Timestamp(year=2000 + i, month=j, day=1)\n", "# for i in range(10)\n", "# for j in range(1, 13)\n", "# ],\n", "# \"price\": [random.randint(10, 200) for _ in range(120)],\n", "# }\n", "# )\n", "\n", "\n", "def line_plot_fn(dataset):\n", " if dataset == \"stocks\":\n", " return gr.LinePlot(\n", " stocks,\n", " x=\"date\",\n", " y=\"price\",\n", " color=\"symbol\",\n", " color_legend_position=\"bottom\",\n", " title=\"Stock Prices\",\n", " tooltip=[\"date\", \"price\", \"symbol\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"climate\":\n", " return gr.LinePlot(\n", " climate,\n", " x=\"DATE\",\n", " y=\"HLY-TEMP-NORMAL\",\n", " y_lim=[250, 500],\n", " title=\"Climate\",\n", " tooltip=[\"DATE\", \"HLY-TEMP-NORMAL\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"seattle_weather\":\n", " return gr.LinePlot(\n", " seattle_weather,\n", " x=\"date\",\n", " y=\"temp_min\",\n", " tooltip=[\"weather\", \"date\"],\n", " overlay_point=True,\n", " title=\"Seattle Weather\",\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"gapminder\":\n", " return gr.LinePlot(\n", " gapminder,\n", " x=\"year\",\n", " y=\"life_expect\",\n", " color=\"country\",\n", " title=\"Life expectancy for countries\",\n", " stroke_dash=\"cluster\",\n", " x_lim=[1950, 2010],\n", " tooltip=[\"country\", \"life_expect\"],\n", " stroke_dash_legend_title=\"Country Cluster\",\n", " height=300,\n", " width=500,\n", " )\n", "\n", "\n", "with gr.Blocks() as line_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(\n", " choices=[\"stocks\", \"climate\", \"seattle_weather\", \"gapminder\"],\n", " value=\"stocks\",\n", " )\n", " with gr.Column():\n", " plot = gr.LinePlot()\n", " dataset.change(line_plot_fn, inputs=dataset, outputs=plot)\n", " line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " line_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/line_plot/run.py b/demo/line_plot/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..aec886c055e435071c8b0330618eb639b0581dad
--- /dev/null
+++ b/demo/line_plot/run.py
@@ -0,0 +1,106 @@
+import gradio as gr
+from vega_datasets import data
+
+stocks = data.stocks()
+gapminder = data.gapminder()
+gapminder = gapminder.loc[
+ gapminder.country.isin(["Argentina", "Australia", "Afghanistan"])
+]
+climate = data.climate()
+seattle_weather = data.seattle_weather()
+
+## Or generate your own fake data, here's an example for stocks:
+#
+# import pandas as pd
+# import random
+#
+# stocks = pd.DataFrame(
+# {
+# "symbol": [
+# random.choice(
+# [
+# "MSFT",
+# "AAPL",
+# "AMZN",
+# "IBM",
+# "GOOG",
+# ]
+# )
+# for _ in range(120)
+# ],
+# "date": [
+# pd.Timestamp(year=2000 + i, month=j, day=1)
+# for i in range(10)
+# for j in range(1, 13)
+# ],
+# "price": [random.randint(10, 200) for _ in range(120)],
+# }
+# )
+
+
+def line_plot_fn(dataset):
+ if dataset == "stocks":
+ return gr.LinePlot(
+ stocks,
+ x="date",
+ y="price",
+ color="symbol",
+ color_legend_position="bottom",
+ title="Stock Prices",
+ tooltip=["date", "price", "symbol"],
+ height=300,
+ width=500,
+ )
+ elif dataset == "climate":
+ return gr.LinePlot(
+ climate,
+ x="DATE",
+ y="HLY-TEMP-NORMAL",
+ y_lim=[250, 500],
+ title="Climate",
+ tooltip=["DATE", "HLY-TEMP-NORMAL"],
+ height=300,
+ width=500,
+ )
+ elif dataset == "seattle_weather":
+ return gr.LinePlot(
+ seattle_weather,
+ x="date",
+ y="temp_min",
+ tooltip=["weather", "date"],
+ overlay_point=True,
+ title="Seattle Weather",
+ height=300,
+ width=500,
+ )
+ elif dataset == "gapminder":
+ return gr.LinePlot(
+ gapminder,
+ x="year",
+ y="life_expect",
+ color="country",
+ title="Life expectancy for countries",
+ stroke_dash="cluster",
+ x_lim=[1950, 2010],
+ tooltip=["country", "life_expect"],
+ stroke_dash_legend_title="Country Cluster",
+ height=300,
+ width=500,
+ )
+
+
+with gr.Blocks() as line_plot:
+ with gr.Row():
+ with gr.Column():
+ dataset = gr.Dropdown(
+ choices=["stocks", "climate", "seattle_weather", "gapminder"],
+ value="stocks",
+ )
+ with gr.Column():
+ plot = gr.LinePlot()
+ dataset.change(line_plot_fn, inputs=dataset, outputs=plot)
+ line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot)
+
+
+if __name__ == "__main__":
+ line_plot.launch()
diff --git a/demo/lineplot_component/requirements.txt b/demo/lineplot_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d1c8a7ae0396d12417907feb8ef43fb4bcc8e89c
--- /dev/null
+++ b/demo/lineplot_component/requirements.txt
@@ -0,0 +1 @@
+vega_datasets
\ No newline at end of file
diff --git a/demo/lineplot_component/run.ipynb b/demo/lineplot_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a30e401b71241b662f100b232da5ac314efc554f
--- /dev/null
+++ b/demo/lineplot_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: lineplot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "with gr.Blocks() as demo:\n", " gr.LinePlot(\n", " data.stocks(),\n", " x=\"date\",\n", " y=\"price\",\n", " color=\"symbol\",\n", " color_legend_position=\"bottom\",\n", " title=\"Stock Prices\",\n", " tooltip=[\"date\", \"price\", \"symbol\"],\n", " height=300,\n", " width=300,\n", " container=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/lineplot_component/run.py b/demo/lineplot_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1a236d19e5dd741d15e7b5611862f7a8b575d4c
--- /dev/null
+++ b/demo/lineplot_component/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+from vega_datasets import data
+
+with gr.Blocks() as demo:
+ gr.LinePlot(
+ data.stocks(),
+ x="date",
+ y="price",
+ color="symbol",
+ color_legend_position="bottom",
+ title="Stock Prices",
+ tooltip=["date", "price", "symbol"],
+ height=300,
+ width=300,
+ container=False,
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/live_dashboard/DESCRIPTION.md b/demo/live_dashboard/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..4d2bfebe0a4c3ce79900df1db5b6ac12c6560daa
--- /dev/null
+++ b/demo/live_dashboard/DESCRIPTION.md
@@ -0,0 +1,3 @@
+This demo shows how you can build a live interactive dashboard with gradio.
+The current time is refreshed every second and the plot every half second by using the 'every' keyword in the event handler.
+Changing the value of the slider will control the period of the sine curve (the distance between peaks).
\ No newline at end of file
diff --git a/demo/live_dashboard/requirements.txt b/demo/live_dashboard/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d42d0ad03bdf8ecf9756a38df5cedf8fe431db79
--- /dev/null
+++ b/demo/live_dashboard/requirements.txt
@@ -0,0 +1 @@
+plotly
\ No newline at end of file
diff --git a/demo/live_dashboard/run.ipynb b/demo/live_dashboard/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..6983127d7c01363fab16e3e927e1f9e398118b39
--- /dev/null
+++ b/demo/live_dashboard/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: live_dashboard\n", "### This demo shows how you can build a live interactive dashboard with gradio.\n", "The current time is refreshed every second and the plot every half second by using the 'every' keyword in the event handler.\n", "Changing the value of the slider will control the period of the sine curve (the distance between peaks). \n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import math\n", "\n", "import pandas as pd\n", "\n", "import gradio as gr\n", "import datetime\n", "import numpy as np\n", "\n", "\n", "def get_time():\n", " return datetime.datetime.now()\n", "\n", "\n", "plot_end = 2 * math.pi\n", "\n", "\n", "def get_plot(period=1):\n", " global plot_end\n", " x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)\n", " y = np.sin(2 * math.pi * period * x)\n", " update = gr.LinePlot(\n", " value=pd.DataFrame({\"x\": x, \"y\": y}),\n", " x=\"x\",\n", " y=\"y\",\n", " title=\"Plot (updates every second)\",\n", " width=600,\n", " height=350,\n", " )\n", " plot_end += 2 * math.pi\n", " if plot_end > 1000:\n", " plot_end = 2 * math.pi\n", " return update\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " c_time2 = gr.Textbox(label=\"Current Time refreshed every second\")\n", " gr.Textbox(\n", " \"Change the value of the slider to automatically update the plot\",\n", " label=\"\",\n", " )\n", " period = gr.Slider(\n", " label=\"Period of plot\", value=1, minimum=0, maximum=10, step=1\n", " )\n", " plot = gr.LinePlot(show_label=False)\n", " with gr.Column():\n", " name = gr.Textbox(label=\"Enter your name\")\n", " greeting = gr.Textbox(label=\"Greeting\")\n", " button = gr.Button(value=\"Greet\")\n", " button.click(lambda s: f\"Hello {s}\", name, greeting)\n", "\n", " demo.load(lambda: datetime.datetime.now(), None, c_time2, every=1)\n", " dep = demo.load(get_plot, None, plot, every=1)\n", " period.change(get_plot, period, plot, every=1, cancels=[dep])\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/live_dashboard/run.py b/demo/live_dashboard/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..90c21c50bfcef56821e8e2651da4802aa5c46f32
--- /dev/null
+++ b/demo/live_dashboard/run.py
@@ -0,0 +1,58 @@
+import math
+
+import pandas as pd
+
+import gradio as gr
+import datetime
+import numpy as np
+
+
+def get_time():
+ return datetime.datetime.now()
+
+
+plot_end = 2 * math.pi
+
+
+def get_plot(period=1):
+ global plot_end
+ x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)
+ y = np.sin(2 * math.pi * period * x)
+ update = gr.LinePlot(
+ value=pd.DataFrame({"x": x, "y": y}),
+ x="x",
+ y="y",
+ title="Plot (updates every second)",
+ width=600,
+ height=350,
+ )
+ plot_end += 2 * math.pi
+ if plot_end > 1000:
+ plot_end = 2 * math.pi
+ return update
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ c_time2 = gr.Textbox(label="Current Time refreshed every second")
+ gr.Textbox(
+ "Change the value of the slider to automatically update the plot",
+ label="",
+ )
+ period = gr.Slider(
+ label="Period of plot", value=1, minimum=0, maximum=10, step=1
+ )
+ plot = gr.LinePlot(show_label=False)
+ with gr.Column():
+ name = gr.Textbox(label="Enter your name")
+ greeting = gr.Textbox(label="Greeting")
+ button = gr.Button(value="Greet")
+ button.click(lambda s: f"Hello {s}", name, greeting)
+
+ demo.load(lambda: datetime.datetime.now(), None, c_time2, every=1)
+ dep = demo.load(get_plot, None, plot, every=1)
+ period.change(get_plot, period, plot, every=1, cancels=[dep])
+
+if __name__ == "__main__":
+ demo.queue().launch()
diff --git a/demo/live_with_vars/run.ipynb b/demo/live_with_vars/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7ed43fbd1213428dc8ef0331fb4b4ef2ec66ef22
--- /dev/null
+++ b/demo/live_with_vars/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: live_with_vars"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "demo = gr.Interface(\n", " lambda x, y: (x + y if y is not None else x, x + y if y is not None else x), \n", " [\"textbox\", \"state\"], \n", " [\"textbox\", \"state\"], live=True)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/live_with_vars/run.py b/demo/live_with_vars/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..70c39b36ccbfa1e1ad3239c4efadcdcb8fccbf14
--- /dev/null
+++ b/demo/live_with_vars/run.py
@@ -0,0 +1,9 @@
+import gradio as gr
+
+demo = gr.Interface(
+ lambda x, y: (x + y if y is not None else x, x + y if y is not None else x),
+ ["textbox", "state"],
+ ["textbox", "state"], live=True)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/load_space/run.ipynb b/demo/load_space/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0f649184f23117ee062c48ad6a3b814f88ff9de5
--- /dev/null
+++ b/demo/load_space/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: load_space"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "demo = gr.load(\"gradio/test-gr-load\", src=\"spaces\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/load_space/run.py b/demo/load_space/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..94eef480f6fbc86fdfa3fe3ae5089dfa17457f7b
--- /dev/null
+++ b/demo/load_space/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+demo = gr.load("gradio/test-gr-load", src="spaces")
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/loginbutton_component/requirements.txt b/demo/loginbutton_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7359a07d4b7db60977b67d788f94a41c00c0ccb
--- /dev/null
+++ b/demo/loginbutton_component/requirements.txt
@@ -0,0 +1 @@
+gradio[oauth]
\ No newline at end of file
diff --git a/demo/loginbutton_component/run.ipynb b/demo/loginbutton_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ee38deb411b2d324942945109932f8ec1d3cdd3c
--- /dev/null
+++ b/demo/loginbutton_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: loginbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio gradio[oauth]"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.LoginButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/loginbutton_component/run.py b/demo/loginbutton_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..51a200c2edddaa04cc53213a15ccd537d4815e48
--- /dev/null
+++ b/demo/loginbutton_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.LoginButton()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/logoutbutton_component/requirements.txt b/demo/logoutbutton_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7359a07d4b7db60977b67d788f94a41c00c0ccb
--- /dev/null
+++ b/demo/logoutbutton_component/requirements.txt
@@ -0,0 +1 @@
+gradio[oauth]
\ No newline at end of file
diff --git a/demo/logoutbutton_component/run.ipynb b/demo/logoutbutton_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..954963165387a331390dcd650114b1b5a6ea4a77
--- /dev/null
+++ b/demo/logoutbutton_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: logoutbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio gradio[oauth]"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.LogoutButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/logoutbutton_component/run.py b/demo/logoutbutton_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..05e04c6e8d3615ff67d5c2a7854c547442f3d6a5
--- /dev/null
+++ b/demo/logoutbutton_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.LogoutButton()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/longest_word/run.ipynb b/demo/longest_word/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..def76957fc5721fc1472aebfffc54523eca979bc
--- /dev/null
+++ b/demo/longest_word/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: longest_word"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def longest_word(text):\n", " words = text.split(\" \")\n", " lengths = [len(word) for word in words]\n", " return max(lengths)\n", "\n", "\n", "ex = \"The quick brown fox jumped over the lazy dog.\"\n", "\n", "demo = gr.Interface(\n", " longest_word, \"textbox\", \"label\", examples=[[ex]]\n", ")\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/longest_word/run.py b/demo/longest_word/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc4e5b0a2e6d926e42d2b2c91a6d06e502700118
--- /dev/null
+++ b/demo/longest_word/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+
+
+def longest_word(text):
+ words = text.split(" ")
+ lengths = [len(word) for word in words]
+ return max(lengths)
+
+
+ex = "The quick brown fox jumped over the lazy dog."
+
+demo = gr.Interface(
+ longest_word, "textbox", "label", examples=[[ex]]
+)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/main_note/audio/cantina.wav b/demo/main_note/audio/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/main_note/audio/cantina.wav differ
diff --git a/demo/main_note/audio/recording1.wav b/demo/main_note/audio/recording1.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a58ba5006d4afbfce2b13764e0fc8768286a340d
Binary files /dev/null and b/demo/main_note/audio/recording1.wav differ
diff --git a/demo/main_note/requirements.txt b/demo/main_note/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ca6034584e0ec2dde9b16b581bab6d6a8327a59a
--- /dev/null
+++ b/demo/main_note/requirements.txt
@@ -0,0 +1,3 @@
+scipy
+numpy
+matplotlib
\ No newline at end of file
diff --git a/demo/main_note/run.ipynb b/demo/main_note/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f2610203736db48094a865fa6887bf0c7c77b5db
--- /dev/null
+++ b/demo/main_note/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: main_note"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio scipy numpy matplotlib"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('audio')\n", "!wget -q -O audio/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/main_note/audio/cantina.wav\n", "!wget -q -O audio/recording1.wav https://github.com/gradio-app/gradio/raw/main/demo/main_note/audio/recording1.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["from math import log2, pow\n", "import os\n", "\n", "import numpy as np\n", "from scipy.fftpack import fft\n", "\n", "import gradio as gr\n", "\n", "A4 = 440\n", "C0 = A4 * pow(2, -4.75)\n", "name = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"]\n", "\n", "\n", "def get_pitch(freq):\n", " h = round(12 * log2(freq / C0))\n", " n = h % 12\n", " return name[n]\n", "\n", "\n", "def main_note(audio):\n", " rate, y = audio\n", " if len(y.shape) == 2:\n", " y = y.T[0]\n", " N = len(y)\n", " T = 1.0 / rate\n", " yf = fft(y)\n", " yf2 = 2.0 / N * np.abs(yf[0 : N // 2])\n", " xf = np.linspace(0.0, 1.0 / (2.0 * T), N // 2)\n", "\n", " volume_per_pitch = {}\n", " total_volume = np.sum(yf2)\n", " for freq, volume in zip(xf, yf2):\n", " if freq == 0:\n", " continue\n", " pitch = get_pitch(freq)\n", " if pitch not in volume_per_pitch:\n", " volume_per_pitch[pitch] = 0\n", " volume_per_pitch[pitch] += 1.0 * volume / total_volume\n", " volume_per_pitch = {k: float(v) for k, v in volume_per_pitch.items()}\n", " return volume_per_pitch\n", "\n", "\n", "demo = gr.Interface(\n", " main_note,\n", " gr.Audio(sources=[\"microphone\"]),\n", " gr.Label(num_top_classes=4),\n", " examples=[\n", " [os.path.join(os.path.abspath(''),\"audio/recording1.wav\")],\n", " [os.path.join(os.path.abspath(''),\"audio/cantina.wav\")],\n", " ],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/main_note/run.py b/demo/main_note/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f09e025d278fc89f3c4e2b61cafff7d4f9893493
--- /dev/null
+++ b/demo/main_note/run.py
@@ -0,0 +1,54 @@
+from math import log2, pow
+import os
+
+import numpy as np
+from scipy.fftpack import fft
+
+import gradio as gr
+
+A4 = 440
+C0 = A4 * pow(2, -4.75)
+name = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
+
+
+def get_pitch(freq):
+ h = round(12 * log2(freq / C0))
+ n = h % 12
+ return name[n]
+
+
+def main_note(audio):
+ rate, y = audio
+ if len(y.shape) == 2:
+ y = y.T[0]
+ N = len(y)
+ T = 1.0 / rate
+ yf = fft(y)
+ yf2 = 2.0 / N * np.abs(yf[0 : N // 2])
+ xf = np.linspace(0.0, 1.0 / (2.0 * T), N // 2)
+
+ volume_per_pitch = {}
+ total_volume = np.sum(yf2)
+ for freq, volume in zip(xf, yf2):
+ if freq == 0:
+ continue
+ pitch = get_pitch(freq)
+ if pitch not in volume_per_pitch:
+ volume_per_pitch[pitch] = 0
+ volume_per_pitch[pitch] += 1.0 * volume / total_volume
+ volume_per_pitch = {k: float(v) for k, v in volume_per_pitch.items()}
+ return volume_per_pitch
+
+
+demo = gr.Interface(
+ main_note,
+ gr.Audio(sources=["microphone"]),
+ gr.Label(num_top_classes=4),
+ examples=[
+ [os.path.join(os.path.dirname(__file__),"audio/recording1.wav")],
+ [os.path.join(os.path.dirname(__file__),"audio/cantina.wav")],
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/main_note/screenshot.png b/demo/main_note/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..e14d43db20c921e38d9d7213279ccbd120547457
Binary files /dev/null and b/demo/main_note/screenshot.png differ
diff --git a/demo/map_airbnb/DESCRIPTION.md b/demo/map_airbnb/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..e070c7dfab319139de1355297b4354e790b3cbbf
--- /dev/null
+++ b/demo/map_airbnb/DESCRIPTION.md
@@ -0,0 +1 @@
+Display an interactive map of AirBnB locations with Plotly. Data is hosted on HuggingFace Datasets.
\ No newline at end of file
diff --git a/demo/map_airbnb/requirements.txt b/demo/map_airbnb/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d42d0ad03bdf8ecf9756a38df5cedf8fe431db79
--- /dev/null
+++ b/demo/map_airbnb/requirements.txt
@@ -0,0 +1 @@
+plotly
\ No newline at end of file
diff --git a/demo/map_airbnb/run.ipynb b/demo/map_airbnb/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..952b3cd187550a5148d5ce1e7d8ea56807e8cd0a
--- /dev/null
+++ b/demo/map_airbnb/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: map_airbnb\n", "### Display an interactive map of AirBnB locations with Plotly. Data is hosted on HuggingFace Datasets. \n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import plotly.graph_objects as go\n", "from datasets import load_dataset\n", "\n", "dataset = load_dataset(\"gradio/NYC-Airbnb-Open-Data\", split=\"train\")\n", "df = dataset.to_pandas()\n", "\n", "def filter_map(min_price, max_price, boroughs):\n", "\n", " filtered_df = df[(df['neighbourhood_group'].isin(boroughs)) & \n", " (df['price'] > min_price) & (df['price'] < max_price)]\n", " names = filtered_df[\"name\"].tolist()\n", " prices = filtered_df[\"price\"].tolist()\n", " text_list = [(names[i], prices[i]) for i in range(0, len(names))]\n", " fig = go.Figure(go.Scattermapbox(\n", " customdata=text_list,\n", " lat=filtered_df['latitude'].tolist(),\n", " lon=filtered_df['longitude'].tolist(),\n", " mode='markers',\n", " marker=go.scattermapbox.Marker(\n", " size=6\n", " ),\n", " hoverinfo=\"text\",\n", " hovertemplate='Name : %{customdata[0]}Price : $%{customdata[1]}'\n", " ))\n", "\n", " fig.update_layout(\n", " mapbox_style=\"open-street-map\",\n", " hovermode='closest',\n", " mapbox=dict(\n", " bearing=0,\n", " center=go.layout.mapbox.Center(\n", " lat=40.67,\n", " lon=-73.90\n", " ),\n", " pitch=0,\n", " zoom=9\n", " ),\n", " )\n", "\n", " return fig\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Column():\n", " with gr.Row():\n", " min_price = gr.Number(value=250, label=\"Minimum Price\")\n", " max_price = gr.Number(value=1000, label=\"Maximum Price\")\n", " boroughs = gr.CheckboxGroup(choices=[\"Queens\", \"Brooklyn\", \"Manhattan\", \"Bronx\", \"Staten Island\"], value=[\"Queens\", \"Brooklyn\"], label=\"Select Boroughs:\")\n", " btn = gr.Button(value=\"Update Filter\")\n", " map = gr.Plot()\n", " demo.load(filter_map, [min_price, max_price, boroughs], map)\n", " btn.click(filter_map, [min_price, max_price, boroughs], map)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/map_airbnb/run.py b/demo/map_airbnb/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc770e561513c30814ced0a44872870361f40bc1
--- /dev/null
+++ b/demo/map_airbnb/run.py
@@ -0,0 +1,55 @@
+import gradio as gr
+import plotly.graph_objects as go
+from datasets import load_dataset
+
+dataset = load_dataset("gradio/NYC-Airbnb-Open-Data", split="train")
+df = dataset.to_pandas()
+
+def filter_map(min_price, max_price, boroughs):
+
+ filtered_df = df[(df['neighbourhood_group'].isin(boroughs)) &
+ (df['price'] > min_price) & (df['price'] < max_price)]
+ names = filtered_df["name"].tolist()
+ prices = filtered_df["price"].tolist()
+ text_list = [(names[i], prices[i]) for i in range(0, len(names))]
+ fig = go.Figure(go.Scattermapbox(
+ customdata=text_list,
+ lat=filtered_df['latitude'].tolist(),
+ lon=filtered_df['longitude'].tolist(),
+ mode='markers',
+ marker=go.scattermapbox.Marker(
+ size=6
+ ),
+ hoverinfo="text",
+ hovertemplate='Name : %{customdata[0]}Price : $%{customdata[1]}'
+ ))
+
+ fig.update_layout(
+ mapbox_style="open-street-map",
+ hovermode='closest',
+ mapbox=dict(
+ bearing=0,
+ center=go.layout.mapbox.Center(
+ lat=40.67,
+ lon=-73.90
+ ),
+ pitch=0,
+ zoom=9
+ ),
+ )
+
+ return fig
+
+with gr.Blocks() as demo:
+ with gr.Column():
+ with gr.Row():
+ min_price = gr.Number(value=250, label="Minimum Price")
+ max_price = gr.Number(value=1000, label="Maximum Price")
+ boroughs = gr.CheckboxGroup(choices=["Queens", "Brooklyn", "Manhattan", "Bronx", "Staten Island"], value=["Queens", "Brooklyn"], label="Select Boroughs:")
+ btn = gr.Button(value="Update Filter")
+ map = gr.Plot()
+ demo.load(filter_map, [min_price, max_price, boroughs], map)
+ btn.click(filter_map, [min_price, max_price, boroughs], map)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/markdown_component/run.ipynb b/demo/markdown_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7867cad8885ab3006853dc1bd33429973dbb0f43
--- /dev/null
+++ b/demo/markdown_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: markdown_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(value=\"This _example_ was **written** in [Markdown](https://en.wikipedia.org/wiki/Markdown)\\n\")\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/markdown_component/run.py b/demo/markdown_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f02bda05bb2b7958520cdaf0db0b168be8ff68ba
--- /dev/null
+++ b/demo/markdown_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Markdown(value="This _example_ was **written** in [Markdown](https://en.wikipedia.org/wiki/Markdown)\n")
+
+demo.launch()
diff --git a/demo/markdown_example/run.ipynb b/demo/markdown_example/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ce2c486049e91d8792931e1072ee4e61021c4ca9
--- /dev/null
+++ b/demo/markdown_example/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: markdown_example"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "css = (\n", " \"footer {display: none !important;} .gradio-container {min-height: 0px !important;}\"\n", ")\n", "\n", "# sample md stolen from https://dillinger.io/\n", "\n", "md = \"\"\"# Dillinger\n", "## _The Last Markdown Editor, Ever_\n", "\n", "This is some `inline code`, it is good.\n", "\n", "[![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://travis-ci.org/joemccann/dillinger)\n", "\n", "Dillinger is a cloud-enabled, mobile-ready, offline-storage compatible,\n", "AngularJS-powered HTML5 Markdown editor.\n", "\n", "- Type some Markdown on the left\n", "- See HTML in the right\n", "- \u2728Magic \u2728\n", "\n", "## Features\n", "\n", "- Import a HTML file and watch it magically convert to Markdown\n", "- Drag and drop images (requires your Dropbox account be linked)\n", "- Import and save files from GitHub, Dropbox, Google Drive and One Drive\n", "- Drag and drop markdown and HTML files into Dillinger\n", "- Export documents as Markdown, HTML and PDF\n", "\n", "Markdown is a lightweight markup language based on the formatting conventions\n", "that people naturally use in email.\n", "As [John Gruber] writes on the [Markdown site][df1]\n", "\n", "> The overriding design goal for Markdown's\n", "> formatting syntax is to make it as readable\n", "> as possible. The idea is that a\n", "> Markdown-formatted document should be\n", "> publishable as-is, as plain text, without\n", "> looking like it's been marked up with tags\n", "> or formatting instructions.\n", "\n", "This text you see here is *actually- written in Markdown! To get a feel\n", "for Markdown's syntax, type some text into the left window and\n", "watch the results in the right.\n", "\n", "## Tech\n", "\n", "Dillinger uses a number of open source projects to work properly:\n", "\n", "- [AngularJS] - HTML enhanced for web apps!\n", "- [Ace Editor] - awesome web-based text editor\n", "- [markdown-it] - Markdown parser done right. Fast and easy to extend.\n", "- [Twitter Bootstrap] - great UI boilerplate for modern web apps\n", "- [node.js] - evented I/O for the backend\n", "- [Express] - fast node.js network app framework [@tjholowaychuk]\n", "- [Gulp] - the streaming build system\n", "- [Breakdance](https://breakdance.github.io/breakdance/) - HTML\n", "to Markdown converter\n", "- [jQuery] - duh\n", "\n", "And of course Dillinger itself is open source with a [public repository][dill]\n", " on GitHub.\n", "\n", "## Installation\n", "\n", "Dillinger requires [Node.js](https://nodejs.org/) v10+ to run.\n", "\n", "Install the dependencies and devDependencies and start the server.\n", "\n", "```bash\n", "cd dillinger\n", "npm i\n", "node app\n", "```\n", "\n", "For production environments...\n", "\n", "```bash\n", "npm install --production\n", "NODE_ENV=production node app\n", "```\n", "\n", "## Plugins\n", "\n", "Dillinger is currently extended with the following plugins.\n", "Instructions on how to use them in your own application are linked below.\n", "\n", "| Plugin | README |\n", "| ------ | ------ |\n", "| Dropbox | [plugins/dropbox/README.md][PlDb] |\n", "| GitHub | [plugins/github/README.md][PlGh] |\n", "| Google Drive | [plugins/googledrive/README.md][PlGd] |\n", "| OneDrive | [plugins/onedrive/README.md][PlOd] |\n", "| Medium | [plugins/medium/README.md][PlMe] |\n", "| Google Analytics | [plugins/googleanalytics/README.md][PlGa] |\n", "\n", "## Development\n", "\n", "Want to contribute? Great!\n", "\n", "Dillinger uses Gulp + Webpack for fast developing.\n", "Make a change in your file and instantaneously see your updates!\n", "\n", "Open your favorite Terminal and run these commands.\n", "\n", "First Tab:\n", "\n", "```bash\n", "node app\n", "```\n", "\n", "Second Tab:\n", "\n", "```bash\n", "gulp watch\n", "```\n", "\n", "(optional) Third:\n", "\n", "```bash\n", "karma test\n", "```\n", "\n", "#### Building for source\n", "\n", "For production release:\n", "\n", "```bash\n", "gulp build --prod\n", "```\n", "\n", "Generating pre-built zip archives for distribution:\n", "\n", "```bash\n", "gulp build dist --prod\n", "```\n", "\n", "## Docker\n", "\n", "Dillinger is very easy to install and deploy in a Docker container.\n", "\n", "By default, the Docker will expose port 8080, so change this within the\n", "Dockerfile if necessary. When ready, simply use the Dockerfile to\n", "build the image.\n", "\n", "```bash\n", "cd dillinger\n", "docker build -t /dillinger:${package.json.version} .\n", "```\n", "\n", "This will create the dillinger image and pull in the necessary dependencies.\n", "Be sure to swap out `${package.json.version}` with the actual\n", "version of Dillinger.\n", "\n", "Once done, run the Docker image and map the port to whatever you wish on\n", "your host. In this example, we simply map port 8000 of the host to\n", "port 8080 of the Docker (or whatever port was exposed in the Dockerfile):\n", "\n", "```bash\n", "docker run -d -p 8000:8080 --restart=always --cap-add=SYS_ADMIN --name=dillinger /dillinger:${package.json.version}\n", "```\n", "\n", "> Note: `--capt-add=SYS-ADMIN` is required for PDF rendering.\n", "\n", "Verify the deployment by navigating to your server address in\n", "your preferred browser.\n", "\n", "```bash\n", "127.0.0.1:8000\n", "```\n", "\n", "```python\n", "import gradio as gr\n", "\n", "gr.Blocks() as demo:\n", " gr.Markdown(value=md)\n", "\n", "demo.launch()\n", "```\n", "\n", "```js\n", "function fancyAlert(arg) {\n", " if(arg) {\n", " $.facebox({div:'#foo'})\n", " }\n", "}\n", "```\n", "\n", "## License\n", "\n", "MIT\n", "\n", "**Free Software, Hell Yeah!**\n", "\n", "[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)\n", "\n", " [dill]: \n", " [git-repo-url]: \n", " [john gruber]: \n", " [df1]: \n", " [markdown-it]: \n", " [Ace Editor]: \n", " [node.js]: \n", " [Twitter Bootstrap]: \n", " [jQuery]: \n", " [@tjholowaychuk]: \n", " [express]: \n", " [AngularJS]: \n", " [Gulp]: \n", "\n", " [PlDb]: \n", " [PlGh]: \n", " [PlGd]: \n", " [PlOd]: \n", " [PlMe]: \n", " [PlGa]: \n", "\n", "\"\"\"\n", "with gr.Blocks(css=css) as demo:\n", " gr.Markdown(value=md, header_links=True)\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/markdown_example/run.py b/demo/markdown_example/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4c6108295a8d9fe3191d0aa8456b6ee85e79f85
--- /dev/null
+++ b/demo/markdown_example/run.py
@@ -0,0 +1,223 @@
+import gradio as gr
+
+css = (
+ "footer {display: none !important;} .gradio-container {min-height: 0px !important;}"
+)
+
+# sample md stolen from https://dillinger.io/
+
+md = """# Dillinger
+## _The Last Markdown Editor, Ever_
+
+This is some `inline code`, it is good.
+
+[![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://travis-ci.org/joemccann/dillinger)
+
+Dillinger is a cloud-enabled, mobile-ready, offline-storage compatible,
+AngularJS-powered HTML5 Markdown editor.
+
+- Type some Markdown on the left
+- See HTML in the right
+- ✨Magic ✨
+
+## Features
+
+- Import a HTML file and watch it magically convert to Markdown
+- Drag and drop images (requires your Dropbox account be linked)
+- Import and save files from GitHub, Dropbox, Google Drive and One Drive
+- Drag and drop markdown and HTML files into Dillinger
+- Export documents as Markdown, HTML and PDF
+
+Markdown is a lightweight markup language based on the formatting conventions
+that people naturally use in email.
+As [John Gruber] writes on the [Markdown site][df1]
+
+> The overriding design goal for Markdown's
+> formatting syntax is to make it as readable
+> as possible. The idea is that a
+> Markdown-formatted document should be
+> publishable as-is, as plain text, without
+> looking like it's been marked up with tags
+> or formatting instructions.
+
+This text you see here is *actually- written in Markdown! To get a feel
+for Markdown's syntax, type some text into the left window and
+watch the results in the right.
+
+## Tech
+
+Dillinger uses a number of open source projects to work properly:
+
+- [AngularJS] - HTML enhanced for web apps!
+- [Ace Editor] - awesome web-based text editor
+- [markdown-it] - Markdown parser done right. Fast and easy to extend.
+- [Twitter Bootstrap] - great UI boilerplate for modern web apps
+- [node.js] - evented I/O for the backend
+- [Express] - fast node.js network app framework [@tjholowaychuk]
+- [Gulp] - the streaming build system
+- [Breakdance](https://breakdance.github.io/breakdance/) - HTML
+to Markdown converter
+- [jQuery] - duh
+
+And of course Dillinger itself is open source with a [public repository][dill]
+ on GitHub.
+
+## Installation
+
+Dillinger requires [Node.js](https://nodejs.org/) v10+ to run.
+
+Install the dependencies and devDependencies and start the server.
+
+```bash
+cd dillinger
+npm i
+node app
+```
+
+For production environments...
+
+```bash
+npm install --production
+NODE_ENV=production node app
+```
+
+## Plugins
+
+Dillinger is currently extended with the following plugins.
+Instructions on how to use them in your own application are linked below.
+
+| Plugin | README |
+| ------ | ------ |
+| Dropbox | [plugins/dropbox/README.md][PlDb] |
+| GitHub | [plugins/github/README.md][PlGh] |
+| Google Drive | [plugins/googledrive/README.md][PlGd] |
+| OneDrive | [plugins/onedrive/README.md][PlOd] |
+| Medium | [plugins/medium/README.md][PlMe] |
+| Google Analytics | [plugins/googleanalytics/README.md][PlGa] |
+
+## Development
+
+Want to contribute? Great!
+
+Dillinger uses Gulp + Webpack for fast developing.
+Make a change in your file and instantaneously see your updates!
+
+Open your favorite Terminal and run these commands.
+
+First Tab:
+
+```bash
+node app
+```
+
+Second Tab:
+
+```bash
+gulp watch
+```
+
+(optional) Third:
+
+```bash
+karma test
+```
+
+#### Building for source
+
+For production release:
+
+```bash
+gulp build --prod
+```
+
+Generating pre-built zip archives for distribution:
+
+```bash
+gulp build dist --prod
+```
+
+## Docker
+
+Dillinger is very easy to install and deploy in a Docker container.
+
+By default, the Docker will expose port 8080, so change this within the
+Dockerfile if necessary. When ready, simply use the Dockerfile to
+build the image.
+
+```bash
+cd dillinger
+docker build -t /dillinger:${package.json.version} .
+```
+
+This will create the dillinger image and pull in the necessary dependencies.
+Be sure to swap out `${package.json.version}` with the actual
+version of Dillinger.
+
+Once done, run the Docker image and map the port to whatever you wish on
+your host. In this example, we simply map port 8000 of the host to
+port 8080 of the Docker (or whatever port was exposed in the Dockerfile):
+
+```bash
+docker run -d -p 8000:8080 --restart=always --cap-add=SYS_ADMIN --name=dillinger /dillinger:${package.json.version}
+```
+
+> Note: `--capt-add=SYS-ADMIN` is required for PDF rendering.
+
+Verify the deployment by navigating to your server address in
+your preferred browser.
+
+```bash
+127.0.0.1:8000
+```
+
+```python
+import gradio as gr
+
+gr.Blocks() as demo:
+ gr.Markdown(value=md)
+
+demo.launch()
+```
+
+```js
+function fancyAlert(arg) {
+ if(arg) {
+ $.facebox({div:'#foo'})
+ }
+}
+```
+
+## License
+
+MIT
+
+**Free Software, Hell Yeah!**
+
+[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)
+
+ [dill]:
+ [git-repo-url]:
+ [john gruber]:
+ [df1]:
+ [markdown-it]:
+ [Ace Editor]:
+ [node.js]:
+ [Twitter Bootstrap]:
+ [jQuery]:
+ [@tjholowaychuk]:
+ [express]:
+ [AngularJS]:
+ [Gulp]:
+
+ [PlDb]:
+ [PlGh]:
+ [PlGd]:
+ [PlOd]:
+ [PlMe]:
+ [PlGa]:
+
+"""
+with gr.Blocks(css=css) as demo:
+ gr.Markdown(value=md, header_links=True)
+
+demo.launch()
diff --git a/demo/matrix_transpose/run.ipynb b/demo/matrix_transpose/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d2d497ef82776db4deca3ad4e30bfb805226150f
--- /dev/null
+++ b/demo/matrix_transpose/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: matrix_transpose"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def transpose(matrix):\n", " return matrix.T\n", "\n", "\n", "demo = gr.Interface(\n", " transpose,\n", " gr.Dataframe(type=\"numpy\", datatype=\"number\", row_count=5, col_count=3),\n", " \"numpy\",\n", " examples=[\n", " [np.zeros((3, 3)).tolist()],\n", " [np.ones((2, 2)).tolist()],\n", " [np.random.randint(0, 10, (3, 10)).tolist()],\n", " [np.random.randint(0, 10, (10, 3)).tolist()],\n", " [np.random.randint(0, 10, (10, 10)).tolist()],\n", " ],\n", " cache_examples=False\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/matrix_transpose/run.py b/demo/matrix_transpose/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..34548199576ef86fa50139cbc6762e038e9d69a8
--- /dev/null
+++ b/demo/matrix_transpose/run.py
@@ -0,0 +1,25 @@
+import numpy as np
+
+import gradio as gr
+
+
+def transpose(matrix):
+ return matrix.T
+
+
+demo = gr.Interface(
+ transpose,
+ gr.Dataframe(type="numpy", datatype="number", row_count=5, col_count=3),
+ "numpy",
+ examples=[
+ [np.zeros((3, 3)).tolist()],
+ [np.ones((2, 2)).tolist()],
+ [np.random.randint(0, 10, (3, 10)).tolist()],
+ [np.random.randint(0, 10, (10, 3)).tolist()],
+ [np.random.randint(0, 10, (10, 10)).tolist()],
+ ],
+ cache_examples=False
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/matrix_transpose/screenshot.png b/demo/matrix_transpose/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9434e9c1df2828ecc1df700eeaaad9609109f82
Binary files /dev/null and b/demo/matrix_transpose/screenshot.png differ
diff --git a/demo/model3D/files/Bunny.obj b/demo/model3D/files/Bunny.obj
new file mode 100644
index 0000000000000000000000000000000000000000..9baeb363cce8feb5dd62ecaf8d64a14b6c50ce37
--- /dev/null
+++ b/demo/model3D/files/Bunny.obj
@@ -0,0 +1,7474 @@
+# OBJ file format with ext .obj
+# vertex count = 2503
+# face count = 4968
+v -3.4101800e-003 1.3031957e-001 2.1754370e-002
+v -8.1719160e-002 1.5250145e-001 2.9656090e-002
+v -3.0543480e-002 1.2477885e-001 1.0983400e-003
+v -2.4901590e-002 1.1211138e-001 3.7560240e-002
+v -1.8405680e-002 1.7843055e-001 -2.4219580e-002
+v 1.9067940e-002 1.2144925e-001 3.1968440e-002
+v 6.0412000e-003 1.2494359e-001 3.2652890e-002
+v -1.3469030e-002 1.6299355e-001 -1.2000020e-002
+v -3.4393240e-002 1.7236688e-001 -9.8213000e-004
+v -8.4314160e-002 1.0957263e-001 3.7097300e-003
+v -4.2233540e-002 1.7211574e-001 -4.1799800e-003
+v -6.3308390e-002 1.5660615e-001 -1.3838790e-002
+v -7.6903950e-002 1.6708033e-001 -2.6931360e-002
+v -7.2253920e-002 1.1539550e-001 5.1670300e-002
+v 1.2981330e-002 1.1366375e-001 3.8302950e-002
+v -3.7857280e-002 1.7010102e-001 1.4236000e-003
+v 4.8689400e-003 3.7962370e-002 4.5867630e-002
+v -5.7180550e-002 4.0918830e-002 4.6301340e-002
+v -4.5209070e-002 3.8839100e-002 4.4503770e-002
+v -3.3761490e-002 1.2617876e-001 1.7132300e-003
+v -5.0242270e-002 1.5773747e-001 9.3944500e-003
+v -2.1216950e-002 1.5887938e-001 -4.6923700e-003
+v -5.6472950e-002 1.5778406e-001 8.1786500e-003
+v -5.2802060e-002 4.1319860e-002 4.6169800e-002
+v -4.9960340e-002 4.3101950e-002 4.4462650e-002
+v -2.9748750e-002 3.6539860e-002 5.2493310e-002
+v -3.5438900e-003 4.2659770e-002 4.7541530e-002
+v 4.9304900e-003 4.1982660e-002 4.5723390e-002
+v -3.9088180e-002 1.6872020e-001 -1.1924680e-002
+v -5.6901000e-002 4.5437000e-002 4.3236960e-002
+v -4.1244880e-002 4.3098890e-002 4.2129560e-002
+v -2.6471980e-002 4.5034530e-002 5.1219460e-002
+v -2.1866970e-002 4.4022930e-002 5.3243800e-002
+v -3.6996250e-002 1.6899301e-001 1.3256300e-003
+v -6.7216590e-002 1.6171340e-001 -1.3733710e-002
+v 4.9760060e-002 7.0235220e-002 2.3732020e-002
+v -4.9186640e-002 4.6411230e-002 4.1170040e-002
+v -4.4590380e-002 4.3797990e-002 4.2685460e-002
+v -4.3686470e-002 4.7154500e-002 4.0286310e-002
+v -2.2491950e-002 4.6513620e-002 5.1885310e-002
+v -6.5174200e-003 4.5036200e-002 4.7502780e-002
+v 3.7699000e-004 4.4935790e-002 4.6519930e-002
+v 3.4023920e-002 1.1353879e-001 2.4595280e-002
+v -2.6467900e-002 1.8104250e-001 -8.0811700e-003
+v -1.7533470e-002 4.7964250e-002 4.8829630e-002
+v -7.0012600e-003 4.6416520e-002 4.7485540e-002
+v 5.9862300e-003 4.6689140e-002 4.9073620e-002
+v 9.1007200e-003 4.8474490e-002 4.9353190e-002
+v -3.5453700e-002 1.1244769e-001 3.5055410e-002
+v -7.5983200e-002 1.3820800e-001 4.9216580e-002
+v 3.4838440e-002 4.3153410e-002 2.8954310e-002
+v -5.2655550e-002 4.8494220e-002 3.8731190e-002
+v -4.7378940e-002 4.8456670e-002 3.9126790e-002
+v -3.8933750e-002 4.6364270e-002 4.0364780e-002
+v -2.6468940e-002 4.7816430e-002 4.9322590e-002
+v -2.2365790e-002 4.8073650e-002 5.0126500e-002
+v -1.3373430e-002 4.7892410e-002 4.7883850e-002
+v -1.2193490e-002 4.9470300e-002 4.9484490e-002
+v -6.3364000e-004 4.7193060e-002 4.9136900e-002
+v 2.0656800e-003 5.0104680e-002 5.2290220e-002
+v -2.2749270e-002 4.9883880e-002 4.6605520e-002
+v -1.8002080e-002 4.9917850e-002 4.6947970e-002
+v -7.8036800e-003 5.0169310e-002 5.0988650e-002
+v -2.6843800e-003 5.1247420e-002 5.3186790e-002
+v -6.3875650e-002 1.6140094e-001 -2.0064210e-002
+v 3.2434000e-002 4.5333970e-002 3.0316760e-002
+v -8.8064570e-002 1.2496764e-001 5.7412000e-004
+v -4.1503710e-002 1.6748512e-001 3.2765900e-003
+v -6.4457010e-002 1.5342891e-001 -5.1180400e-003
+v -3.4303190e-002 5.0520150e-002 3.8286020e-002
+v -2.2949400e-002 5.1020650e-002 4.3926450e-002
+v -1.4354710e-002 5.4428200e-002 5.0710310e-002
+v 1.3773100e-003 5.2302710e-002 5.3149010e-002
+v 3.6285000e-003 5.3198640e-002 5.3422710e-002
+v 8.0723800e-003 5.1574140e-002 5.1773560e-002
+v -7.2665890e-002 1.3005582e-001 5.1668200e-002
+v 3.7992780e-002 4.9793200e-002 3.1902020e-002
+v 3.8497260e-002 4.8062400e-002 3.1737450e-002
+v 2.1503510e-002 1.2563988e-001 2.1252620e-002
+v -7.6481330e-002 1.4827412e-001 -8.9376200e-003
+v -8.7240410e-002 1.1967213e-001 -1.7813000e-004
+v -4.3719960e-002 1.6822738e-001 2.3425000e-003
+v -4.0652200e-002 1.2266506e-001 2.6290300e-002
+v -4.6686180e-002 5.4570720e-002 3.7587370e-002
+v -4.4071750e-002 5.1058250e-002 3.8977810e-002
+v -3.8144110e-002 5.0599600e-002 3.9302160e-002
+v -1.9875770e-002 5.1607710e-002 4.6142000e-002
+v -1.6911250e-002 5.1843550e-002 4.8459320e-002
+v -1.6249190e-002 5.4292110e-002 5.0306940e-002
+v -1.0446540e-002 5.3685970e-002 5.1958610e-002
+v -4.3090900e-003 5.4467500e-002 5.3908250e-002
+v 7.8152700e-003 5.5050680e-002 5.2750250e-002
+v 3.7955090e-002 1.0488710e-001 -3.2031800e-003
+v -7.9003790e-002 1.2850550e-001 5.3149340e-002
+v -7.9778990e-002 1.3448894e-001 5.0990290e-002
+v -5.9129700e-002 1.5039712e-001 3.4489540e-002
+v -6.5691790e-002 1.4961818e-001 3.8160980e-002
+v -3.1951660e-002 1.2518394e-001 1.9400580e-002
+v -6.9372590e-002 1.6061775e-001 -9.1905000e-003
+v -4.5225500e-002 1.2935459e-001 2.0377520e-002
+v -4.1879110e-002 5.6164390e-002 3.9796700e-002
+v -3.0614840e-002 5.4412650e-002 3.6694290e-002
+v -2.4787600e-002 5.2606220e-002 4.0839760e-002
+v -2.1588860e-002 5.6836920e-002 4.5467040e-002
+v -2.4264000e-004 5.4536020e-002 5.4641200e-002
+v -8.0900510e-002 1.2558713e-001 5.2155370e-002
+v -2.9996210e-002 1.7811137e-001 -5.2358200e-003
+v 3.5515390e-002 5.0449570e-002 3.1439830e-002
+v 4.3315550e-002 5.2145550e-002 3.2492110e-002
+v -6.3938540e-002 1.5262699e-001 3.4481070e-002
+v -4.4489440e-002 6.1077710e-002 3.9545320e-002
+v -3.8979900e-002 5.7996270e-002 4.0151390e-002
+v -7.9087730e-002 1.7044488e-001 -4.1373170e-002
+v -4.6247300e-003 5.7759650e-002 5.3990710e-002
+v -1.4985500e-003 5.5925480e-002 5.4630800e-002
+v 5.1981700e-003 5.7017990e-002 5.3423530e-002
+v 3.0920000e-005 1.2315746e-001 3.4749660e-002
+v 3.3568300e-002 1.1523716e-001 2.1798410e-002
+v 3.8686300e-002 5.6450590e-002 3.1188930e-002
+v -3.4385780e-002 5.4096000e-002 3.8060290e-002
+v -8.5308300e-003 6.0159420e-002 5.5308950e-002
+v -4.4024000e-004 5.8343410e-002 5.4483410e-002
+v -9.1078730e-002 1.1506037e-001 4.0141810e-002
+v 4.0775480e-002 5.4557490e-002 3.2014740e-002
+v 4.5636880e-002 5.7402620e-002 3.1992220e-002
+v 2.0358850e-002 1.2448747e-001 2.5906340e-002
+v -1.4169700e-002 1.2767892e-001 1.3080500e-003
+v -1.1987590e-002 5.7493210e-002 5.2752420e-002
+v 3.2514500e-003 5.9828640e-002 5.5464300e-002
+v -1.2395240e-002 1.2264726e-001 3.3588280e-002
+v 1.3813780e-002 1.2322188e-001 3.2502590e-002
+v -7.7004310e-002 1.5521281e-001 2.4534770e-002
+v -2.8001360e-002 6.1075420e-002 3.7471210e-002
+v -8.5480000e-004 6.0593520e-002 5.5824810e-002
+v -3.8050200e-002 1.1527068e-001 3.3178540e-002
+v -1.6231340e-002 1.2382942e-001 2.9576990e-002
+v -2.5373550e-002 1.5840012e-001 -1.4801300e-003
+v -6.7818590e-002 1.5454353e-001 3.0233720e-002
+v -4.3082600e-003 6.1418570e-002 5.5688490e-002
+v -3.1958900e-003 1.1912518e-001 3.8349580e-002
+v -6.4292400e-003 1.2201090e-001 3.5740890e-002
+v 4.2312960e-002 5.9099150e-002 3.0848420e-002
+v 4.8510010e-002 6.1780760e-002 3.0347250e-002
+v 5.0412290e-002 6.0312610e-002 3.0245060e-002
+v -3.9185590e-002 6.3074530e-002 4.1382890e-002
+v -3.4448660e-002 6.0780500e-002 3.9543990e-002
+v -1.4746030e-002 6.5583910e-002 5.3730860e-002
+v 2.6645200e-003 6.2700010e-002 5.6525210e-002
+v -1.3991610e-002 1.1962575e-001 3.6251540e-002
+v 1.9659170e-002 1.1236219e-001 3.7545270e-002
+v -3.2597160e-002 1.7498725e-001 -2.5953100e-003
+v -2.1513900e-003 9.9437380e-002 4.9849750e-002
+v -5.6001390e-002 6.1830670e-002 2.7931150e-002
+v -5.4707260e-002 6.3461570e-002 3.1670590e-002
+v -5.1307940e-002 6.0521660e-002 3.1434930e-002
+v -4.1979320e-002 6.9629980e-002 4.1824930e-002
+v -3.0272490e-002 6.2474660e-002 3.7982220e-002
+v -1.1387860e-002 6.4742460e-002 5.4918000e-002
+v 6.9544900e-003 6.4700130e-002 5.5599150e-002
+v 4.3015090e-002 9.7690960e-002 1.0258300e-003
+v 4.0635900e-002 6.1574860e-002 2.9841250e-002
+v 4.6183560e-002 6.1910110e-002 3.0223400e-002
+v 3.7552960e-002 1.0685291e-001 2.6303470e-002
+v -7.8640730e-002 1.6387238e-001 -2.8387790e-002
+v -6.1996240e-002 1.4761484e-001 -4.3256800e-003
+v -5.7499800e-003 6.5488980e-002 5.6173390e-002
+v 2.5369000e-004 6.5741170e-002 5.6569260e-002
+v -2.0542550e-002 1.1979518e-001 3.3003670e-002
+v 4.3155900e-003 1.2782561e-001 2.8646880e-002
+v -4.6549580e-002 6.7652130e-002 3.9635790e-002
+v -1.7420580e-002 6.9659490e-002 5.4089530e-002
+v -1.5242190e-002 7.0909900e-002 5.5004790e-002
+v -1.0282890e-002 6.8926360e-002 5.5289610e-002
+v -1.1289000e-004 6.9288200e-002 5.6579790e-002
+v -3.6309330e-002 1.1876943e-001 3.0674020e-002
+v -7.0325800e-002 6.3367770e-002 1.9809180e-002
+v 4.3023100e-002 6.3795810e-002 2.8039210e-002
+v 4.2831110e-002 8.5556040e-002 2.7873760e-002
+v 1.6981600e-002 1.2715003e-001 2.2931490e-002
+v -4.2121490e-002 1.2825104e-001 1.0751500e-003
+v 1.6329230e-002 1.2251895e-001 3.1375390e-002
+v -8.1264160e-002 1.5381172e-001 2.5897830e-002
+v -3.2257870e-002 8.8192600e-002 -2.5130960e-002
+v -1.3774950e-002 7.0887950e-002 5.4695630e-002
+v 5.2929600e-003 6.8006030e-002 5.5670490e-002
+v 7.6962500e-003 7.2375600e-002 5.6062150e-002
+v 3.4830600e-003 1.2002635e-001 3.6911950e-002
+v 6.6532500e-003 1.1673563e-001 3.8716340e-002
+v 4.6086570e-002 6.6473930e-002 2.6808990e-002
+v 5.2327290e-002 6.4327070e-002 2.8281890e-002
+v -6.1897630e-002 1.2297065e-001 -8.7725500e-003
+v -6.3934700e-003 1.0524472e-001 -2.2841900e-002
+v -3.5218330e-002 6.8559830e-002 4.1381470e-002
+v -3.2689880e-002 6.7729720e-002 4.0124390e-002
+v -2.9245440e-002 6.9551520e-002 3.9369010e-002
+v -5.0024500e-003 6.9655000e-002 5.6892510e-002
+v 1.6573960e-002 1.1890153e-001 3.5042300e-002
+v -8.9385100e-002 9.9024040e-002 1.7521830e-002
+v 4.5719230e-002 6.9489400e-002 2.3549340e-002
+v 5.4537210e-002 6.8796720e-002 2.4517690e-002
+v -4.4989450e-002 7.1577330e-002 4.1929250e-002
+v -4.2439400e-003 1.2914902e-001 2.5829230e-002
+v -7.3880090e-002 1.2091638e-001 5.3395800e-002
+v -7.4033870e-002 1.4406894e-001 4.4994970e-002
+v 5.0400010e-002 6.7292480e-002 2.6851470e-002
+v -5.4056890e-002 1.5671602e-001 -2.4865900e-003
+v 2.6148110e-002 1.2014725e-001 2.7308010e-002
+v -1.0736490e-002 1.2990285e-001 1.0993790e-002
+v -4.5078840e-002 8.7261130e-002 -2.1865520e-002
+v -3.8340900e-002 6.8843770e-002 4.1846470e-002
+v -2.9255580e-002 7.5169210e-002 4.1186430e-002
+v -4.7311210e-002 1.6296037e-001 6.0740300e-003
+v -1.1866030e-002 7.3183750e-002 5.6250050e-002
+v -6.3734600e-003 7.2184340e-002 5.7972980e-002
+v -2.9935300e-003 7.2186440e-002 5.8167190e-002
+v -2.5781060e-002 9.3778180e-002 -2.8388220e-002
+v -1.6692560e-002 1.1568553e-001 3.7853150e-002
+v -8.4123410e-002 1.0832050e-001 2.4730980e-002
+v -7.4294080e-002 1.6356850e-001 -1.5534220e-002
+v -9.4297150e-002 1.2617744e-001 1.9224650e-002
+v -3.5207090e-002 1.2505219e-001 2.1635690e-002
+v -4.9495940e-002 7.3436340e-002 4.1673570e-002
+v -3.3064160e-002 7.6654840e-002 4.1277900e-002
+v -7.3157300e-003 7.3919590e-002 5.7971690e-002
+v 2.1850000e-005 7.3496040e-002 5.7696650e-002
+v 4.1934400e-003 7.2915170e-002 5.6298730e-002
+v -7.7256080e-002 1.4565854e-001 4.3122930e-002
+v 4.1073260e-002 8.8724320e-002 -9.7879400e-003
+v 3.7418710e-002 1.0850822e-001 3.3973000e-004
+v -5.5111380e-002 7.4687840e-002 4.1939740e-002
+v -4.2740230e-002 7.6995340e-002 4.2804080e-002
+v -6.8531190e-002 1.5630045e-001 2.0997710e-002
+v -9.9440200e-003 7.6343100e-002 5.7388560e-002
+v -3.2479200e-003 7.5710690e-002 5.8714640e-002
+v 1.3414380e-002 9.3073740e-002 5.1467750e-002
+v -7.3504440e-002 9.3883340e-002 -1.4751720e-002
+v -7.4471830e-002 1.3507476e-001 5.0688900e-002
+v -2.5851310e-002 1.2182948e-001 2.6079670e-002
+v -3.4022940e-002 1.7597076e-001 -3.7271600e-003
+v -7.5405850e-002 1.6839072e-001 -2.6792980e-002
+v -3.6658410e-002 7.5087300e-002 4.2006940e-002
+v -1.7795480e-002 7.7486190e-002 5.6087240e-002
+v -1.1378660e-002 7.9877150e-002 5.7698880e-002
+v -1.0415000e-004 7.6881950e-002 5.8190740e-002
+v 2.7381400e-003 7.9105680e-002 5.6719190e-002
+v 5.5681200e-003 7.6397140e-002 5.6327220e-002
+v -6.1895860e-002 1.5424247e-001 -1.9018600e-002
+v -7.2646960e-002 1.4098943e-001 4.6976640e-002
+v 1.5799740e-002 1.2901416e-001 1.3236870e-002
+v -1.1703420e-002 9.7355720e-002 5.1592080e-002
+v -5.8922160e-002 7.7545490e-002 4.2961390e-002
+v -5.3121320e-002 7.7912430e-002 4.3334920e-002
+v -5.0745740e-002 7.6148400e-002 4.3137630e-002
+v -4.7401820e-002 7.5550340e-002 4.2630140e-002
+v -4.5055620e-002 7.8796280e-002 4.2341310e-002
+v -3.9517650e-002 7.8127780e-002 4.2918620e-002
+v -1.5245570e-002 8.2940770e-002 5.6934590e-002
+v -1.4557790e-002 7.6582160e-002 5.6493250e-002
+v -5.9406000e-003 7.9038240e-002 5.7969830e-002
+v 3.7176540e-002 1.1064404e-001 1.8811330e-002
+v 2.3929700e-003 1.3162713e-001 1.1955100e-002
+v -9.3644210e-002 1.1789378e-001 1.8662080e-002
+v -6.3939810e-002 7.8621830e-002 4.2083520e-002
+v -4.5376460e-002 8.2383550e-002 4.3282120e-002
+v -3.6505460e-002 8.1152260e-002 4.3162320e-002
+v -3.3244340e-002 8.2266590e-002 4.1852180e-002
+v -3.0800650e-002 8.0068420e-002 4.1798070e-002
+v -2.0578500e-003 8.0998290e-002 5.7553840e-002
+v 8.1848100e-003 8.0756170e-002 5.5374510e-002
+v -1.2953370e-002 1.1593580e-001 3.8920230e-002
+v -7.8081470e-002 1.2351940e-001 5.2136990e-002
+v -2.6580930e-002 1.5567694e-001 -4.1963400e-003
+v -8.2471600e-002 1.1624130e-001 -2.3236300e-003
+v -2.7538480e-002 7.9964780e-002 4.7697210e-002
+v 1.2556400e-003 8.3845570e-002 5.7446440e-002
+v 6.1508300e-003 8.3406240e-002 5.6463500e-002
+v -6.2433240e-002 8.4035270e-002 4.4203120e-002
+v -5.9867170e-002 8.0540510e-002 4.3277090e-002
+v -5.5238340e-002 8.1999450e-002 4.4984770e-002
+v -5.4000400e-002 8.0568410e-002 4.4601460e-002
+v -5.0027020e-002 8.1311330e-002 4.4264180e-002
+v -4.1996120e-002 8.1083670e-002 4.2456150e-002
+v -3.9357940e-002 8.3631380e-002 4.3502350e-002
+v -8.6161480e-002 1.0838594e-001 1.8244920e-002
+v -8.6723010e-002 9.9917250e-002 3.5537100e-003
+v -2.2413700e-002 8.3283520e-002 5.5590700e-002
+v -1.6993180e-002 8.2555820e-002 5.7523880e-002
+v -1.2406010e-002 8.5222570e-002 5.7267780e-002
+v -7.4442100e-003 1.1693417e-001 3.9283850e-002
+v -2.1452000e-003 1.1143287e-001 4.2436620e-002
+v -7.5718220e-002 1.2522734e-001 5.3087330e-002
+v -7.7056660e-002 1.3193469e-001 5.2462430e-002
+v -6.1121040e-002 1.5569660e-001 2.2517050e-002
+v -3.7538540e-002 1.2744127e-001 1.5320870e-002
+v -2.0516700e-003 1.0093469e-001 4.5625920e-002
+v -6.4992150e-002 8.4550900e-002 4.4120060e-002
+v -5.7861950e-002 8.3944360e-002 4.4186030e-002
+v -4.5681080e-002 8.4988010e-002 4.4159500e-002
+v -3.5022640e-002 8.2888160e-002 4.2912760e-002
+v -2.9982010e-002 8.5402300e-002 4.3745080e-002
+v -8.8892260e-002 9.9209100e-002 9.5703200e-003
+v -1.9135300e-002 8.3474800e-002 5.7217390e-002
+v -8.3489710e-002 1.0724729e-001 7.5790000e-004
+v -7.0112800e-002 1.1790350e-001 5.2714160e-002
+v -3.5526320e-002 1.7595563e-001 -4.8676200e-003
+v -7.0831390e-002 1.2254425e-001 5.3274880e-002
+v 4.5133810e-002 9.3630690e-002 6.2336800e-003
+v -5.3616700e-002 8.5346850e-002 4.5332470e-002
+v -4.9000840e-002 8.6221680e-002 4.5352040e-002
+v -3.6744880e-002 8.6083690e-002 4.3612890e-002
+v -1.0872600e-002 8.8826770e-002 5.6665490e-002
+v -3.8450200e-003 8.4787810e-002 5.7197980e-002
+v -4.9020070e-002 1.1771293e-001 3.1581430e-002
+v -4.2914400e-002 1.1835991e-001 3.0645040e-002
+v -5.7684530e-002 1.5561695e-001 1.2983110e-002
+v -2.5411730e-002 1.2472533e-001 1.2886000e-004
+v 1.9012230e-002 1.2736197e-001 1.7786580e-002
+v -5.9498600e-002 8.8845470e-002 4.5109290e-002
+v -5.6931050e-002 8.8101500e-002 4.4692930e-002
+v 3.5765600e-003 1.3138981e-001 7.2086000e-003
+v -1.6683350e-002 8.7266690e-002 5.6741190e-002
+v -8.4980800e-003 8.3990470e-002 5.7605220e-002
+v 3.5078200e-003 8.6339520e-002 5.7048320e-002
+v -2.8398700e-002 1.8070650e-001 -7.8469500e-003
+v -7.6565830e-002 1.1674037e-001 5.1489350e-002
+v 1.7869430e-002 9.0898610e-002 4.8712940e-002
+v -4.0342100e-002 1.1669551e-001 3.2460200e-002
+v 5.9105700e-003 1.3140929e-001 1.6823750e-002
+v -8.5777550e-002 9.1701370e-002 -4.6970000e-005
+v -5.0372230e-002 8.8844660e-002 4.5188000e-002
+v -4.4434130e-002 8.7654530e-002 4.3477620e-002
+v -4.2056390e-002 8.6711520e-002 4.2534630e-002
+v -3.3058460e-002 8.6185500e-002 4.2560350e-002
+v -2.9241910e-002 9.0453360e-002 4.4236610e-002
+v -6.8964100e-003 8.4432910e-002 5.7168580e-002
+v -6.6210600e-003 9.0415250e-002 5.6879750e-002
+v -1.2439100e-003 8.9093200e-002 5.6552120e-002
+v 9.4076000e-003 9.0328050e-002 5.4214140e-002
+v 4.0194810e-002 1.0231597e-001 -2.0048600e-003
+v -8.6227130e-002 1.1466841e-001 2.2102000e-003
+v -8.9495490e-002 9.5632430e-002 1.4234810e-002
+v -6.7132160e-002 1.5709447e-001 -6.2032000e-003
+v -5.2935640e-002 9.0913520e-002 4.4568870e-002
+v -3.6744910e-002 8.8886950e-002 4.3312050e-002
+v -1.3626110e-002 8.9787930e-002 5.6674380e-002
+v 2.3337130e-002 1.2353449e-001 2.4874140e-002
+v -3.7053790e-002 1.2715094e-001 3.5474000e-004
+v -7.3696690e-002 1.5613015e-001 1.4359790e-002
+v -6.5592380e-002 9.1042400e-002 4.4092080e-002
+v -5.8997380e-002 9.2030670e-002 4.5335270e-002
+v -3.3238910e-002 8.8573580e-002 4.3697040e-002
+v -3.1834990e-002 9.0722970e-002 4.4173460e-002
+v -2.0022170e-002 8.8032110e-002 5.5589350e-002
+v -1.1213830e-002 9.2366370e-002 5.6105260e-002
+v 3.9108440e-002 1.0829072e-001 1.3142330e-002
+v 2.8675700e-002 1.1959600e-001 2.4545910e-002
+v -6.8940210e-002 1.5652777e-001 -1.9716000e-003
+v -6.2615110e-002 9.1126880e-002 4.5090730e-002
+v 3.0444560e-002 1.1886441e-001 2.0821750e-002
+v -1.5241090e-002 9.1821720e-002 5.5817230e-002
+v -5.6221700e-003 9.3235010e-002 5.5893630e-002
+v 4.7989900e-003 9.1654840e-002 5.4715170e-002
+v -6.8282400e-002 9.2376840e-002 4.2388730e-002
+v -5.5623730e-002 9.2187420e-002 4.5054970e-002
+v -5.1901030e-002 9.5457620e-002 4.3937650e-002
+v -4.8809030e-002 9.1083890e-002 4.4456690e-002
+v -4.5411560e-002 9.1002130e-002 4.3252770e-002
+v -4.4514550e-002 9.4860420e-002 4.2972490e-002
+v -3.9430320e-002 8.9597620e-002 4.3177890e-002
+v -3.5642240e-002 9.2617410e-002 4.4238490e-002
+v -1.2246000e-004 9.3201160e-002 5.5398380e-002
+v 9.5104600e-003 9.5483870e-002 5.0910600e-002
+v 2.1441660e-002 9.1354960e-002 4.8043360e-002
+v -8.9830300e-003 1.6926449e-001 -2.2683480e-002
+v -7.3019050e-002 1.5602104e-001 2.2419340e-002
+v -6.4760430e-002 1.5311588e-001 -2.0371200e-003
+v -6.9368510e-002 9.5242790e-002 4.2129000e-002
+v -6.0117140e-002 9.5552910e-002 4.4183820e-002
+v -2.9241690e-002 9.4290440e-002 4.4821190e-002
+v -2.6561430e-002 9.3289510e-002 4.4975420e-002
+v -1.4394030e-002 9.4587640e-002 5.3993500e-002
+v -8.8691600e-003 9.5400260e-002 5.4445980e-002
+v -1.2188700e-003 9.6201750e-002 5.3815910e-002
+v 4.0479000e-003 9.5817360e-002 5.2936770e-002
+v -4.6019400e-003 1.2428544e-001 3.3471960e-002
+v -7.8436460e-002 1.3928013e-001 4.8329360e-002
+v 1.0774610e-002 1.3079162e-001 1.4341740e-002
+v -5.6623730e-002 9.6322170e-002 4.3667910e-002
+v -3.6298870e-002 9.5695620e-002 4.3580310e-002
+v -2.4379930e-002 9.5866450e-002 4.4434530e-002
+v 1.0915500e-002 1.2633629e-001 2.9857020e-002
+v -5.8622700e-003 9.7350210e-002 5.2743650e-002
+v 1.6973450e-002 9.7106620e-002 4.7440920e-002
+v -6.7231980e-002 9.9173950e-002 4.1593880e-002
+v -5.4994210e-002 9.9640820e-002 4.2955230e-002
+v -4.8617990e-002 9.6452700e-002 4.4183060e-002
+v -5.5369000e-002 1.5442476e-001 1.6160650e-002
+v -9.4243550e-002 1.2207432e-001 2.3568470e-002
+v 1.3242990e-002 9.6738240e-002 4.8750160e-002
+v 2.0639290e-002 9.6602480e-002 4.6971000e-002
+v 7.3429700e-003 1.2098188e-001 3.5973430e-002
+v -1.3493870e-002 1.2882438e-001 5.9690700e-003
+v -2.0110640e-002 1.2504545e-001 2.3588310e-002
+v -6.9438450e-002 1.6479930e-001 -1.7218700e-002
+v -6.4028050e-002 9.7838670e-002 4.2565330e-002
+v -5.1996350e-002 9.9707850e-002 4.2716590e-002
+v -4.3990880e-002 9.9425460e-002 4.2383430e-002
+v -3.9738250e-002 1.0215357e-001 4.0574410e-002
+v -3.5931490e-002 9.9809950e-002 4.2335800e-002
+v -3.0867600e-002 9.6914680e-002 4.4651400e-002
+v -2.8342070e-002 9.7782680e-002 4.3761280e-002
+v -2.5622580e-002 9.8713420e-002 4.4210890e-002
+v -8.5236620e-002 1.1077356e-001 2.4537670e-002
+v 7.1936000e-003 9.8859470e-002 4.8419510e-002
+v 9.6509200e-003 1.0108782e-001 4.7373080e-002
+v 1.3487100e-002 1.0076420e-001 4.7454290e-002
+v 7.7389800e-003 1.3147500e-001 1.1682970e-002
+v 8.0905000e-004 1.1633319e-001 4.0167560e-002
+v -7.2652570e-002 1.6567918e-001 -1.8212480e-002
+v -5.6009400e-003 1.3076674e-001 1.0516060e-002
+v -2.6303720e-002 1.2518875e-001 1.7392980e-002
+v -4.7590430e-002 1.0081180e-001 4.2349150e-002
+v -4.1460830e-002 9.8544800e-002 4.1778620e-002
+v -3.3582070e-002 1.0383908e-001 4.0737990e-002
+v -2.2870240e-002 1.0284737e-001 4.3544750e-002
+v -2.2361970e-002 9.8207610e-002 4.4765940e-002
+v -1.8870510e-002 9.8973200e-002 4.4489280e-002
+v -7.1433690e-002 7.7573520e-002 3.8060760e-002
+v -7.3001150e-002 1.1826712e-001 5.3034590e-002
+v -6.8466430e-002 1.3498146e-001 -8.3359800e-003
+v -7.4683810e-002 1.0786100e-001 -9.0477100e-003
+v -6.4958960e-002 1.5852021e-001 -1.2595320e-002
+v -7.8931700e-002 1.5093057e-001 3.5151900e-002
+v -7.4113550e-002 9.9442520e-002 3.8337710e-002
+v -7.0456930e-002 1.0098777e-001 3.9794060e-002
+v -5.9058760e-002 1.0041260e-001 4.2725130e-002
+v -4.9187330e-002 1.0452012e-001 4.0301390e-002
+v -2.9151180e-002 1.0197369e-001 4.2633060e-002
+v -1.1599720e-002 1.0107813e-001 4.4191660e-002
+v 5.1450400e-003 1.0163906e-001 4.5423010e-002
+v -5.1495700e-002 1.0496738e-001 4.0347210e-002
+v -2.0218210e-002 1.0214391e-001 4.3701160e-002
+v 4.2515900e-003 1.0523743e-001 4.2563550e-002
+v 1.6832800e-002 1.0337487e-001 4.5287270e-002
+v -2.5661080e-002 1.2562669e-001 4.5537500e-003
+v -7.2141950e-002 1.0536685e-001 3.7523210e-002
+v -6.4984570e-002 1.0371550e-001 4.0647810e-002
+v -6.0652480e-002 1.0467197e-001 4.0906390e-002
+v -5.5308980e-002 1.0365394e-001 4.1516690e-002
+v -4.4243240e-002 1.0431726e-001 4.1339990e-002
+v -1.5513340e-002 1.0436131e-001 4.2919420e-002
+v -7.6323200e-003 1.0304531e-001 4.3710640e-002
+v -7.8046900e-003 1.0516619e-001 4.3825460e-002
+v 9.7163200e-003 1.0523506e-001 4.3603830e-002
+v 3.0300390e-002 1.1553645e-001 2.8685010e-002
+v -4.7496910e-002 1.0635662e-001 4.0165640e-002
+v -3.8978950e-002 1.0683037e-001 3.8247660e-002
+v -2.5869310e-002 1.0426705e-001 4.2207540e-002
+v -1.8057930e-002 1.0503919e-001 4.2802830e-002
+v -1.5180030e-002 1.0807750e-001 4.2350430e-002
+v -3.8981500e-003 1.0566175e-001 4.4047190e-002
+v 2.6820000e-005 1.0446731e-001 4.3775910e-002
+v 1.1978350e-002 1.0403629e-001 4.5396310e-002
+v 1.5004970e-002 1.0726898e-001 4.1811990e-002
+v 2.6488060e-002 1.2230287e-001 2.0398110e-002
+v -3.6225630e-002 1.0634244e-001 3.8644860e-002
+v -2.1126780e-002 1.0932290e-001 4.0715320e-002
+v -1.2819810e-002 1.0457100e-001 4.3465690e-002
+v 5.2847900e-003 1.0943666e-001 4.1674980e-002
+v 8.9403700e-003 1.0710645e-001 4.1243400e-002
+v -5.1839670e-002 1.6062039e-001 7.1421300e-003
+v -5.4201370e-002 1.1451730e-001 3.4843990e-002
+v 1.3226250e-002 1.2958070e-001 1.9689610e-002
+v -6.9382410e-002 1.0865787e-001 3.7507800e-002
+v -6.7691040e-002 1.0734145e-001 3.8018440e-002
+v -6.3782400e-002 1.1037270e-001 3.7579790e-002
+v -5.0749390e-002 1.0928682e-001 3.8297580e-002
+v -9.3936200e-003 1.0742813e-001 4.3454570e-002
+v 1.1760100e-003 1.0932531e-001 4.2662800e-002
+v 9.8020300e-003 1.1003994e-001 3.9945400e-002
+v 2.0131290e-002 1.0732778e-001 4.0323840e-002
+v -2.7872800e-003 1.0577531e-001 -2.2459030e-002
+v -5.4996890e-002 1.0774199e-001 3.9424590e-002
+v -4.5966740e-002 1.0905146e-001 3.8754110e-002
+v -4.2324540e-002 1.0737278e-001 3.9456440e-002
+v -3.2161240e-002 1.0896504e-001 3.8102720e-002
+v -3.0770180e-002 1.1597313e-001 3.2858800e-002
+v -1.1608610e-002 1.0983707e-001 4.2475330e-002
+v -2.9428320e-002 9.3166620e-002 -2.4931860e-002
+v -8.0043570e-002 9.2080160e-002 -9.4198200e-003
+v -4.9797430e-002 1.1342104e-001 3.5117920e-002
+v -4.3723850e-002 1.6191369e-001 5.7713400e-003
+v -5.7981740e-002 1.0943152e-001 3.7997640e-002
+v -4.1491180e-002 1.1224766e-001 3.5873450e-002
+v -2.4929830e-002 1.1592775e-001 3.4094730e-002
+v -2.0881690e-002 1.1409528e-001 3.7872990e-002
+v -7.5519700e-003 1.1183813e-001 4.2039690e-002
+v 3.7667200e-003 1.1240547e-001 4.1494710e-002
+v -6.2829620e-002 1.5189480e-001 -9.2373400e-003
+v -5.9195950e-002 1.1320797e-001 3.6234680e-002
+v -5.1079080e-002 9.3892810e-002 -2.1761690e-002
+v -7.3945370e-002 8.4374880e-002 -1.5154490e-002
+v -7.2146240e-002 1.3486431e-001 -7.7592200e-003
+v -1.9408870e-002 1.7041104e-001 -2.0994830e-002
+v -5.5530450e-002 1.4905531e-001 -1.9602100e-003
+v 1.6688460e-002 3.6976600e-002 4.3000600e-002
+v -5.2277330e-002 1.1775075e-001 3.3769460e-002
+v -6.9201380e-002 9.3039200e-002 -1.6486120e-002
+v 2.6579210e-002 1.1702438e-001 3.0867940e-002
+v -2.3574310e-002 3.7036910e-002 5.4144750e-002
+v -7.3775100e-003 3.8988430e-002 4.8929450e-002
+v 1.3234660e-002 3.8453060e-002 4.4501470e-002
+v 1.9487350e-002 4.0809290e-002 4.2641060e-002
+v -6.3953930e-002 1.4694729e-001 3.8484200e-002
+v -4.9579470e-002 3.6096540e-002 4.5955360e-002
+v -4.3323650e-002 3.6286400e-002 4.4042360e-002
+v -2.9047200e-002 1.2556338e-001 7.7617700e-003
+v -1.7343100e-003 3.9476800e-002 4.7262900e-002
+v -3.1358130e-002 1.5362199e-001 -4.6738900e-003
+v 2.5822000e-003 1.0747582e-001 -2.0606030e-002
+v -5.6802300e-002 1.4514674e-001 3.1740300e-002
+v -5.6464330e-002 3.7683110e-002 4.6819640e-002
+v -5.0964750e-002 3.8312290e-002 4.6286140e-002
+v -5.0980410e-002 1.3486613e-001 2.7585000e-002
+v -2.5647410e-002 3.8860730e-002 5.4161390e-002
+v -2.2542110e-002 4.0615780e-002 5.3986030e-002
+v -1.7618010e-002 3.8911170e-002 5.2403440e-002
+v -1.9711750e-002 1.6829145e-001 -1.3020960e-002
+v 2.3780070e-002 9.5222940e-002 4.6347330e-002
+v 1.4744290e-002 4.2716950e-002 4.4510310e-002
+v 2.1691360e-002 4.0161530e-002 4.0846450e-002
+v -6.4067240e-002 9.0172190e-002 -1.8855520e-002
+v 2.0319150e-002 1.0041961e-001 4.5760520e-002
+v -3.6425000e-002 9.3630690e-002 -2.3534630e-002
+v -1.4981170e-002 4.2571420e-002 5.1404530e-002
+v -5.7335340e-002 1.2340101e-001 4.0231470e-002
+v -5.4172560e-002 1.2337919e-001 3.7576440e-002
+v 2.2625210e-002 4.3621680e-002 4.0904580e-002
+v 2.8810520e-002 4.3352290e-002 3.2157720e-002
+v -4.2764160e-002 1.5727487e-001 5.2016200e-003
+v 9.2231900e-003 4.4125090e-002 4.5057440e-002
+v 1.5048210e-002 4.5755840e-002 4.3793870e-002
+v -6.3757290e-002 1.0251144e-001 -1.7484400e-002
+v -3.4070430e-002 1.6148975e-001 -1.3786960e-002
+v -8.2191500e-002 7.5610200e-002 1.6542620e-002
+v -6.6299420e-002 1.2337119e-001 5.0615920e-002
+v -1.5510100e-002 4.5283110e-002 5.0653040e-002
+v 1.8928020e-002 4.4249610e-002 4.3009830e-002
+v 2.5821800e-002 4.6326610e-002 3.8277230e-002
+v 2.7268700e-002 4.4547790e-002 3.6152520e-002
+v -4.5301340e-002 1.5695057e-001 7.2036900e-003
+v 2.3855760e-002 1.0616625e-001 3.9378080e-002
+v 2.1632670e-002 4.8127270e-002 4.0694430e-002
+v 4.3785360e-002 4.8803700e-002 3.1343420e-002
+v 4.8074790e-002 4.8969960e-002 2.8165490e-002
+v 5.2663090e-002 4.7673620e-002 2.1201270e-002
+v -5.2722450e-002 4.4722850e-002 4.4143250e-002
+v -3.0071610e-002 1.7258324e-001 -6.3597700e-003
+v -3.4508050e-002 1.5447469e-001 1.6504600e-003
+v 1.0629710e-002 4.6711810e-002 4.6472020e-002
+v 1.6743440e-002 4.8439000e-002 4.3678630e-002
+v 2.8827050e-002 9.2133370e-002 4.3920090e-002
+v -5.9937100e-002 1.2726188e-001 4.0771270e-002
+v -3.6752090e-002 1.5802075e-001 4.1862000e-003
+v -3.7885390e-002 1.6199719e-001 2.4686000e-004
+v -2.2047790e-002 1.8348586e-001 -1.2094990e-002
+v -2.4364620e-002 1.8096836e-001 -9.8312000e-003
+v -4.4882280e-002 1.5052959e-001 7.6451700e-003
+v 2.6996760e-002 5.1317780e-002 3.8752040e-002
+v 4.7735750e-002 5.2751040e-002 3.0797290e-002
+v 5.1703790e-002 4.8857380e-002 2.4147970e-002
+v -6.7504360e-002 1.1424088e-001 4.8036050e-002
+v -1.6257520e-002 1.6031250e-001 -9.6926000e-003
+v -6.3926300e-002 1.6792441e-001 -4.0730420e-002
+v -4.1665290e-002 1.4996141e-001 4.5405000e-003
+v -3.5203230e-002 1.6493551e-001 -2.6810000e-003
+v 4.1318770e-002 9.9496740e-002 2.4275750e-002
+v 1.4055220e-002 5.2523910e-002 4.8593880e-002
+v 1.9421220e-002 5.1321300e-002 4.4798910e-002
+v 2.3677990e-002 5.1474390e-002 4.1053270e-002
+v 3.4258130e-002 5.1930810e-002 3.2757880e-002
+v 5.5957340e-002 5.3147410e-002 2.3197720e-002
+v -3.9937960e-002 1.4922850e-001 1.6017200e-003
+v -4.6988800e-002 1.2600802e-001 2.6985500e-002
+v -2.7708370e-002 9.0081290e-002 -3.1911460e-002
+v 1.9204630e-002 5.5166510e-002 4.7722150e-002
+v 2.1886000e-002 5.3927560e-002 4.5102460e-002
+v 3.1286270e-002 5.2863840e-002 3.6913620e-002
+v 4.6661160e-002 5.4719230e-002 3.1976810e-002
+v 5.1823730e-002 5.3276700e-002 2.7927010e-002
+v -2.9264880e-002 1.6140418e-001 -2.1039500e-003
+v -6.8700770e-002 1.4463537e-001 4.3041630e-002
+v -5.6070060e-002 1.5000706e-001 2.9867640e-002
+v 4.4717850e-002 9.4802660e-002 1.2024710e-002
+v -4.1804090e-002 1.5582081e-001 6.4548200e-003
+v -6.8369340e-002 1.2289287e-001 5.2437860e-002
+v -6.4114810e-002 9.5509880e-002 -1.8114610e-002
+v -1.8383130e-002 1.8543664e-001 -1.7136370e-002
+v 1.1745400e-002 5.6678340e-002 5.1914060e-002
+v -5.9375360e-002 1.1998238e-001 4.0548240e-002
+v 5.9092080e-002 5.7956980e-002 2.0270120e-002
+v 4.3547740e-002 9.7389400e-002 1.7314650e-002
+v -2.6291780e-002 1.5963381e-001 -5.1845000e-004
+v 1.4904780e-002 5.6350380e-002 4.9522780e-002
+v 2.4286200e-002 5.4958580e-002 4.3086850e-002
+v 2.8952610e-002 5.6125250e-002 4.0388970e-002
+v -4.9507770e-002 1.2949500e-001 3.0259270e-002
+v 4.0824790e-002 9.5170220e-002 2.8657920e-002
+v 1.7774800e-002 5.8243780e-002 4.8864720e-002
+v 3.3573840e-002 5.8515260e-002 3.8310990e-002
+v 3.6385040e-002 5.6996480e-002 3.3601460e-002
+v -6.4205010e-002 1.2243894e-001 4.8008340e-002
+v -6.5424500e-002 1.4011279e-001 4.1308960e-002
+v 5.0801340e-002 5.7308080e-002 3.0001390e-002
+v 5.6671750e-002 5.6970820e-002 2.4291920e-002
+v -4.9349930e-002 1.4913519e-001 1.1274060e-002
+v -6.9760570e-002 1.3442855e-001 4.8265220e-002
+v 1.9537060e-002 6.0003780e-002 4.8576140e-002
+v 2.7013910e-002 5.9952790e-002 4.3454420e-002
+v 5.7679430e-002 6.1392970e-002 2.4201790e-002
+v -5.6916540e-002 1.2623512e-001 3.9426610e-002
+v 2.3469280e-002 1.1656262e-001 3.3537270e-002
+v -5.8298640e-002 1.3885500e-001 3.2937460e-002
+v 6.4598400e-003 6.0297430e-002 5.4780030e-002
+v 1.0406020e-002 5.9162400e-002 5.2484370e-002
+v 2.3183950e-002 5.8654360e-002 4.5871060e-002
+v 3.3040360e-002 6.1773840e-002 3.9781440e-002
+v -6.4348220e-002 1.2628088e-001 4.6650200e-002
+v -5.7031440e-002 1.1562007e-001 3.6494880e-002
+v 5.4451560e-002 5.8342890e-002 2.7653010e-002
+v -3.0134400e-002 1.7011322e-001 -7.3591600e-003
+v -3.7077100e-002 1.5986369e-001 1.6096500e-003
+v -5.6032760e-002 1.3731083e-001 3.1970590e-002
+v -6.7676470e-002 1.4150325e-001 4.3868140e-002
+v 9.9911700e-003 6.2735270e-002 5.4009240e-002
+v 1.4521510e-002 6.1382890e-002 5.0500900e-002
+v 3.0051740e-002 6.2169610e-002 4.1545810e-002
+v 3.7519170e-002 6.1062710e-002 3.4366020e-002
+v 5.3944010e-002 6.1391550e-002 2.8268530e-002
+v 5.9119900e-002 6.3128810e-002 2.1561830e-002
+v -2.4366390e-002 1.7693266e-001 -1.1719630e-002
+v -1.3253420e-002 1.6627152e-001 -1.4120370e-002
+v 3.9218740e-002 1.0669250e-001 2.0450190e-002
+v -1.7968980e-002 1.8078031e-001 -1.8103430e-002
+v 2.1902390e-002 6.0875970e-002 4.7282360e-002
+v 3.5341750e-002 6.1630030e-002 3.7606020e-002
+v -6.2145620e-002 1.3599775e-001 3.6700970e-002
+v 5.6820620e-002 6.3691150e-002 2.5286090e-002
+v -3.2800040e-002 1.5948699e-001 2.1962800e-003
+v 1.1212140e-002 6.6584120e-002 5.3982180e-002
+v 1.2919590e-002 6.4203580e-002 5.2441150e-002
+v 2.0126950e-002 6.3851330e-002 4.7919660e-002
+v 3.5971760e-002 6.6669610e-002 3.7781400e-002
+v 3.9906940e-002 6.4361260e-002 3.1686660e-002
+v -6.6702350e-002 1.3210600e-001 4.5480940e-002
+v -4.1601430e-002 1.5978000e-001 3.5374700e-003
+v 3.3044580e-002 1.0766252e-001 3.1916150e-002
+v 2.4672100e-002 6.3694500e-002 4.5204640e-002
+v 2.6108660e-002 6.8007640e-002 4.3902690e-002
+v 3.3363940e-002 6.7054760e-002 3.9729480e-002
+v 4.2915790e-002 6.6707700e-002 2.6994720e-002
+v 5.4714960e-002 6.4697160e-002 2.6979680e-002
+v -1.6530940e-002 1.6325000e-001 -9.2475200e-003
+v -1.7891600e-002 1.6113800e-001 -6.7072700e-003
+v 4.1118120e-002 9.7491260e-002 -3.9756700e-003
+v 2.3386770e-002 7.0075990e-002 4.7012620e-002
+v 3.8102900e-002 6.5678440e-002 3.5132520e-002
+v 1.0145240e-002 1.2221678e-001 3.4718950e-002
+v 5.8392410e-002 6.6741240e-002 2.1979460e-002
+v 3.8302050e-002 8.4549140e-002 -1.4478830e-002
+v 3.4126440e-002 9.7053980e-002 3.7590390e-002
+v -3.1355740e-002 1.5809888e-001 1.9128800e-003
+v -5.8259510e-002 1.4099493e-001 3.2440640e-002
+v -6.6817230e-002 1.1951525e-001 5.1490220e-002
+v -6.8090040e-002 1.1647050e-001 5.1151230e-002
+v 1.6568300e-002 6.6269890e-002 5.1009890e-002
+v 2.9362870e-002 6.6509780e-002 4.2289380e-002
+v 3.7027180e-002 9.3949630e-002 -1.1674040e-002
+v 5.6412730e-002 6.7659930e-002 2.3969320e-002
+v -6.1295740e-002 1.4519988e-001 3.7137830e-002
+v 8.3873000e-003 1.1336223e-001 3.9792610e-002
+v 1.1807030e-002 7.0920980e-002 5.4240490e-002
+v 2.9741730e-002 7.0647100e-002 4.1653890e-002
+v 3.6294410e-002 7.1220700e-002 3.7114610e-002
+v 3.9899680e-002 7.0294820e-002 3.2720020e-002
+v -6.2763130e-002 1.3778012e-001 3.6678590e-002
+v -1.5815440e-002 1.7504938e-001 -1.8654160e-002
+v -9.2268990e-002 1.1475156e-001 1.7017380e-002
+v -9.4964000e-004 1.0141111e-001 4.4290070e-002
+v -6.3712920e-002 1.1274250e-001 3.8006760e-002
+v -6.1096020e-002 1.1701650e-001 3.9654020e-002
+v 2.0991870e-002 6.9335450e-002 4.9003540e-002
+v 2.5658530e-002 7.0550460e-002 4.4539930e-002
+v 3.2978560e-002 7.3500690e-002 4.0486510e-002
+v 4.2156130e-002 6.9717580e-002 2.8318230e-002
+v -5.5516860e-002 1.2956070e-001 3.6598450e-002
+v -4.0802290e-002 1.6436059e-001 3.7448800e-003
+v -6.2546500e-003 1.0121650e-001 4.4322030e-002
+v -1.0986820e-002 1.6621199e-001 -1.6047550e-002
+v -3.0351420e-002 1.6448158e-001 -5.3291400e-003
+v 2.6110920e-002 1.0088990e-001 4.1733260e-002
+v -6.5599940e-002 1.1329504e-001 4.2318710e-002
+v 2.8814660e-002 9.6712680e-002 4.2257700e-002
+v 1.5263280e-002 7.1571940e-002 5.2717390e-002
+v 2.8982400e-002 7.4088480e-002 4.3447240e-002
+v 4.4872540e-002 7.5516710e-002 2.3155250e-002
+v -7.8225230e-002 1.4962481e-001 -2.5019400e-003
+v -4.6094940e-002 1.5296850e-001 9.0029700e-003
+v -5.2369030e-002 1.4682913e-001 1.8934650e-002
+v -2.1592100e-002 1.5763440e-001 -6.8623600e-003
+v 1.7176770e-002 7.3066230e-002 5.1826600e-002
+v 2.2687500e-002 7.5149180e-002 4.9312500e-002
+v 3.5472040e-002 7.3076670e-002 3.8482270e-002
+v -8.9480840e-002 1.3839976e-001 2.5061450e-002
+v -5.3216730e-002 1.3221978e-001 3.2978380e-002
+v -3.7776780e-002 1.5551947e-001 4.3700800e-003
+v -9.0549380e-002 1.3511875e-001 2.1680550e-002
+v -6.3366580e-002 1.3037076e-001 4.1669940e-002
+v 1.4074270e-002 7.6651720e-002 5.4221350e-002
+v 1.8109790e-002 7.5806590e-002 5.2488260e-002
+v 4.2209940e-002 7.8861480e-002 2.9187200e-002
+v -5.2115930e-002 1.4179906e-001 2.0510310e-002
+v 2.9063090e-002 1.1149602e-001 3.3805790e-002
+v -5.4731460e-002 1.4267229e-001 2.8980480e-002
+v 2.5903640e-002 7.5536040e-002 4.6416650e-002
+v 3.1298760e-002 7.5907440e-002 4.2699060e-002
+v 3.8446170e-002 7.5649430e-002 3.5050640e-002
+v 4.6351670e-002 7.4079520e-002 1.8354320e-002
+v -4.7656560e-002 1.3077525e-001 2.5523570e-002
+v -1.1447430e-002 1.7131059e-001 -1.9602980e-002
+v -3.6647240e-002 1.6640131e-001 -2.8167000e-004
+v -4.6653530e-002 1.5917824e-001 7.8019000e-003
+v -4.5569890e-002 1.4663612e-001 5.6514200e-003
+v 4.1438880e-002 9.2365100e-002 -7.4587000e-003
+v -6.4287420e-002 1.3463625e-001 3.9945640e-002
+v -6.1128890e-002 1.3178328e-001 3.8915910e-002
+v -4.7843540e-002 1.2215063e-001 2.8833160e-002
+v -4.9536830e-002 1.2491344e-001 3.1778440e-002
+v -7.1135380e-002 1.3817656e-001 4.7853960e-002
+v 1.0113870e-002 7.6468110e-002 5.5256790e-002
+v 1.7897450e-002 7.9516550e-002 5.2759530e-002
+v 2.1740850e-002 8.0250650e-002 5.0425390e-002
+v 2.5271590e-002 7.8724920e-002 4.8026570e-002
+v 3.0885040e-002 7.8999480e-002 4.3388770e-002
+v -6.2441930e-002 1.4084781e-001 3.6965840e-002
+v -6.2165060e-002 1.5666850e-001 -1.7837760e-002
+v 2.0657260e-002 1.0416830e-001 4.3004680e-002
+v -6.3602800e-002 1.1571453e-001 4.2572290e-002
+v 1.4424020e-002 8.0085500e-002 5.3755600e-002
+v 2.8779340e-002 8.2553250e-002 4.4527350e-002
+v 4.4450130e-002 8.1846900e-002 2.4552920e-002
+v 4.5541990e-002 8.3338380e-002 1.9700850e-002
+v -4.9665810e-002 1.2063801e-001 3.2163270e-002
+v -2.9177290e-002 1.7619959e-001 -5.6241100e-003
+v -5.8203130e-002 1.3270975e-001 3.6918680e-002
+v 3.8997050e-002 9.7088220e-002 -7.7799300e-003
+v -5.4725800e-002 1.2071262e-001 3.7451450e-002
+v 1.3189120e-002 8.4211180e-002 5.3065830e-002
+v -1.9926300e-002 1.6489742e-001 -9.9900200e-003
+v 2.0153130e-002 1.1849719e-001 3.4271250e-002
+v -5.5859940e-002 1.1774313e-001 3.7253480e-002
+v 1.8045260e-002 8.3623160e-002 5.1285840e-002
+v -6.3757130e-002 1.5912175e-001 -5.0155730e-002
+v -1.8527620e-002 1.7653197e-001 -1.7043540e-002
+v 2.8734400e-002 1.0360053e-001 3.8035240e-002
+v 4.1414010e-002 1.0284216e-001 1.6578920e-002
+v 2.4411730e-002 9.8016880e-002 4.4687400e-002
+v 2.0925180e-002 8.6311430e-002 4.9433120e-002
+v 3.0445010e-002 8.4959560e-002 4.3011090e-002
+v 3.3030090e-002 8.3781640e-002 4.1636930e-002
+v 3.6975090e-002 7.9876480e-002 3.7198390e-002
+v -7.7721460e-002 1.1355888e-001 4.8155990e-002
+v 2.9250000e-002 1.0651935e-001 3.6590330e-002
+v -5.3078180e-002 1.3754688e-001 2.8266470e-002
+v -6.2990590e-002 1.1999459e-001 4.5235530e-002
+v -6.5398320e-002 1.1751956e-001 4.8735570e-002
+v 3.3373910e-002 1.1227890e-001 2.7788130e-002
+v 3.8413590e-002 8.7489930e-002 3.5185850e-002
+v -6.1945930e-002 1.6479234e-001 -5.6647670e-002
+v -2.2876480e-002 1.7392813e-001 -1.3431140e-002
+v 4.3766230e-002 8.8390020e-002 -3.5708800e-003
+v 3.9291530e-002 1.0125969e-001 2.7550520e-002
+v 1.0936230e-002 8.6027290e-002 5.4732670e-002
+v 2.4108720e-002 8.4492600e-002 4.8292310e-002
+v 3.6758390e-002 9.9195470e-002 3.2837670e-002
+v -5.1941640e-002 1.2565987e-001 3.4587860e-002
+v -3.1582110e-002 1.6641850e-001 -5.7320000e-003
+v 7.6405900e-003 8.6427230e-002 5.6117850e-002
+v 1.6771020e-002 8.8644690e-002 5.0522960e-002
+v 3.4404610e-002 8.6932850e-002 4.0574270e-002
+v 3.6143820e-002 8.4439200e-002 3.7936930e-002
+v 4.1258830e-002 1.0361081e-001 2.6760600e-003
+v 2.4766140e-002 1.1081111e-001 3.6728360e-002
+v -2.2601590e-002 1.6250449e-001 -6.0717000e-003
+v -1.2893670e-002 1.7879041e-001 -2.2624750e-002
+v -2.4939150e-002 1.7031135e-001 -1.1329700e-002
+v -4.8468630e-002 1.4559606e-001 8.3661500e-003
+v 1.2534490e-002 8.9593930e-002 5.3394630e-002
+v 2.5872860e-002 8.8482290e-002 4.6655260e-002
+v 3.2756470e-002 8.8969130e-002 4.2215450e-002
+v -2.3343620e-002 1.6103450e-001 -3.1862400e-003
+v -9.2594970e-002 1.1943826e-001 2.6802950e-002
+v -7.4314840e-002 1.3761738e-001 -6.6698800e-003
+v -9.2499230e-002 1.2131500e-001 2.9256200e-002
+v -7.7378260e-002 1.5764266e-001 -1.4133650e-002
+v -9.2907340e-002 1.2307021e-001 3.6523230e-002
+v 2.8423340e-002 8.8011080e-002 4.4234200e-002
+v 3.5251680e-002 9.0836820e-002 3.9183920e-002
+v 1.5760560e-002 9.3203560e-002 4.9939310e-002
+v 3.8785530e-002 9.4954300e-002 3.2520220e-002
+v -6.1511220e-002 1.2373565e-001 4.3062680e-002
+v -6.8145120e-002 1.2748676e-001 5.0148970e-002
+v -2.0616710e-002 1.8237588e-001 -1.4299100e-002
+v 1.5137190e-002 1.1571495e-001 3.7031980e-002
+v -5.0718270e-002 1.5276300e-001 1.1816680e-002
+v 3.0168690e-002 1.0048686e-001 3.9404710e-002
+v -8.7426500e-002 9.5469530e-002 4.0312400e-003
+v -6.0010390e-002 1.4284463e-001 3.5449690e-002
+v -5.8603310e-002 1.4637237e-001 3.3808800e-002
+v 3.2411650e-002 9.3736150e-002 4.0890240e-002
+v -7.5917780e-002 1.4997690e-001 -1.6842050e-002
+v 1.8596570e-002 3.5293940e-002 -8.6782200e-003
+v 1.7209800e-002 3.5259400e-002 -1.4685160e-002
+v 4.4326540e-002 9.0818120e-002 2.2097520e-002
+v 3.8335910e-002 3.8830830e-002 3.0938100e-003
+v 2.2192920e-002 3.6775320e-002 -2.0919300e-003
+v 1.9636020e-002 3.8234010e-002 -1.2507670e-002
+v 2.3682120e-002 3.9762540e-002 3.7148760e-002
+v 4.6693280e-002 4.2465320e-002 6.5649500e-003
+v 2.1621110e-002 3.7657240e-002 -4.7021600e-003
+v 1.6638610e-002 3.8196090e-002 -1.9884930e-002
+v -9.0253980e-002 1.1366307e-001 3.7720210e-002
+v -9.0593870e-002 1.1373094e-001 1.0276770e-002
+v -6.2541690e-002 1.7679461e-001 -5.7821820e-002
+v -1.1091940e-002 1.7992082e-001 -2.5996430e-002
+v -6.2263130e-002 1.5219935e-001 -2.2578880e-002
+v -4.2276760e-002 9.4982570e-002 -2.2562420e-002
+v 4.3293410e-002 4.1864140e-002 2.0634400e-003
+v 4.3779590e-002 4.4530720e-002 -1.2622500e-003
+v 2.1696990e-002 4.0427270e-002 -9.4629500e-003
+v -1.1183700e-002 1.6450000e-001 -1.6151690e-002
+v -6.2372570e-002 1.5313041e-001 -2.8997120e-002
+v -9.2489300e-003 1.7725850e-001 -2.8270200e-002
+v 4.1477400e-002 8.5509410e-002 -9.1575000e-003
+v -8.1268710e-002 1.0879438e-001 2.9440660e-002
+v 4.9575680e-002 4.3815900e-002 1.4582960e-002
+v 5.2987960e-002 4.7747690e-002 5.0420000e-003
+v 2.1977540e-002 4.2855330e-002 -1.4536230e-002
+v 1.8505700e-002 3.8294100e-002 -1.7136500e-002
+v -3.5100500e-002 1.5203437e-001 -1.3279000e-004
+v 4.8749130e-002 4.5265000e-002 2.3023500e-003
+v 3.1912900e-002 9.9870060e-002 -1.4620980e-002
+v -1.4222520e-002 1.6167426e-001 -1.3349060e-002
+v -4.8663640e-002 1.3638523e-001 6.8063900e-003
+v -9.5837200e-003 1.7426102e-001 -2.8390760e-002
+v 5.2801850e-002 4.6539940e-002 1.0427720e-002
+v 5.1433800e-002 4.8485200e-002 1.0401000e-003
+v 2.3911240e-002 9.8021670e-002 -2.0807290e-002
+v 2.4567060e-002 4.4130110e-002 -1.0820840e-002
+v 2.0356810e-002 4.3662400e-002 -2.0456280e-002
+v -2.1882420e-002 1.1087418e-001 -1.9695320e-002
+v -5.3831800e-002 1.4981693e-001 2.5066610e-002
+v 5.4114210e-002 4.7773090e-002 1.7484000e-002
+v 5.6730570e-002 5.0515740e-002 1.0627080e-002
+v 4.5941820e-002 4.8138820e-002 -3.8715700e-003
+v -8.3817760e-002 1.1109094e-001 2.8524490e-002
+v 2.9207770e-002 4.7450250e-002 -8.5081800e-003
+v 2.8454920e-002 4.8067390e-002 -1.2847240e-002
+v 2.6637260e-002 4.7607100e-002 -1.6427740e-002
+v 2.2040110e-002 4.4992500e-002 -1.7528500e-002
+v 1.9120080e-002 4.7167750e-002 -2.2114680e-002
+v -1.5782200e-002 1.0072957e-001 -2.3724130e-002
+v -6.2514170e-002 1.7213119e-001 -5.2788100e-002
+v -6.2345600e-002 1.4745498e-001 -7.6600200e-003
+v 4.5598180e-002 8.8151720e-002 1.3124070e-002
+v -4.9422610e-002 1.4283525e-001 8.9728300e-003
+v -8.2761860e-002 1.1162341e-001 4.4221460e-002
+v -5.2166220e-002 1.5013661e-001 1.7448750e-002
+v -6.3616740e-002 1.4801371e-001 -2.0170260e-002
+v -5.1492690e-002 1.3796388e-001 2.3662180e-002
+v -6.1517580e-002 1.7517449e-001 -6.0631700e-002
+v 5.6524870e-002 5.0125660e-002 1.5564490e-002
+v 5.5257900e-002 5.1416260e-002 3.2062600e-003
+v 5.0318130e-002 5.2786370e-002 -3.4166300e-003
+v -6.2681950e-002 1.6744086e-001 -4.5713890e-002
+v 5.6520150e-002 5.1179900e-002 1.9940560e-002
+v 5.6907980e-002 5.1578130e-002 7.2538300e-003
+v 5.2854160e-002 5.1898670e-002 -6.2070000e-004
+v -3.8921140e-002 3.3767390e-002 -2.9042560e-002
+v 2.9740700e-002 5.0324690e-002 -1.3990860e-002
+v -6.8796190e-002 3.5117720e-002 -5.2067400e-003
+v 5.8826020e-002 5.5503780e-002 1.8647920e-002
+v -2.6160570e-002 1.2309988e-001 -4.4735500e-003
+v -5.3341960e-002 1.4401200e-001 2.4261390e-002
+v 5.8177390e-002 5.2821320e-002 1.5182420e-002
+v 5.9798140e-002 5.6840180e-002 1.3342730e-002
+v 5.4549870e-002 5.6044630e-002 -6.6158000e-004
+v 2.6775460e-002 5.1423450e-002 -2.0234060e-002
+v -8.6960400e-003 1.7291588e-001 -2.6708770e-002
+v -7.7039560e-002 7.1967020e-002 2.6405070e-002
+v -6.3069890e-002 1.5897471e-001 -4.2951850e-002
+v 3.5706690e-002 5.6083040e-002 -8.9993300e-003
+v 3.2600380e-002 5.3707520e-002 -1.1006150e-002
+v 2.9739960e-002 5.2538430e-002 -1.6224950e-002
+v 5.9238530e-002 5.6362780e-002 9.4530800e-003
+v 5.7421750e-002 5.6012210e-002 4.0245600e-003
+v 2.9062990e-002 5.5210580e-002 -1.8042060e-002
+v -1.7224410e-002 9.5214090e-002 -3.2085300e-002
+v -8.5911380e-002 1.0968787e-001 7.6582400e-003
+v 6.0594930e-002 6.1677210e-002 1.5591560e-002
+v 5.9531640e-002 6.0504600e-002 5.8397000e-003
+v 5.7306470e-002 5.9944620e-002 1.8886400e-003
+v 3.8829380e-002 5.9839830e-002 -6.4252500e-003
+v 3.0662770e-002 5.7300390e-002 -1.6518370e-002
+v -2.7762070e-002 1.2068537e-001 -9.0152900e-003
+v -8.8194590e-002 1.0314633e-001 1.7509020e-002
+v 6.0778800e-002 6.1646560e-002 1.0463990e-002
+v 3.5915080e-002 5.9916380e-002 -1.1966510e-002
+v 2.4251860e-002 5.6457470e-002 -2.4254800e-002
+v -6.1954390e-002 1.6865320e-001 -5.2621160e-002
+v -9.0557930e-002 1.1275994e-001 1.6141030e-002
+v -8.8469220e-002 1.1124294e-001 1.2679160e-002
+v 5.9558010e-002 6.3099260e-002 5.9471000e-003
+v 3.0940440e-002 6.0518080e-002 -1.8132720e-002
+v -9.3575750e-002 1.2474629e-001 2.6213300e-002
+v -9.3189820e-002 1.2019919e-001 3.7913720e-002
+v -9.2296100e-003 1.7314463e-001 -2.4197660e-002
+v -8.1739460e-002 7.6861340e-002 2.3313610e-002
+v -3.6992750e-002 1.5063932e-001 -2.0372300e-003
+v 6.0093570e-002 6.5693450e-002 1.8533320e-002
+v 5.9837240e-002 6.6423180e-002 8.5139400e-003
+v 4.0706180e-002 6.4475310e-002 -5.5920300e-003
+v 3.4745940e-002 6.3261340e-002 -1.4646740e-002
+v -6.1879660e-002 1.6000450e-001 -2.5806250e-002
+v -7.6537810e-002 1.5344875e-001 -1.2898750e-002
+v 3.8111070e-002 6.4811810e-002 -1.1142000e-002
+v 3.1909340e-002 6.4657050e-002 -1.8473410e-002
+v -8.3159350e-002 1.4674277e-001 3.0757900e-003
+v -8.7055900e-002 1.0562761e-001 9.7651100e-003
+v -7.1448330e-002 1.8105301e-001 -5.5478550e-002
+v -8.5632110e-002 1.2461094e-001 -2.7335800e-003
+v 6.0728970e-002 6.5806600e-002 1.3974830e-002
+v 3.9909650e-002 6.8171740e-002 -9.5698200e-003
+v 3.4981790e-002 6.7740790e-002 -1.5683210e-002
+v -9.1822030e-002 1.2747346e-001 3.6458650e-002
+v -6.2425420e-002 1.6366637e-001 -4.9667290e-002
+v -7.1168950e-002 1.4740156e-001 -2.7590940e-002
+v -5.0364760e-002 1.3715763e-001 1.9526100e-003
+v -5.0492650e-002 1.4159899e-001 1.6291740e-002
+v 5.9886670e-002 6.8513050e-002 1.6171610e-002
+v -6.1406990e-002 1.7268822e-001 -5.8265750e-002
+v 2.4990740e-002 6.5897320e-002 -2.3568270e-002
+v -7.4852750e-002 1.4993112e-001 -2.7752940e-002
+v -6.2225690e-002 6.0265200e-002 2.0449290e-002
+v -6.2001940e-002 3.6435020e-002 4.3918940e-002
+v 5.8374570e-002 7.1186410e-002 1.3072740e-002
+v -3.6125040e-002 1.2286688e-001 -8.2927900e-003
+v 2.9216510e-002 6.7850250e-002 -2.0418570e-002
+v -4.1681700e-002 1.2575112e-001 -7.0193300e-003
+v -7.4226550e-002 1.6437012e-001 -3.8240340e-002
+v -9.7845700e-003 1.6928488e-001 -2.4756660e-002
+v -8.9577950e-002 1.2078310e-001 3.5229100e-003
+v -6.2311930e-002 1.6371109e-001 -4.0623990e-002
+v 4.3514770e-002 9.1519890e-002 -2.6468100e-003
+v -4.8434350e-002 1.3754973e-001 1.3244980e-002
+v -8.9313160e-002 1.3653006e-001 3.0458750e-002
+v -7.4230190e-002 1.5652681e-001 -2.5167090e-002
+v 3.7378600e-002 7.3093410e-002 -1.2635370e-002
+v 2.6321810e-002 7.0240650e-002 -2.3878680e-002
+v -4.8023620e-002 1.4426649e-001 4.2498600e-003
+v -9.2019580e-002 1.1611534e-001 3.5842730e-002
+v -7.1305510e-002 7.3899020e-002 3.5969780e-002
+v -6.2059290e-002 1.5697807e-001 -3.3784580e-002
+v -9.7015300e-003 1.6738863e-001 -1.9360250e-002
+v 4.3342140e-002 7.1676120e-002 -2.2304600e-003
+v 4.1772460e-002 6.9568020e-002 -6.1596000e-003
+v 3.3505410e-002 7.2809860e-002 -1.7034800e-002
+v 2.9665000e-002 7.1506830e-002 -2.1282340e-002
+v -2.9460160e-002 1.5550263e-001 -1.1914700e-003
+v -8.6396440e-002 1.0479356e-001 5.9820600e-003
+v -5.4910700e-002 1.4662313e-001 2.8438970e-002
+v 4.4203810e-002 8.5204260e-002 -2.1170500e-003
+v 4.3264350e-002 7.5810540e-002 -3.8843900e-003
+v 1.3096990e-002 9.1126480e-002 -2.9269770e-002
+v -6.7069210e-002 9.1144610e-002 -1.7425950e-002
+v -9.0821680e-002 1.2276896e-001 6.0998500e-003
+v 4.5620000e-002 7.4684430e-002 2.6073900e-003
+v -9.3039800e-002 1.2026416e-001 1.1216820e-002
+v 4.4635590e-002 9.2794290e-002 1.7832070e-002
+v -1.1243390e-002 1.6457514e-001 -1.8240780e-002
+v 4.5511190e-002 8.6953050e-002 3.8865500e-003
+v 4.6252720e-002 7.7373870e-002 6.9140800e-003
+v 4.0281640e-002 7.2637130e-002 -9.2881000e-003
+v 4.3218200e-002 9.9486740e-002 5.0153300e-003
+v -5.1108270e-002 1.4520219e-001 1.4279480e-002
+v 4.4692980e-002 9.2688550e-002 2.2466700e-003
+v 4.3422540e-002 9.1860370e-002 2.4538450e-002
+v 4.0751360e-002 1.0554729e-001 7.5074100e-003
+v -8.5613030e-002 9.6277110e-002 -6.6514000e-004
+v 4.0721470e-002 7.8475530e-002 -8.2130000e-003
+v 3.5538080e-002 7.6062960e-002 -1.4434750e-002
+v -9.2736510e-002 1.2073095e-001 3.2692730e-002
+v -6.2278520e-002 1.5166598e-001 -1.4672730e-002
+v 4.4960220e-002 8.0942630e-002 6.1119000e-004
+v 3.7814740e-002 7.9698150e-002 -1.3289630e-002
+v 3.3864490e-002 7.8656690e-002 -1.7632490e-002
+v -9.1044280e-002 1.4199862e-001 2.1729630e-002
+v -7.4004450e-002 1.7818523e-001 -5.3916320e-002
+v -6.1768650e-002 1.6067957e-001 -3.4046350e-002
+v -4.9747450e-002 1.4112519e-001 5.2937500e-003
+v 4.1065440e-002 9.0460700e-002 2.9888620e-002
+v -7.2916360e-002 6.5057400e-002 1.8794620e-002
+v -9.0949690e-002 1.3895375e-001 1.7371130e-002
+v 4.2879050e-002 1.0093777e-001 9.4753200e-003
+v -7.2455480e-002 1.7610676e-001 -5.3535420e-002
+v -7.5862940e-002 1.5071299e-001 -9.0209000e-003
+v -8.5269820e-002 1.0267793e-001 1.3935600e-003
+v -7.7025570e-002 1.1396763e-001 -4.6168100e-003
+v 4.6280880e-002 7.8702020e-002 1.4786330e-002
+v 4.2106910e-002 8.1533160e-002 -6.6690900e-003
+v 3.6523880e-002 8.1991750e-002 -1.6229590e-002
+v -3.7420220e-002 4.5428500e-002 -2.4226790e-002
+v -8.5148910e-002 1.3965520e-001 2.4808500e-003
+v -6.3313300e-002 1.6503258e-001 -3.2895120e-002
+v -6.1591410e-002 1.5681572e-001 -2.5945630e-002
+v 4.5918540e-002 8.7036220e-002 8.4236300e-003
+v 4.4631140e-002 8.4178380e-002 8.2665000e-004
+v -4.4842870e-002 1.4629393e-001 1.7114800e-003
+v -6.4124180e-002 1.7953625e-001 -5.8730420e-002
+v -6.7070300e-002 1.8072682e-001 -5.6618620e-002
+v -6.4793760e-002 1.7885275e-001 -5.5883250e-002
+v -6.4371030e-002 1.7296209e-001 -4.9225660e-002
+v -7.0381530e-002 1.8071180e-001 -5.3172590e-002
+v -7.5269270e-002 1.5232949e-001 3.4374060e-002
+v -1.6273090e-002 1.2844514e-001 1.6683610e-002
+v -6.2116150e-002 1.5600787e-001 1.8034420e-002
+v -5.6010790e-002 1.5381662e-001 2.5369280e-002
+v -3.7277920e-002 1.7289068e-001 -8.6627000e-004
+v -7.4158700e-002 1.7987275e-001 -5.0794750e-002
+v -7.9039960e-002 1.5537445e-001 1.5141810e-002
+v -7.2505530e-002 1.5459529e-001 2.9588830e-002
+v -6.7738180e-002 1.7728865e-001 -5.0375960e-002
+v -7.5346900e-003 1.0021302e-001 4.7488700e-002
+v -5.9575620e-002 1.5472401e-001 2.6373250e-002
+v -7.7382710e-002 1.5346600e-001 3.0894990e-002
+v -8.1496670e-002 1.5473104e-001 1.9697340e-002
+v -7.2223320e-002 1.5896734e-001 -5.4242300e-003
+v -1.3708500e-002 1.8491150e-001 -2.5549550e-002
+v -4.3465340e-002 1.2451145e-001 2.2518890e-002
+v -6.9103650e-002 1.5559479e-001 1.6370800e-003
+v -7.3748080e-002 1.5539253e-001 2.3491700e-003
+v -6.8192410e-002 1.7439828e-001 -4.5365870e-002
+v -6.0052850e-002 1.5280350e-001 3.2887630e-002
+v -2.3459490e-002 1.2615386e-001 1.6613770e-002
+v -7.2777220e-002 1.7854465e-001 -4.8208800e-002
+v -7.6595580e-002 1.7753227e-001 -4.7118080e-002
+v 1.3906410e-002 1.2790838e-001 2.5110240e-002
+v -8.6367510e-002 1.0906537e-001 1.1980640e-002
+v -3.1358850e-002 1.2140977e-001 2.5971090e-002
+v -4.9104590e-002 1.3666879e-001 1.9314030e-002
+v -4.2930640e-002 1.2928436e-001 9.2700700e-003
+v -6.5320350e-002 1.5390322e-001 9.1386000e-004
+v -3.7606490e-002 1.2422605e-001 2.4313530e-002
+v 9.5078400e-003 1.3041865e-001 2.0715020e-002
+v -1.7976800e-003 1.3117283e-001 1.6360660e-002
+v 3.6231700e-003 1.3076791e-001 2.1168600e-002
+v -9.2674700e-002 1.1701945e-001 1.1889520e-002
+v -6.5739720e-002 1.5565338e-001 2.6017600e-002
+v -8.6561940e-002 1.4249188e-001 8.4326800e-003
+v -7.0731530e-002 1.5569959e-001 6.9058200e-003
+v -8.0840700e-003 1.3030537e-001 1.6872280e-002
+v -4.4286250e-002 1.2606625e-001 2.0795220e-002
+v -7.0222260e-002 1.5143521e-001 3.6718910e-002
+v -1.5210690e-002 1.8463639e-001 -2.2057240e-002
+v -1.7270750e-002 1.8699602e-001 -1.9977570e-002
+v -8.3560950e-002 1.5255943e-001 7.6806700e-003
+v -8.8130280e-002 9.7540510e-002 5.6788000e-003
+v -8.8399240e-002 1.3899000e-001 1.0640660e-002
+v -6.7780550e-002 1.5614453e-001 1.4276320e-002
+v -6.5864600e-003 1.2641717e-001 3.0226390e-002
+v -8.8746180e-002 1.3625578e-001 7.1477800e-003
+v -7.7206730e-002 1.5639950e-001 -1.8972540e-002
+v -9.3176480e-002 1.1821016e-001 2.3362360e-002
+v -2.3506850e-002 1.2672006e-001 1.0996900e-002
+v -6.6546650e-002 1.7171115e-001 -4.2127770e-002
+v -6.9136000e-002 1.7247836e-001 -3.9013330e-002
+v 5.7180270e-002 7.1107690e-002 8.0307600e-003
+v -7.5390870e-002 1.7952824e-001 -5.2402050e-002
+v -3.1828840e-002 1.2639115e-001 1.0013410e-002
+v -8.9888800e-003 1.2952269e-001 2.2026810e-002
+v 3.4325880e-002 1.1193312e-001 -2.2406500e-003
+v -8.1414950e-002 9.7100250e-002 -6.8745800e-003
+v -2.3298830e-002 1.8324307e-001 -1.7923000e-002
+v -6.1641660e-002 1.5582039e-001 1.1099820e-002
+v -8.8826450e-002 9.0483320e-002 2.1204700e-002
+v 5.8373130e-002 6.8067590e-002 5.7247600e-003
+v -4.3045630e-002 1.2785122e-001 1.6842260e-002
+v 3.0835720e-002 1.1554234e-001 -3.1785500e-003
+v -8.8631270e-002 9.4881200e-002 7.9337600e-003
+v -9.1715140e-002 1.1709957e-001 3.0809400e-002
+v -7.2083780e-002 1.7499844e-001 -4.1930320e-002
+v -6.9540630e-002 1.5308527e-001 3.3865720e-002
+v 6.0078690e-002 6.8129260e-002 1.1454500e-002
+v -4.0081060e-002 1.2628381e-001 1.9607250e-002
+v 3.2819930e-002 1.1655625e-001 4.4458600e-003
+v -7.2823220e-002 1.4510601e-001 -1.5654680e-002
+v -8.5270210e-002 1.0551770e-001 2.3290940e-002
+v -7.6051320e-002 1.1103825e-001 -6.2722100e-003
+v -8.6537730e-002 1.5154801e-001 2.5875370e-002
+v 5.5888480e-002 7.2579250e-002 1.0669650e-002
+v -5.4642360e-002 1.5522963e-001 1.2612400e-002
+v 3.6729960e-002 1.1116756e-001 3.8670600e-003
+v 3.1501870e-002 1.1725172e-001 1.6855100e-003
+v -7.8751550e-002 9.5240290e-002 -1.0600670e-002
+v -8.9408160e-002 1.4352815e-001 3.0924750e-002
+v -2.0891130e-002 1.8595338e-001 -1.5037360e-002
+v -7.0863560e-002 1.6136525e-001 -9.7324600e-003
+v -7.0919760e-002 1.7136688e-001 -3.2763750e-002
+v -3.0771290e-002 1.2564075e-001 1.6594770e-002
+v -5.4454180e-002 1.5297699e-001 2.2505190e-002
+v -1.5539500e-003 1.2754717e-001 2.9232870e-002
+v 2.9130550e-002 1.2027445e-001 6.1117500e-003
+v 2.5725940e-002 1.2122705e-001 -3.6150000e-005
+v -8.9318970e-002 9.9546980e-002 1.3418110e-002
+v -7.5429500e-002 1.7095605e-001 -3.2879890e-002
+v -2.8596020e-002 1.1901156e-001 2.9888170e-002
+v 2.1069780e-002 1.2497756e-001 1.0998100e-003
+v -9.2240760e-002 1.1816838e-001 4.1201730e-002
+v 2.4094600e-003 1.0016785e-001 4.6938070e-002
+v -5.6627620e-002 1.5270606e-001 2.9629030e-002
+v -5.7264800e-002 1.5506250e-001 1.9322430e-002
+v -3.6452070e-002 1.2199869e-001 2.7670650e-002
+v -7.4108160e-002 1.7355729e-001 -3.7986840e-002
+v 5.1537130e-002 7.3496690e-002 1.2698700e-002
+v -6.6096040e-002 1.5532529e-001 7.1561800e-003
+v 3.6102000e-002 1.1266103e-001 1.0491780e-002
+v 1.6715210e-002 1.2689851e-001 2.2331000e-004
+v -8.0767920e-002 1.4301400e-001 -1.5312800e-003
+v -9.1757600e-002 1.4334588e-001 1.7790710e-002
+v -8.6824940e-002 1.5280775e-001 1.5521450e-002
+v -6.5808100e-002 1.6764344e-001 -3.0558670e-002
+v -7.8217340e-002 1.6873975e-001 -3.3564250e-002
+v -7.2567060e-002 1.4753230e-001 4.1714090e-002
+v 5.8439960e-002 7.0200810e-002 1.7779620e-002
+v 5.6847560e-002 7.2017160e-002 1.7139380e-002
+v 5.4919390e-002 7.3161610e-002 1.5223590e-002
+v 4.7446900e-002 7.3691410e-002 1.2430020e-002
+v 1.2319360e-002 1.2903768e-001 1.3336200e-003
+v -7.9790640e-002 1.0351662e-001 -6.6275400e-003
+v -7.6655210e-002 1.5509766e-001 7.9686300e-003
+v 2.1747320e-002 1.2118456e-001 3.0878810e-002
+v -7.5260490e-002 1.4938613e-001 3.9175980e-002
+v -2.5919610e-002 1.8272826e-001 -1.3541090e-002
+v -6.7983790e-002 1.6974781e-001 -3.1627490e-002
+v 1.6831110e-002 1.2487146e-001 2.8425580e-002
+v 5.4016490e-002 7.2883850e-002 1.8678010e-002
+v 5.0522750e-002 7.3397910e-002 1.6166890e-002
+v -5.9582440e-002 1.5623338e-001 7.9209900e-003
+v 2.5343500e-002 1.2374750e-001 9.9818800e-003
+v 1.9262750e-002 1.2689390e-001 5.5552100e-003
+v -9.0758520e-002 1.4223375e-001 2.6008130e-002
+v -4.6548490e-002 1.3320769e-001 1.6889630e-002
+v -2.4106950e-002 1.8380887e-001 -1.1544760e-002
+v 8.6784400e-003 1.2894574e-001 2.6156880e-002
+v 2.4919200e-003 1.2983563e-001 2.4847110e-002
+v 5.7345150e-002 6.9482720e-002 2.1153510e-002
+v -8.5329840e-002 1.5339912e-001 2.0378290e-002
+v 3.2877320e-002 1.1691463e-001 9.2957500e-003
+v 2.4246630e-002 1.2377758e-001 4.8764500e-003
+v -4.7765650e-002 1.3301969e-001 2.2874020e-002
+v -6.3541830e-002 1.6332115e-001 -2.5912990e-002
+v -6.6605200e-002 1.6477375e-001 -2.0670760e-002
+v -6.8504220e-002 1.6732018e-001 -2.3959570e-002
+v -7.2759160e-002 1.6965906e-001 -2.7013420e-002
+v 4.8206850e-002 7.2698580e-002 1.6994630e-002
+v -2.7383180e-002 1.2324257e-001 2.1658860e-002
+v -4.5077500e-002 1.3124443e-001 1.1145770e-002
+v 2.9253150e-002 1.2057701e-001 1.2299330e-002
+v 1.3677610e-002 1.2967262e-001 6.9327400e-003
+v 8.4210900e-003 1.3090986e-001 6.2754400e-003
+v 9.6836000e-004 1.3064303e-001 2.5865900e-003
+v 3.0802000e-003 9.8307360e-002 5.0535640e-002
+v -5.2420170e-002 1.5310101e-001 1.2927370e-002
+v -7.0359720e-002 1.6906988e-001 -2.6144260e-002
+v 5.4359390e-002 7.1467260e-002 2.1381250e-002
+v 4.5161440e-002 7.1030380e-002 2.2530690e-002
+v 1.9320440e-002 1.2738348e-001 1.1296310e-002
+v -9.3281210e-002 1.2691094e-001 1.3505010e-002
+v -8.7405060e-002 1.0593990e-001 1.3645920e-002
+v -2.2851640e-002 9.0635040e-002 5.2280460e-002
+v -6.2099370e-002 1.5406697e-001 3.0837360e-002
+v -4.5851560e-002 1.2072981e-001 2.7665040e-002
+v 5.0781670e-002 7.2155170e-002 2.0680180e-002
+v -8.9607270e-002 1.3971105e-001 2.9308560e-002
+v -5.3323050e-002 1.5273520e-001 1.6213860e-002
+v -1.5227080e-002 1.2784878e-001 2.1545200e-002
+v 3.3663540e-002 1.1574212e-001 1.7181290e-002
+v 2.4000260e-002 1.2468761e-001 1.5517930e-002
+v -8.4166840e-002 9.7756820e-002 -3.2761900e-003
+v -3.6223590e-002 1.2777519e-001 9.8501500e-003
+v -3.9189580e-002 1.2828193e-001 5.0346300e-003
+v -3.3674050e-002 1.7774449e-001 -8.1799500e-003
+v -7.4488620e-002 1.5649443e-001 -2.5954600e-003
+v -4.6755620e-002 1.3284294e-001 8.1212800e-003
+v -8.4970410e-002 1.5322309e-001 1.2654460e-002
+v -1.0866210e-002 1.2691699e-001 2.7575440e-002
+v -3.1074000e-003 1.3072898e-001 5.6428500e-003
+v -8.8760540e-002 9.7037440e-002 2.1079040e-002
+v -6.4811320e-002 3.4530640e-002 1.5508440e-002
+v -6.4300260e-002 3.5086450e-002 2.4272050e-002
+v -6.6727020e-002 3.5895770e-002 3.3849430e-002
+v 1.9838510e-002 9.6518890e-002 -2.2785880e-002
+v -3.8670510e-002 1.6070199e-001 -1.2357760e-002
+v -7.6890090e-002 1.3041906e-001 -6.9570100e-003
+v -7.2539730e-002 3.5399270e-002 7.0298800e-003
+v -6.9209050e-002 3.5454810e-002 1.2042140e-002
+v -6.4160810e-002 3.5900770e-002 1.7687570e-002
+v -6.6804150e-002 3.7377740e-002 3.3296290e-002
+v -6.2928350e-002 3.9061660e-002 4.2707680e-002
+v -7.1752230e-002 3.6789350e-002 8.6966700e-003
+v -6.5171380e-002 3.7289500e-002 2.5953770e-002
+v -6.6392030e-002 3.7712350e-002 2.9621950e-002
+v -6.4558720e-002 3.9639900e-002 3.9411530e-002
+v -6.0145790e-002 4.1202050e-002 4.4293830e-002
+v -6.0318430e-002 3.8442990e-002 4.5245950e-002
+v -3.6756310e-002 8.8663360e-002 -2.3868800e-002
+v -3.9494750e-002 3.7551570e-002 4.2870900e-002
+v -7.2016030e-002 3.7572700e-002 3.9789400e-003
+v -7.1693630e-002 3.9461000e-002 6.0145000e-003
+v -7.1165950e-002 3.9366310e-002 8.1142100e-003
+v -6.9000300e-002 3.8467710e-002 1.0768900e-002
+v -6.7253420e-002 3.8142160e-002 1.3533960e-002
+v -6.1125670e-002 3.7790050e-002 1.9710900e-002
+v -3.9179680e-002 4.2406740e-002 4.1476070e-002
+v -3.5145960e-002 3.8585920e-002 4.7732690e-002
+v -2.8950940e-002 3.9285940e-002 5.3309090e-002
+v -1.8223900e-002 9.7494570e-002 4.6847940e-002
+v -6.6916260e-002 1.2278907e-001 -8.9077400e-003
+v -6.3754640e-002 3.8250120e-002 1.6593500e-002
+v -6.4415760e-002 4.1283840e-002 2.8243480e-002
+v -8.5856340e-002 9.7025390e-002 2.7414960e-002
+v -3.7501130e-002 4.0221900e-002 4.4296550e-002
+v -3.4333970e-002 4.0923630e-002 4.8425810e-002
+v -3.1172890e-002 4.0294330e-002 5.1312460e-002
+v -6.9997320e-002 4.2073080e-002 6.6897800e-003
+v -8.0379330e-002 9.7800660e-002 3.3645750e-002
+v -2.6273160e-002 7.7631160e-002 4.8356180e-002
+v -3.7501450e-002 4.2736690e-002 4.2988400e-002
+v -2.6177500e-002 4.2498930e-002 5.3315220e-002
+v -6.9637250e-002 4.1881270e-002 3.1825800e-003
+v -6.7156510e-002 4.1972860e-002 1.0240940e-002
+v -8.7405510e-002 1.0205209e-001 2.2020360e-002
+v -2.3944380e-002 7.8800140e-002 5.3534730e-002
+v -6.0902360e-002 4.3429500e-002 4.2678530e-002
+v -3.1217880e-002 4.3847510e-002 4.9780920e-002
+v -7.5729440e-002 1.0354026e-001 3.6070970e-002
+v -6.2425320e-002 4.1885720e-002 1.4646770e-002
+v -6.1051660e-002 4.4392230e-002 1.2421940e-002
+v 2.5855060e-002 8.9610660e-002 -2.2701840e-002
+v -7.7644960e-002 8.2214940e-002 3.5797660e-002
+v -6.0381270e-002 4.5921420e-002 4.0088740e-002
+v -2.4982010e-002 8.1777650e-002 5.3421060e-002
+v -3.4453850e-002 4.4563960e-002 4.5422990e-002
+v -2.9842910e-002 4.6782280e-002 4.7746920e-002
+v -1.5119580e-002 9.9930020e-002 4.4500270e-002
+v -6.7306470e-002 4.4176830e-002 7.5958300e-003
+v -5.7852990e-002 4.6444500e-002 1.1062610e-002
+v -5.1815260e-002 1.6392582e-001 1.7488800e-003
+v -5.5174130e-002 4.8383880e-002 3.8517780e-002
+v -7.8849150e-002 1.1867375e-001 5.0622870e-002
+v -2.7229070e-002 8.7991480e-002 4.7909730e-002
+v -7.5536880e-002 1.5977062e-001 -1.0438650e-002
+v -3.6151280e-002 4.6505140e-002 4.0740900e-002
+v -2.5439220e-002 9.0677870e-002 4.8852330e-002
+v -8.0050370e-002 1.1670406e-001 4.8762460e-002
+v -5.2513640e-002 4.7577880e-002 1.4858440e-002
+v -3.2043560e-002 5.0461830e-002 3.9341520e-002
+v -3.1487770e-002 4.6930210e-002 4.5253210e-002
+v -2.0321500e-002 9.3999570e-002 5.1588540e-002
+v -7.2145040e-002 9.1556450e-002 4.1494780e-002
+v -5.3644200e-002 4.9358170e-002 1.2201850e-002
+v -8.2403890e-002 1.2186563e-001 4.9365030e-002
+v -4.9754420e-002 4.9738300e-002 3.7037110e-002
+v -3.2332060e-002 4.8672840e-002 4.2523960e-002
+v -2.3122950e-002 9.4515900e-002 4.7358870e-002
+v -8.6347140e-002 9.1722090e-002 2.6811080e-002
+v -5.7713110e-002 4.8717820e-002 7.2765100e-003
+v -8.6970360e-002 8.8912090e-002 2.4879860e-002
+v -9.2237750e-002 1.2488519e-001 4.0786530e-002
+v -1.5862800e-002 9.7021620e-002 5.0139360e-002
+v -2.7720040e-002 5.0502090e-002 4.3340720e-002
+v -8.5918770e-002 1.4263412e-001 3.9849810e-002
+v -7.5097360e-002 9.0073560e-002 3.9581000e-002
+v -8.9430840e-002 1.4730552e-001 2.7694960e-002
+v -5.3288350e-002 5.1925760e-002 1.1730350e-002
+v -5.0168720e-002 5.3462260e-002 1.6255440e-002
+v -8.5986050e-002 1.4670902e-001 3.4827030e-002
+v -6.9937250e-002 8.6076860e-002 4.2175690e-002
+v -5.0399320e-002 5.1831330e-002 3.4037400e-002
+v -8.3298980e-002 1.4960772e-001 3.3740890e-002
+v -2.9174820e-002 5.2264530e-002 3.7637320e-002
+v -8.8763730e-002 1.1944938e-001 4.6560090e-002
+v -7.7693460e-002 1.7367969e-001 -4.1478670e-002
+v -8.3418140e-002 9.4127440e-002 3.0898450e-002
+v -5.6067510e-002 5.3470630e-002 7.3718200e-003
+v -7.8935630e-002 1.4817228e-001 3.9463070e-002
+v -6.7902770e-002 8.7817230e-002 4.3526990e-002
+v -4.4111240e-002 9.2883990e-002 -2.2373210e-002
+v -8.6605100e-002 1.3226807e-001 4.6783020e-002
+v -9.2654280e-002 1.2084025e-001 4.1629650e-002
+v -5.0887310e-002 5.2727900e-002 1.4455790e-002
+v -4.9763410e-002 5.6241200e-002 3.3624250e-002
+v -8.9771330e-002 1.2904861e-001 4.3022990e-002
+v -2.8054240e-002 5.4551030e-002 3.6786850e-002
+v -2.5867080e-002 5.6689210e-002 3.9182240e-002
+v -8.3702200e-002 1.2226381e-001 -3.7301400e-003
+v -8.1455470e-002 1.3012213e-001 5.2117660e-002
+v -5.1458550e-002 5.5878150e-002 1.5900350e-002
+v -7.8597700e-002 1.7441574e-001 -4.6607580e-002
+v -5.2909820e-002 5.7043070e-002 2.0988410e-002
+v -5.2978500e-002 5.9553770e-002 2.6211920e-002
+v -5.2130640e-002 5.6302970e-002 2.6672460e-002
+v -4.7714500e-002 6.1944520e-002 3.6705820e-002
+v -8.3539790e-002 8.1169560e-002 2.7014070e-002
+v -1.8340000e-002 5.7489970e-002 4.9763020e-002
+v -8.0069810e-002 9.0586130e-002 3.4593070e-002
+v -8.3812250e-002 8.6337700e-002 2.9223270e-002
+v -5.5436650e-002 5.9420250e-002 2.3018970e-002
+v -8.2227680e-002 1.4513771e-001 4.0600080e-002
+v -2.4187580e-002 7.2269150e-002 4.7681090e-002
+v -2.5353150e-002 6.2567200e-002 4.0642170e-002
+v -9.1132110e-002 1.2282100e-001 4.4115160e-002
+v -4.6076290e-002 1.6819719e-001 7.3744000e-004
+v -8.7829280e-002 1.4351461e-001 3.5707670e-002
+v -8.6990640e-002 1.3812326e-001 4.2316550e-002
+v -1.5715900e-002 6.0822970e-002 5.2365440e-002
+v -8.3803580e-002 1.2561100e-001 5.0440490e-002
+v -6.2786680e-002 1.1274190e-001 -1.3605440e-002
+v -8.1033840e-002 8.4698180e-002 3.3106400e-002
+v -8.8563540e-002 1.1624535e-001 4.5392840e-002
+v -2.0268380e-002 6.2266810e-002 4.8212120e-002
+v -1.2619630e-002 6.1635030e-002 5.4424080e-002
+v -7.0491190e-002 8.1818160e-002 4.0609890e-002
+v -8.3882520e-002 1.3331465e-001 4.9113540e-002
+v -5.6560350e-002 4.8355540e-002 3.6607050e-002
+v 9.9444900e-003 1.0919723e-001 -1.9472810e-002
+v -5.5928250e-002 3.5917310e-002 4.6376100e-002
+v -7.6003260e-002 1.6361344e-001 -1.8021110e-002
+v -8.3798850e-002 1.0290691e-001 2.8038330e-002
+v -8.8252110e-002 1.2692730e-001 4.6141300e-002
+v -7.9126720e-002 1.0619883e-001 3.2050700e-002
+v -8.8206230e-002 9.4485700e-002 2.3744010e-002
+v -8.9110330e-002 1.3851394e-001 3.7658780e-002
+v -1.9321360e-002 9.2123890e-002 5.3820650e-002
+v -5.8265630e-002 9.0926390e-002 -2.0948690e-002
+v -2.7046310e-002 6.7014450e-002 3.9672140e-002
+v -2.1416300e-002 1.7977662e-001 -2.1732520e-002
+v -7.8240000e-003 1.0924112e-001 -2.2185670e-002
+v -2.3988340e-002 8.5995590e-002 5.3716430e-002
+v -6.0483580e-002 1.5567975e-001 4.3343800e-003
+v -8.6389150e-002 1.2168475e-001 4.8412440e-002
+v -7.4084360e-002 1.4987744e-001 -3.2610050e-002
+v -2.0580600e-002 7.9572500e-002 5.6013880e-002
+v -8.3837500e-002 1.3927865e-001 4.4893850e-002
+v -2.2933960e-002 3.5632910e-002 5.2865490e-002
+v -8.6153620e-002 1.2735612e-001 4.8563960e-002
+v -6.5728590e-002 1.0709818e-001 -1.4317670e-002
+v -2.1481090e-002 7.4194460e-002 5.2857680e-002
+v -7.6423900e-002 1.5736285e-001 -9.0354600e-003
+v -7.7216010e-002 8.5594880e-002 3.7420770e-002
+v -8.4150830e-002 1.2955013e-001 5.0483700e-002
+v -8.1221440e-002 8.1003250e-002 3.1255840e-002
+v -8.1704000e-002 1.0167226e-001 3.0939660e-002
+v -8.6252730e-002 1.0106846e-001 2.5413770e-002
+v -8.0944970e-002 1.3903572e-001 4.7359080e-002
+v -7.8908350e-002 9.4830900e-002 3.5435500e-002
+v -7.3440160e-002 9.5412600e-002 4.0210650e-002
+v -5.2675780e-002 8.8220740e-002 -2.1886300e-002
+v -7.6440670e-002 7.7511060e-002 3.3748300e-002
+v -2.1791140e-002 1.0658035e-001 -2.2327000e-002
+v -8.8360940e-002 1.4996706e-001 2.6044170e-002
+v -2.4078870e-002 6.7906700e-002 4.5178370e-002
+v -2.0018090e-002 6.7569300e-002 5.1565340e-002
+v -8.3577750e-002 1.2052625e-001 4.9177500e-002
+v -1.4655950e-002 1.7456543e-001 -2.5972690e-002
+v -2.7395940e-002 8.4108300e-002 4.8745680e-002
+v -4.1933580e-002 8.8463400e-002 -2.2126350e-002
+v -3.1693900e-002 1.0261265e-001 -2.2352310e-002
+v -2.7890200e-002 1.0440703e-001 -2.2830920e-002
+v -7.3790400e-002 1.2016662e-001 -7.8851200e-003
+v -4.6124160e-002 1.0506369e-001 -2.0457580e-002
+v -2.7412650e-002 7.3269450e-002 4.2641380e-002
+v -4.5532880e-002 3.4736480e-002 -2.1363200e-002
+v -4.4993030e-002 3.9017010e-002 -2.1097830e-002
+v -4.6462610e-002 3.6800270e-002 -1.7778710e-002
+v -8.8366460e-002 1.1361863e-001 5.8227800e-003
+v 5.1746240e-002 7.2897250e-002 9.0647400e-003
+v -7.0385250e-002 3.7450300e-002 -9.3190000e-004
+v -6.0923170e-002 3.8621820e-002 2.2468850e-002
+v -7.7696720e-002 1.7027889e-001 -4.3117910e-002
+v -4.3793210e-002 1.6955506e-001 -7.3026400e-003
+v -7.7587180e-002 1.7717875e-001 -5.0221090e-002
+v -4.0541880e-002 3.8886010e-002 -2.7364950e-002
+v -4.4215850e-002 3.6131460e-002 -2.4252210e-002
+v -6.6634880e-002 4.0430310e-002 -5.0180700e-003
+v -6.9242120e-002 4.1474050e-002 1.9289000e-004
+v -7.5640690e-002 1.5930400e-001 -2.6908460e-002
+v -6.3087030e-002 3.9614170e-002 2.5181560e-002
+v -7.2303020e-002 1.5186699e-001 -4.1544310e-002
+v -4.1051490e-002 4.1528620e-002 -2.4061000e-002
+v -4.6990580e-002 3.8892380e-002 -1.4016920e-002
+v -8.9559690e-002 1.2851666e-001 4.5457500e-003
+v -7.6987340e-002 1.5369375e-001 -2.2970800e-003
+v -7.0121670e-002 1.6882633e-001 -5.1173650e-002
+v -6.4792610e-002 4.1724530e-002 3.1616900e-002
+v -4.2148060e-002 1.2409627e-001 -9.5602500e-003
+v -4.8069700e-002 1.2493027e-001 -8.4076400e-003
+v -4.2150480e-002 4.3343970e-002 -2.1508710e-002
+v -6.7315160e-002 4.4034000e-002 1.5741800e-003
+v -7.3386640e-002 1.5463418e-001 -2.9943830e-002
+v -5.5352770e-002 4.2936210e-002 1.9135490e-002
+v -6.0067770e-002 4.1419500e-002 2.2953280e-002
+v -6.5488460e-002 4.0937780e-002 3.5315470e-002
+v -8.0066400e-002 1.5039650e-001 6.0518000e-004
+v -4.4031300e-002 4.1949070e-002 -1.7993960e-002
+v -4.5186510e-002 4.2453420e-002 -1.4193620e-002
+v -8.3109430e-002 1.0265445e-001 -3.2933400e-003
+v -6.5472800e-002 4.5627570e-002 4.5575400e-003
+v -7.5427730e-002 1.5201213e-001 -1.4393690e-002
+v -5.4473420e-002 4.5937510e-002 2.3612600e-002
+v -6.2464100e-002 4.3722000e-002 2.8493310e-002
+v -6.2832600e-002 4.5182750e-002 3.4622890e-002
+v -6.3538130e-002 4.3524020e-002 3.7974010e-002
+v -6.0255260e-002 4.4749620e-002 -4.1316200e-003
+v -6.3242050e-002 4.5549700e-002 4.8428000e-004
+v -6.2249430e-002 4.6540050e-002 7.1903500e-003
+v -9.1003650e-002 1.4885725e-001 2.1507030e-002
+v -5.7094130e-002 4.5996540e-002 2.6865280e-002
+v -5.7276490e-002 4.7299580e-002 2.9889950e-002
+v -3.9519900e-002 1.7385855e-001 -7.5752600e-003
+v -8.9641110e-002 1.3841920e-001 3.4141800e-002
+v -9.2601430e-002 1.3018652e-001 2.5183580e-002
+v -9.2280860e-002 1.2762053e-001 2.9751670e-002
+v -3.3957310e-002 4.1025060e-002 -2.9660250e-002
+v -9.0199540e-002 1.1657506e-001 5.6754900e-003
+v -5.8515890e-002 4.7731310e-002 2.1246000e-004
+v -7.1723560e-002 1.4617438e-001 -2.1567820e-002
+v -5.2389820e-002 4.5449130e-002 1.7686300e-002
+v -5.9414350e-002 4.7277990e-002 3.4172420e-002
+v -5.7520620e-002 1.5877600e-001 4.1621200e-003
+v -8.0959140e-002 1.0926674e-001 -2.0189900e-003
+v -5.1904000e-002 4.6100060e-002 1.9421290e-002
+v -5.1830050e-002 4.8568730e-002 2.1647030e-002
+v -7.7650400e-002 1.5658012e-001 -1.6599150e-002
+v -3.7416450e-002 4.7682130e-002 -1.7147280e-002
+v -7.8876110e-002 1.5347012e-001 3.9875800e-003
+v -5.7635420e-002 5.0425540e-002 4.6108400e-003
+v -5.2625440e-002 5.0434620e-002 2.9046740e-002
+v -5.2998720e-002 4.9169020e-002 3.3967600e-002
+v -7.3502600e-002 1.6871934e-001 -4.4791800e-002
+v -5.4420720e-002 4.7836520e-002 -5.9186900e-003
+v -5.2312740e-002 5.1085350e-002 2.4485690e-002
+v -7.9129930e-002 1.6736568e-001 -3.5506230e-002
+v 9.4115700e-003 1.2350285e-001 -9.8291000e-003
+v -3.2715700e-002 1.0896631e-001 -1.8941410e-002
+v -3.1133380e-002 4.9607260e-002 -1.9406940e-002
+v 4.5997330e-002 6.9814450e-002 3.0143300e-003
+v 3.3525460e-002 1.0966209e-001 -6.9894800e-003
+v -5.5047160e-002 5.2767560e-002 -3.9461300e-003
+v -5.6897890e-002 4.9655570e-002 -1.5319000e-003
+v -5.0290500e-002 4.9098930e-002 1.7164780e-002
+v -5.0595170e-002 4.9923270e-002 1.9174130e-002
+v -5.1887420e-002 5.3324670e-002 2.8705560e-002
+v -6.7684480e-002 1.6533627e-001 -5.5466400e-002
+v -3.0271440e-002 5.2106080e-002 -1.7676140e-002
+v -9.1087300e-003 1.1141669e-001 -2.0543230e-002
+v -5.7069360e-002 5.4424380e-002 2.3395500e-003
+v -3.2748380e-002 1.7759875e-001 -1.1627470e-002
+v -2.9009580e-002 5.1265290e-002 -2.2175780e-002
+v -3.1383130e-002 5.1791310e-002 -1.3886800e-002
+v -5.5673960e-002 5.6983850e-002 -3.3510400e-003
+v -5.0916050e-002 5.3813610e-002 1.9753140e-002
+v -8.8875380e-002 1.5169443e-001 2.0086580e-002
+v -7.7153050e-002 1.7378676e-001 -4.7867620e-002
+v -7.8577770e-002 1.6420639e-001 -3.1825860e-002
+v -2.7545910e-002 5.4021570e-002 -2.5147390e-002
+v -5.4463660e-002 5.5357450e-002 1.0326840e-002
+v -8.7041410e-002 1.3058932e-001 9.1161000e-004
+v -9.0009340e-002 1.3278082e-001 5.9220600e-003
+v -9.2232620e-002 1.3195400e-001 1.5430650e-002
+v -4.8639980e-002 1.6472475e-001 -5.0591500e-003
+v -5.4066480e-002 5.9959350e-002 -7.5992200e-003
+v -5.7434090e-002 5.7683500e-002 8.7259700e-003
+v -8.6794730e-002 1.3850688e-001 4.5575900e-003
+v -9.2989530e-002 1.3092307e-001 1.9919290e-002
+v -9.1282030e-002 1.3311897e-001 2.4688630e-002
+v 2.1815020e-002 1.1770533e-001 -1.0015300e-002
+v -2.9647120e-002 5.8104260e-002 -2.1311320e-002
+v -3.1289530e-002 5.5208570e-002 -1.4387840e-002
+v -5.9002160e-002 5.9234620e-002 2.6140800e-003
+v -9.0241700e-002 1.3575994e-001 1.4149160e-002
+v -6.1569420e-002 1.7084875e-001 -6.1679170e-002
+v -6.6070180e-002 1.6557822e-001 -5.8644080e-002
+v -2.4539930e-002 1.8005865e-001 -1.8726950e-002
+v -1.6131750e-002 1.8298848e-001 -2.6037190e-002
+v -3.0809390e-002 5.6998040e-002 -1.7835020e-002
+v 1.0464280e-002 9.6180450e-002 -2.5898970e-002
+v -5.7491630e-002 5.9530160e-002 -1.0786100e-003
+v -8.9146460e-002 1.3650500e-001 2.5952780e-002
+v 4.3714500e-003 1.0391901e-001 -2.1515100e-002
+v -9.0377040e-002 1.3252490e-001 3.1082650e-002
+v -9.0795450e-002 1.3855232e-001 2.0562560e-002
+v -9.4237710e-002 1.2615419e-001 2.2201450e-002
+v -9.0336910e-002 1.3119830e-001 3.8138790e-002
+v -4.5082610e-002 1.2218447e-001 -1.1569430e-002
+v 1.1348010e-002 9.8243750e-002 -2.3024250e-002
+v -3.9227920e-002 9.9184630e-002 -2.1912720e-002
+v -6.5509530e-002 1.5857325e-001 -5.5600270e-002
+v -7.7409510e-002 1.6260515e-001 -2.0754580e-002
+v -4.8580010e-002 1.6689211e-001 -2.5256100e-003
+v -7.6922910e-002 1.5351394e-001 -9.0785600e-003
+v -6.7750580e-002 1.5734825e-001 -5.3982110e-002
+v 5.2906410e-002 6.5230450e-002 -5.1112000e-004
+v -2.9054820e-002 6.1084120e-002 -2.4918230e-002
+v -3.1066920e-002 6.5058860e-002 -2.2751080e-002
+v 2.4249720e-002 1.0266151e-001 -1.8313830e-002
+v -5.5473660e-002 1.6050213e-001 1.3763500e-003
+v -6.6642850e-002 1.6040875e-001 -5.6842680e-002
+v -7.8200320e-002 1.6073213e-001 -2.3999690e-002
+v -1.8320680e-002 1.1968625e-001 -1.1110660e-002
+v 2.1712970e-002 1.0956342e-001 -1.5081090e-002
+v -6.8382640e-002 1.5980248e-001 -5.4208800e-002
+v -2.5445620e-002 6.0208550e-002 -3.0864700e-002
+v -2.6540330e-002 6.5084000e-002 -3.1664870e-002
+v -2.8425710e-002 6.2199610e-002 -2.7938500e-002
+v -3.2605750e-002 6.1264600e-002 -1.5453010e-002
+v -7.0872290e-002 1.1611638e-001 -7.9563700e-003
+v -6.9780530e-002 1.5938570e-001 -4.9418240e-002
+v -3.0324870e-002 6.7694720e-002 -2.7654950e-002
+v -3.2977370e-002 6.6365180e-002 -1.8385530e-002
+v 1.3533490e-002 1.0255388e-001 -2.1579310e-002
+v 4.4408530e-002 6.9758860e-002 9.4765000e-004
+v -2.1999000e-003 1.1215881e-001 -1.9658660e-002
+v -7.2028500e-002 6.7046610e-002 -7.2256000e-004
+v -7.8699630e-002 1.7313910e-001 -4.2720470e-002
+v -8.3211970e-002 1.5072131e-001 4.2128500e-003
+v -8.7439060e-002 1.3374875e-001 2.3974700e-003
+v 2.6348020e-002 8.4562230e-002 -2.3151710e-002
+v -7.4901490e-002 7.0419350e-002 -2.2854300e-003
+v -5.4576350e-002 9.1562950e-002 -2.2098700e-002
+v -7.3242520e-002 1.5231332e-001 -3.5703520e-002
+v -7.4550960e-002 1.7218738e-001 -4.7551010e-002
+v -2.8680680e-002 6.8283500e-002 -3.0610160e-002
+v 1.7372900e-002 1.0246037e-001 -2.1487700e-002
+v -8.1257430e-002 7.3025200e-002 7.1020400e-003
+v -7.4982300e-002 1.5407794e-001 -1.8974470e-002
+v -9.1556500e-002 1.3196262e-001 1.0638150e-002
+v -8.2448000e-004 9.5165120e-002 -3.2056320e-002
+v -7.7618830e-002 7.3999130e-002 -5.3263500e-003
+v -7.9858790e-002 7.2755040e-002 3.0420200e-003
+v -8.1627470e-002 7.3470610e-002 1.1161690e-002
+v -7.3679290e-002 1.4785987e-001 -2.0236290e-002
+v -9.1309820e-002 1.4848588e-001 1.6270070e-002
+v -9.0850140e-002 1.4625613e-001 1.4809050e-002
+v -6.8543890e-002 1.7513008e-001 -5.7187900e-002
+v -2.7253960e-002 1.0747453e-001 -2.1279680e-002
+v 2.1443580e-002 1.2273826e-001 -2.9316700e-003
+v -7.9061200e-002 7.3724300e-002 -8.4521000e-004
+v -8.2063500e-002 7.5993670e-002 1.7615500e-003
+v -8.3736580e-002 7.6771840e-002 8.9586000e-003
+v -9.0205720e-002 1.4947775e-001 1.3035090e-002
+v 8.4818000e-004 1.1670025e-001 -1.7337090e-002
+v -7.4577550e-002 1.5164041e-001 -2.8647990e-002
+v -2.9087460e-002 7.2924630e-002 -3.3354470e-002
+v -3.1184020e-002 7.3989530e-002 -3.0339870e-002
+v -3.2606620e-002 7.1955620e-002 -2.4866580e-002
+v -8.0575990e-002 7.6607800e-002 -2.9879400e-003
+v -8.9491020e-002 1.4392581e-001 1.2488490e-002
+v -7.7388410e-002 1.4656426e-001 -4.3543000e-003
+v -7.2896160e-002 1.5834962e-001 -3.4109420e-002
+v 7.1346500e-003 1.1468229e-001 -1.8345640e-002
+v -3.4502610e-002 7.6130020e-002 -2.2373150e-002
+v -8.3890740e-002 8.0789530e-002 2.2951400e-003
+v -8.3740480e-002 7.7240270e-002 4.6673300e-003
+v -8.6204620e-002 8.0930750e-002 1.0535420e-002
+v -8.6061500e-002 7.9931100e-002 1.4440780e-002
+v -8.1542760e-002 7.7950660e-002 2.6727280e-002
+v 2.6666170e-002 1.1268609e-001 -1.0509540e-002
+v -7.6041430e-002 1.5663068e-001 -2.1420480e-002
+v -9.0012110e-002 1.5083344e-001 1.5752740e-002
+v -7.1156510e-002 1.6335125e-001 -4.5360530e-002
+v -3.3210960e-002 7.6873190e-002 -2.7708380e-002
+v -7.3263090e-002 7.9983830e-002 -1.3749940e-002
+v -7.9285950e-002 8.0048830e-002 -7.0125500e-003
+v -8.6034510e-002 8.2645720e-002 1.9542680e-002
+v -8.4335410e-002 8.0729950e-002 2.2180460e-002
+v -7.1351460e-002 1.5727092e-001 -4.2183090e-002
+v -7.3548450e-002 1.6120822e-001 -3.5288420e-002
+v 1.6732620e-002 1.0991230e-001 -1.7020040e-002
+v -3.0978770e-002 7.7020860e-002 -3.2816490e-002
+v -6.2359240e-002 1.7544824e-001 -6.1485990e-002
+v -1.7587870e-002 1.1491318e-001 -1.7205040e-002
+v -8.2354050e-002 8.0876320e-002 -2.4038900e-003
+v -7.8578910e-002 1.4050129e-001 -4.6031000e-003
+v -2.8931080e-002 7.9247620e-002 -3.5049800e-002
+v -3.1225710e-002 8.0413100e-002 -3.2182320e-002
+v -3.3258680e-002 7.9621670e-002 -2.7146060e-002
+v -4.4697400e-002 1.1791537e-001 -1.4725860e-002
+v -7.9723740e-002 8.4226660e-002 -8.7608600e-003
+v -8.5042160e-002 8.3817830e-002 -7.7640000e-005
+v -8.6776400e-002 8.4344860e-002 1.2419030e-002
+v -8.6674670e-002 8.2665010e-002 1.5174340e-002
+v -8.5106250e-002 8.5176580e-002 2.5679440e-002
+v -7.6975760e-002 8.2935940e-002 -1.1450630e-002
+v -8.2776390e-002 8.3430890e-002 -4.3687000e-003
+v -8.6180440e-002 8.2572150e-002 6.3639000e-003
+v -9.1160820e-002 1.4144362e-001 1.5673910e-002
+v -7.4638800e-002 1.4398484e-001 -7.1504600e-003
+v -8.3448500e-002 1.3393299e-001 -1.6873200e-003
+v -7.5804700e-002 1.5134475e-001 -1.9881200e-002
+v -7.4924140e-002 1.5273013e-001 -1.9397440e-002
+v -5.2314440e-002 1.2159646e-001 -1.0798060e-002
+v -3.0734050e-002 8.5427560e-002 -3.0506670e-002
+v -3.2590560e-002 8.1942660e-002 -2.9100210e-002
+v -8.6454830e-002 8.6940490e-002 9.1667000e-004
+v -1.2501820e-002 1.0634409e-001 -2.2360190e-002
+v -8.8585880e-002 1.4605869e-001 9.8780000e-003
+v -8.5609750e-002 1.4712513e-001 6.5981100e-003
+v -8.7511210e-002 1.5061504e-001 1.0152460e-002
+v -6.0113540e-002 3.5550440e-002 4.4907580e-002
+v -8.8284200e-002 8.6869110e-002 8.1029200e-003
+v -8.8812560e-002 8.7765490e-002 1.4226540e-002
+v -8.8001070e-002 8.6626430e-002 1.5466680e-002
+v -8.6991110e-002 8.6444700e-002 2.2420950e-002
+v -7.4609990e-002 1.4727815e-001 -1.4172380e-002
+v -3.4707910e-002 8.4035880e-002 -2.4302260e-002
+v -8.4964900e-002 8.9962540e-002 -3.0068000e-003
+v -8.8091450e-002 8.7741580e-002 4.8489900e-003
+v -9.1490470e-002 1.4543178e-001 2.2277220e-002
+v -9.4380420e-002 1.2183919e-001 1.7904340e-002
+v -2.9164530e-002 8.5393440e-002 -3.3666780e-002
+v -3.0557790e-002 8.8625920e-002 -2.7550670e-002
+v -7.7770550e-002 8.7844840e-002 -1.1694810e-002
+v -8.0728260e-002 8.8204150e-002 -7.8003100e-003
+v -8.3272540e-002 8.9476690e-002 -5.6502900e-003
+v -8.9398710e-002 8.9539000e-002 1.1645550e-002
+v -8.9698390e-002 1.3971257e-001 1.3774760e-002
+v -7.7134890e-002 1.5151225e-001 -5.5823000e-003
+v -5.1121410e-002 1.6374125e-001 -2.6640500e-003
+v -8.6442960e-002 1.2767438e-001 -1.4864100e-003
+v -6.9605590e-002 1.5490763e-001 -5.0188670e-002
+v -8.7265180e-002 9.2110030e-002 4.2059000e-003
+v -8.9086250e-002 9.2377120e-002 1.0569860e-002
+v -8.9612340e-002 9.1599880e-002 1.7812280e-002
+v -8.2732460e-002 1.4196856e-001 1.2529100e-003
+v -7.2618370e-002 1.4368135e-001 -1.0987100e-002
+v -7.7677230e-002 1.6610992e-001 -3.6777320e-002
+v -1.5078060e-002 9.3863440e-002 -3.4317310e-002
+v -7.1057280e-002 1.5476885e-001 -4.5778530e-002
+v -9.2331920e-002 1.2523886e-001 9.1589500e-003
+v -7.6046700e-002 9.1037250e-002 -1.3643150e-002
+v -8.2942810e-002 9.3291700e-002 -6.1856300e-003
+v -1.0411170e-002 9.4592340e-002 -3.3784850e-002
+v -2.9331140e-002 1.1476230e-001 -1.5844640e-002
+v -3.7218250e-002 1.1594244e-001 -1.5173050e-002
+v -1.2429920e-002 1.0286006e-001 -2.3822480e-002
+v 6.6509600e-003 8.8144500e-002 -3.2945810e-002
+v -6.4119900e-003 9.2876210e-002 -3.4817640e-002
+v 1.5800150e-002 1.1996558e-001 -1.1415630e-002
+v 2.9102740e-002 1.0247506e-001 -1.5768380e-002
+v 4.2080690e-002 6.3480630e-002 -2.5405300e-003
+v 2.8723120e-002 9.7943220e-002 -1.7497350e-002
+v -1.9987640e-002 1.0278313e-001 -2.3392920e-002
+v 3.3748350e-002 8.3644140e-002 -1.8630450e-002
+v -1.8685680e-002 1.8689625e-001 -2.0248700e-002
+v 6.4154900e-003 1.1790181e-001 -1.6282740e-002
+v 5.6305210e-002 6.7769910e-002 2.6525000e-003
+v -5.3608300e-003 1.1289400e-001 -1.9613290e-002
+v 4.5769430e-002 6.4628800e-002 -1.2166100e-003
+v -1.0090870e-002 9.8229650e-002 -2.7731360e-002
+v -6.0458520e-002 1.1755645e-001 -1.1354580e-002
+v 1.2933940e-002 1.1887250e-001 -1.3979370e-002
+v 1.5235680e-002 9.4977900e-002 -2.4437140e-002
+v -3.0892950e-002 4.7409030e-002 -2.4954000e-002
+v -1.7766190e-002 1.8572344e-001 -2.3049280e-002
+v -1.3034890e-002 1.1002855e-001 -2.0161170e-002
+v -7.1206550e-002 3.8608570e-002 7.7218000e-004
+v 1.7904800e-002 1.0627709e-001 -1.7729250e-002
+v -3.3623490e-002 1.1840428e-001 -1.1927480e-002
+v -4.9906840e-002 1.1788332e-001 -1.4402480e-002
+v -6.6878100e-003 1.1747209e-001 -1.5359280e-002
+v -1.5451470e-002 1.8597600e-001 -2.4795870e-002
+v -3.0603900e-002 3.8038460e-002 -3.0123840e-002
+v -1.3220270e-002 1.8397188e-001 -2.7519460e-002
+v -4.7859450e-002 1.1162729e-001 -1.7482120e-002
+v -1.3098990e-002 9.0776040e-002 -3.6659270e-002
+v -6.3117340e-002 1.5425437e-001 2.9730400e-003
+v -5.5139750e-002 1.1051601e-001 -1.7672740e-002
+v -1.1096770e-002 1.8202324e-001 -2.8042450e-002
+v -2.6568900e-002 3.4695830e-002 -2.9113750e-002
+v -6.6396600e-003 1.0222209e-001 -2.3519320e-002
+v -5.6996400e-002 1.5741713e-001 6.0244000e-004
+v 1.9076550e-002 9.1870620e-002 -2.4890230e-002
+v 1.3473090e-002 1.2429893e-001 -6.8361400e-003
+v -2.1730490e-002 9.8410960e-002 -2.4306850e-002
+v -1.7142170e-002 9.8057460e-002 -2.4924330e-002
+v -5.8698110e-002 1.5137318e-001 -6.5801000e-004
+v 3.5641100e-003 1.2764883e-001 -4.4672400e-003
+v -8.5369800e-003 9.9921220e-002 -2.4351070e-002
+v -1.2171980e-002 1.8125102e-001 -2.9061170e-002
+v -6.1113980e-002 1.5305212e-001 9.9983000e-004
+v -2.9570620e-002 1.1713871e-001 -1.3675530e-002
+v 3.0530110e-002 1.1221207e-001 -8.1860600e-003
+v -3.1714100e-002 3.5111530e-002 -3.0658990e-002
+v -1.3691130e-002 1.7914707e-001 -2.8126410e-002
+v 1.1620840e-002 1.1548972e-001 -1.6385680e-002
+v -6.1993570e-002 1.5028063e-001 -1.6297100e-003
+v 3.6684020e-002 1.0099570e-001 -9.8485900e-003
+v 4.8512670e-002 7.1798180e-002 6.0005000e-003
+v -4.6583000e-004 1.1983662e-001 -1.3610580e-002
+v 1.6747170e-002 9.0113950e-002 -2.7127190e-002
+v 6.9832400e-003 9.7730080e-002 -2.4800310e-002
+v -4.3226830e-002 4.6263570e-002 -1.1771730e-002
+v -8.3562500e-003 1.1373600e-001 -1.8239810e-002
+v -1.2354410e-002 1.1556773e-001 -1.6486930e-002
+v 4.6834470e-002 7.4354100e-002 1.0139500e-002
+v 2.5319170e-002 1.0931725e-001 -1.3579660e-002
+v -4.2459500e-002 1.1392482e-001 -1.6188050e-002
+v 5.7744640e-002 6.4158440e-002 2.6277600e-003
+v -5.9710530e-002 3.6535780e-002 -9.4949000e-003
+v -3.2078400e-003 1.0962100e-001 -2.1523850e-002
+v 2.7020740e-002 6.1345700e-002 -2.2292060e-002
+v 7.1030200e-003 1.0191162e-001 -2.1230990e-002
+v -3.8225680e-002 1.2465525e-001 -7.3257400e-003
+v 2.5941540e-002 1.1576352e-001 -8.2193900e-003
+v -6.1297960e-002 3.3900220e-002 -9.3216600e-003
+v -5.9466670e-002 1.4743956e-001 -1.8885400e-003
+v 1.0506610e-002 1.0087700e-001 -2.2109510e-002
+v 3.3081340e-002 1.0273382e-001 -1.2787210e-002
+v 1.2517840e-002 1.0475378e-001 -1.9915960e-002
+v 2.3087990e-002 9.3998720e-002 -2.2210680e-002
+v 3.1555430e-002 9.2484730e-002 -1.8204280e-002
+v 6.2723100e-003 9.9910370e-002 -2.2296890e-002
+v -4.0917240e-002 4.6121780e-002 -1.7942580e-002
+v 3.5407360e-002 9.8188850e-002 -1.2008970e-002
+v 9.4135900e-003 1.2121902e-001 -1.2937780e-002
+v 5.3735190e-002 7.2027350e-002 6.8010000e-003
+v 2.5620340e-002 1.1880719e-001 -5.0330800e-003
+v -3.8150260e-002 4.2466610e-002 -2.6893990e-002
+v -2.8212410e-002 1.1116862e-001 -1.8001930e-002
+v -6.0253590e-002 1.4339100e-001 -3.7906300e-003
+v 1.9016880e-002 1.0401450e-001 -1.9333120e-002
+v 7.5446700e-003 9.1682150e-002 -3.1643140e-002
+v -7.0760800e-003 1.2240119e-001 -1.1364410e-002
+v -1.9047500e-002 9.6562130e-002 -2.7579900e-002
+v -1.6953390e-002 1.0669256e-001 -2.2002990e-002
+v -6.7307000e-004 1.0119875e-001 -2.2857770e-002
+v -9.0179300e-003 1.2528031e-001 -7.7912000e-003
+v -6.8136180e-002 1.8006113e-001 -5.8816050e-002
+v -2.3600190e-002 1.1513818e-001 -1.5577390e-002
+v -5.9831220e-002 4.2842260e-002 -6.6469100e-003
+v 5.3124070e-002 5.9012380e-002 -2.8853800e-003
+v -3.6931840e-002 3.7107370e-002 -2.9714170e-002
+v -5.6215140e-002 1.4139213e-001 -2.8027300e-003
+v 3.6695880e-002 1.0372844e-001 -7.9621500e-003
+v -3.5885070e-002 1.2040038e-001 -1.0640470e-002
+v -9.3569500e-003 8.5423730e-002 -3.8112540e-002
+v -6.0127340e-002 1.2041391e-001 -9.3791100e-003
+v -3.9842790e-002 1.2156113e-001 -1.1570310e-002
+v 2.8322200e-002 1.0847957e-001 -1.2623390e-002
+v -1.8733500e-003 1.1593910e-001 -1.7169430e-002
+v 3.8648150e-002 9.0153340e-002 -1.2549680e-002
+v -1.7359200e-003 9.2244170e-002 -3.4310460e-002
+v 5.0000820e-002 6.1612070e-002 -3.4649900e-003
+v 5.5858960e-002 6.2910170e-002 6.9037000e-004
+v 2.0461520e-002 1.1515372e-001 -1.3103780e-002
+v -1.5165840e-002 1.1798075e-001 -1.4465520e-002
+v -7.0859540e-002 7.1510150e-002 3.3895100e-002
+v 2.2674030e-002 8.6606050e-002 -2.4925490e-002
+v 3.5358840e-002 8.7438890e-002 -1.7109050e-002
+v 1.8400920e-002 1.2145507e-001 -7.6804200e-003
+v -2.5425900e-002 4.1421010e-002 -2.9204830e-002
+v -8.2085100e-003 9.6777440e-002 -3.0809780e-002
+v -5.6810660e-002 3.3873940e-002 -1.1166310e-002
+v -3.4588640e-002 4.4744960e-002 -2.7122900e-002
+v -4.0251680e-002 1.1827531e-001 -1.3674080e-002
+v 1.6387020e-002 1.1402346e-001 -1.5496900e-002
+v 4.2635280e-002 6.0797460e-002 -3.4583700e-003
+v -5.0687200e-002 3.5935870e-002 -1.2380790e-002
+v 7.3446800e-003 9.4509570e-002 -2.9683220e-002
+v -1.9706700e-002 9.2917340e-002 -3.4636880e-002
+v -1.2083040e-002 1.2219229e-001 -9.7120900e-003
+v 4.8805930e-002 6.8457810e-002 1.6952900e-003
+v -3.0869700e-003 9.8402500e-002 -2.7403170e-002
+v -5.3198790e-002 1.3672896e-001 -1.6580500e-003
+v -4.7290060e-002 1.3055355e-001 1.6909100e-003
+v 4.4651700e-003 1.2044039e-001 -1.3931400e-002
+v -2.3850100e-003 1.2290534e-001 -1.0382460e-002
+v -2.4833330e-002 9.5858030e-002 -2.5162110e-002
+v -4.2296900e-002 3.6291920e-002 -2.7253600e-002
+v -5.4388260e-002 1.3404922e-001 -3.9920400e-003
+v -5.0539380e-002 1.3336659e-001 -1.0872200e-003
+v 2.6040300e-003 9.6942660e-002 -2.8407060e-002
+v -7.8163100e-003 1.2821209e-001 -1.9430400e-003
+v 6.5111700e-003 1.3002517e-001 9.2881000e-004
+v 3.4742860e-002 9.2274140e-002 -1.5654590e-002
+v -6.7787700e-002 1.8088887e-001 -5.8191050e-002
+v -3.3715410e-002 1.1151566e-001 -1.8078440e-002
+v 4.4630400e-003 1.2427294e-001 -9.4291400e-003
+v -2.3370170e-002 9.3392760e-002 -3.2031820e-002
+v -4.8982070e-002 1.2980647e-001 -1.3229400e-003
+v -7.8164000e-004 1.2822918e-001 -3.2490000e-003
+v 2.4960400e-003 8.9857600e-002 -3.3628450e-002
+v 7.4553300e-003 1.1196790e-001 -1.9554260e-002
+v 2.8791140e-002 9.1157340e-002 -2.0370210e-002
+v -5.3590150e-002 1.2437450e-001 -7.3470400e-003
+v -4.7743630e-002 1.2064432e-001 -1.2812990e-002
+v -1.9616230e-002 1.2109197e-001 -9.5487700e-003
+v -6.5047370e-002 1.7999148e-001 -5.9758600e-002
+v -5.1704160e-002 3.7620360e-002 -1.1763450e-002
+v -5.2124270e-002 1.2929832e-001 -4.1187000e-003
+v -4.5334450e-002 1.2891494e-001 1.5819100e-003
+v -3.0471200e-003 1.2919453e-001 -1.0688000e-003
+v 7.2129600e-003 1.2721957e-001 -5.2073700e-003
+v 1.1669320e-002 1.2720154e-001 -3.1850900e-003
+v 5.3056400e-002 6.9708830e-002 3.1291400e-003
+v -6.3021150e-002 1.7810951e-001 -6.0393570e-002
+v 2.8204800e-002 6.4391270e-002 -2.0698040e-002
+v 3.4400180e-002 1.0503000e-001 -1.0224920e-002
+v 3.0975190e-002 1.0790250e-001 -1.1058430e-002
+v -4.8984390e-002 1.1480518e-001 -1.5966690e-002
+v -3.2821710e-002 1.2300500e-001 -5.9088300e-003
+v -5.0792860e-002 1.2716487e-001 -4.8183200e-003
+v -3.5301670e-002 1.2547815e-001 -3.1542800e-003
+v 5.6455250e-002 6.9951490e-002 4.9191700e-003
+v -1.6240450e-002 1.2512177e-001 -3.6499700e-003
+v -1.6970400e-002 1.1119793e-001 -1.9586410e-002
+v -5.4088120e-002 3.9781210e-002 -1.0544680e-002
+v -3.4190490e-002 4.7514010e-002 -2.2301500e-002
+v 1.3699090e-002 9.3914220e-002 -2.6427690e-002
+v 8.8000000e-004 9.9234930e-002 -2.4355670e-002
+v -4.6459460e-002 1.2723953e-001 -4.8843300e-003
+v -4.1735500e-002 1.2687599e-001 -4.1742000e-003
+v -2.1000480e-002 1.2313643e-001 -6.1190100e-003
+v -1.2130450e-002 1.2572568e-001 -5.2007900e-003
+v -4.3822400e-003 1.2640753e-001 -6.9495200e-003
+v 1.4085700e-003 3.4781990e-002 -2.3265200e-002
+v -1.4846200e-002 3.5070930e-002 -2.6071900e-002
+v -2.1399500e-002 3.4795120e-002 -2.7958820e-002
+v 1.2009220e-002 3.5961900e-002 -2.1735750e-002
+v 3.8249200e-003 3.6129220e-002 -2.3878090e-002
+v -5.1139560e-002 9.6617580e-002 -2.2095120e-002
+v -5.4813320e-002 9.8102480e-002 -2.1425370e-002
+v -2.7597040e-002 1.6979824e-001 -1.8170420e-002
+v 1.3359870e-002 3.9377410e-002 -2.2496330e-002
+v 4.3919300e-003 3.8674430e-002 -2.4170290e-002
+v -6.8478200e-003 3.6444540e-002 -2.5177120e-002
+v -1.3280260e-002 3.7699590e-002 -2.6391810e-002
+v -4.7672760e-002 3.6116650e-002 -1.3301210e-002
+v -4.5590120e-002 1.0853826e-001 -1.8796680e-002
+v -5.0095670e-002 1.0990925e-001 -1.8504510e-002
+v -6.5766640e-002 3.6469550e-002 -7.2073000e-003
+v -2.3455840e-002 1.6824727e-001 -1.8822880e-002
+v -4.5918000e-003 3.8404570e-002 -2.5412870e-002
+v -2.4954130e-002 3.7441060e-002 -2.9152720e-002
+v 2.9007770e-002 3.7358220e-002 -2.7474000e-004
+v -7.9468800e-003 4.1489920e-002 -2.5911270e-002
+v -1.6803800e-002 3.9753810e-002 -2.7565350e-002
+v -6.5156150e-002 1.4034537e-001 -7.6848600e-003
+v -4.7080100e-002 4.0700690e-002 -1.1869830e-002
+v -6.8470630e-002 3.7477700e-002 -4.9557400e-003
+v 3.7326850e-002 4.0209510e-002 -8.5850000e-004
+v 3.5349870e-002 4.1257050e-002 -2.8075100e-003
+v 5.1820700e-003 4.1536320e-002 -2.4065670e-002
+v 1.8660660e-002 1.0030784e-001 -2.2127290e-002
+v -6.0510780e-002 1.0748450e-001 -1.7042300e-002
+v -6.2374340e-002 4.0146090e-002 -7.4040200e-003
+v 2.5456950e-002 3.9483890e-002 -4.0251400e-003
+v -2.2828000e-004 4.3394940e-002 -2.5124420e-002
+v -8.1088400e-003 4.3439060e-002 -2.6140070e-002
+v -1.7362450e-002 4.3237420e-002 -2.7665190e-002
+v -2.6416670e-002 4.4674020e-002 -2.8209740e-002
+v 3.8064500e-003 1.0944331e-001 -2.0203790e-002
+v -5.8232370e-002 9.5690400e-002 -2.0616030e-002
+v -6.6122370e-002 4.2341260e-002 -2.7538800e-003
+v -6.0959920e-002 9.4173040e-002 -1.9015670e-002
+v 3.1352250e-002 4.2649280e-002 -4.6745000e-003
+v -3.3540900e-002 3.6342620e-002 4.9089960e-002
+v 1.7252780e-002 4.4335610e-002 -2.3067190e-002
+v 1.0637660e-002 4.4161560e-002 -2.4926170e-002
+v 4.3843100e-003 4.5806710e-002 -2.6788990e-002
+v -8.2506400e-003 4.5148720e-002 -2.8441070e-002
+v -1.5748410e-002 4.5043860e-002 -2.7877790e-002
+v 2.8990330e-002 4.4697850e-002 -6.1863000e-003
+v 8.1686400e-003 4.5053030e-002 -2.5178740e-002
+v -9.6291000e-004 4.5378230e-002 -2.7308280e-002
+v -1.7033400e-003 4.7819200e-002 -2.9928930e-002
+v -3.1535830e-002 4.4740410e-002 -2.8079410e-002
+v -3.3619650e-002 1.5691468e-001 -1.1024870e-002
+v -5.0751180e-002 4.3109620e-002 -1.0018680e-002
+v 3.6890890e-002 4.7353200e-002 -6.1057100e-003
+v 2.4975630e-002 4.2644580e-002 -7.0169900e-003
+v 2.4562420e-002 4.8369560e-002 -1.9672760e-002
+v 1.3964040e-002 4.5579170e-002 -2.4706510e-002
+v 1.3376130e-002 4.8630300e-002 -2.6551500e-002
+v 3.7308900e-003 4.8127990e-002 -2.9025970e-002
+v -8.7947000e-003 4.7056850e-002 -2.9881630e-002
+v -1.3753770e-002 5.1865060e-002 -3.2243480e-002
+v -2.1200840e-002 4.6657090e-002 -2.7951320e-002
+v 3.9693540e-002 4.5658580e-002 -4.5274100e-003
+v 3.3627400e-002 4.8717730e-002 -6.3904600e-003
+v -6.5352120e-002 9.9294570e-002 -1.6820150e-002
+v 1.2868100e-003 5.0383670e-002 -3.0357440e-002
+v -8.1797500e-003 4.9845800e-002 -3.1071390e-002
+v -1.7184350e-002 4.8210500e-002 -2.9741930e-002
+v -2.6049450e-002 4.7692500e-002 -2.6149500e-002
+v -8.4747010e-002 1.1078350e-001 3.9488380e-002
+v -5.1316870e-002 4.8270690e-002 -7.9310500e-003
+v -8.2506510e-002 1.2765487e-001 -4.6796400e-003
+v 3.8663690e-002 5.1696670e-002 -6.6910200e-003
+v -7.5643160e-002 9.9440450e-002 -1.1927610e-002
+v 2.0284470e-002 5.1349190e-002 -2.4895380e-002
+v 5.9436000e-003 5.0976660e-002 -2.9119360e-002
+v -2.5528290e-002 5.1472710e-002 -2.6884680e-002
+v -3.5562670e-002 4.9399890e-002 -1.2865040e-002
+v -4.2818980e-002 1.6220182e-001 -1.0337510e-002
+v -6.5593600e-002 1.7665711e-001 -6.0504730e-002
+v -3.4151080e-002 1.7442797e-001 -1.3312550e-002
+v 4.3673180e-002 5.0162230e-002 -5.9843500e-003
+v -5.0342410e-002 1.5546197e-001 -5.1927700e-003
+v 2.5464180e-002 5.4029700e-002 -2.1691010e-002
+v 1.0149790e-002 4.9258540e-002 -2.7750590e-002
+v -2.2043190e-002 5.3612020e-002 -3.0135610e-002
+v -3.2875520e-002 5.1677630e-002 -1.0888650e-002
+v -3.7613820e-002 4.9534770e-002 -1.1626140e-002
+v -4.0750630e-002 4.9285110e-002 -1.1286200e-002
+v -4.6385170e-002 4.7490850e-002 -1.0085980e-002
+v 4.4473170e-002 5.3293010e-002 -6.3327900e-003
+v 3.3205620e-002 5.1020650e-002 -7.2382500e-003
+v 1.5678350e-002 5.1169270e-002 -2.6397810e-002
+v 6.8341700e-003 5.5010170e-002 -3.0561130e-002
+v 2.1424700e-003 5.5502800e-002 -3.1334400e-002
+v 5.9285000e-004 5.2867950e-002 -3.0513830e-002
+v -3.6481400e-003 5.1869000e-002 -3.1457940e-002
+v -9.4245600e-003 5.5399220e-002 -3.3653980e-002
+v -1.9302150e-002 5.8224770e-002 -3.3919700e-002
+v -6.1084270e-002 1.3386190e-001 -7.2248900e-003
+v -4.3309760e-002 5.5656840e-002 -1.1402110e-002
+v -6.1080540e-002 1.6833773e-001 -5.9192060e-002
+v 4.7574690e-002 5.2943630e-002 -5.1300300e-003
+v -3.7403030e-002 1.1150775e-001 -1.8243310e-002
+v 1.9972490e-002 5.4409710e-002 -2.7108230e-002
+v 5.3974800e-003 5.8382570e-002 -3.0903760e-002
+v -1.0603590e-002 5.3602910e-002 -3.3403350e-002
+v -3.4998290e-002 5.2331560e-002 -1.0347380e-002
+v -4.6471230e-002 5.1304340e-002 -9.8299800e-003
+v -6.7945360e-002 1.1493603e-001 -9.5107300e-003
+v -7.1048210e-002 1.5161088e-001 -4.4679270e-002
+v -5.8903800e-003 3.4790620e-002 -2.4224470e-002
+v 1.6842140e-002 5.5555670e-002 -2.8284560e-002
+v 1.0711040e-002 5.4687610e-002 -2.9767520e-002
+v -1.1826800e-003 5.9492420e-002 -3.3360920e-002
+v -5.2325900e-003 5.5688960e-002 -3.2840220e-002
+v -5.1705830e-002 5.2470760e-002 -7.4047200e-003
+v -5.2626360e-002 6.0043760e-002 -8.9566900e-003
+v -7.2598590e-002 9.7762720e-002 -1.4434510e-002
+v 4.4331260e-002 5.5818010e-002 -6.0362700e-003
+v 3.8463400e-002 5.4934820e-002 -6.1822500e-003
+v 3.8838620e-002 5.7808260e-002 -5.2584800e-003
+v -9.2015400e-003 5.9510130e-002 -3.4437110e-002
+v -3.5262560e-002 5.5284900e-002 -1.0545060e-002
+v -3.8336450e-002 5.4503540e-002 -1.0905320e-002
+v -1.7727540e-002 3.6289540e-002 5.2222250e-002
+v 5.0006490e-002 5.8095800e-002 -4.6211800e-003
+v 4.6133970e-002 5.9278810e-002 -4.7769600e-003
+v 1.5110300e-002 5.9819840e-002 -2.8645750e-002
+v 1.0312380e-002 5.7586530e-002 -2.9995250e-002
+v -6.1353400e-003 6.0256790e-002 -3.4695830e-002
+v -1.2318220e-002 5.9396390e-002 -3.5268510e-002
+v -1.4466910e-002 6.3136020e-002 -3.6865870e-002
+v -4.6650260e-002 5.9840950e-002 -1.2135840e-002
+v -5.6572080e-002 1.2480275e-001 -7.1885700e-003
+v -7.9237500e-002 1.2055419e-001 -5.6744800e-003
+v -7.9334790e-002 1.2560650e-001 -6.1175900e-003
+v 2.2340000e-002 5.8492230e-002 -2.6014120e-002
+v 7.6270400e-003 6.2098330e-002 -3.1135840e-002
+v 3.3101700e-003 6.0456840e-002 -3.2481070e-002
+v -1.6811880e-002 6.1275230e-002 -3.5929330e-002
+v -3.2491910e-002 5.7196350e-002 -1.2104730e-002
+v -3.4108240e-002 6.1466560e-002 -1.3053130e-002
+v -3.3896980e-002 5.7025330e-002 -1.1047570e-002
+v -3.8623580e-002 5.8303290e-002 -1.1505750e-002
+v -4.5008400e-002 6.2723940e-002 -1.3390450e-002
+v -5.6896010e-002 1.3398739e-001 -5.6270700e-003
+v -4.4853890e-002 1.5746031e-001 -8.6731600e-003
+v -7.8609550e-002 6.9656870e-002 1.1810740e-002
+v -2.3730020e-002 1.0186156e-001 -2.3836400e-002
+v -2.8122930e-002 9.9322390e-002 -2.3580130e-002
+v -5.0076720e-002 1.4997652e-001 -3.6419700e-003
+v -3.3048420e-002 9.5958590e-002 -2.3426460e-002
+v 1.9520390e-002 6.2064770e-002 -2.7292470e-002
+v -3.8864710e-002 1.0333987e-001 -2.0641400e-002
+v -4.8952940e-002 5.6281090e-002 -1.0220880e-002
+v -5.3993040e-002 1.4498656e-001 -1.1093400e-003
+v -4.5530560e-002 9.8510850e-002 -2.1729510e-002
+v -5.0910960e-002 1.0074570e-001 -2.1619430e-002
+v 2.3245830e-002 6.2792530e-002 -2.5047990e-002
+v 9.7412800e-003 6.3181400e-002 -3.1141370e-002
+v -8.6614000e-004 6.4559630e-002 -3.4490930e-002
+v -8.5264000e-003 6.4001730e-002 -3.5850480e-002
+v -4.8451500e-002 6.4794120e-002 -1.3029910e-002
+v -5.2325160e-002 1.0614813e-001 -1.9271240e-002
+v -5.5265350e-002 1.0216682e-001 -1.9897100e-002
+v -5.9042010e-002 9.9032210e-002 -1.9222950e-002
+v -5.7846760e-002 1.0433496e-001 -1.8525740e-002
+v -2.7113460e-002 1.7332156e-001 -1.8538890e-002
+v 2.2832000e-002 6.7082570e-002 -2.6297510e-002
+v 1.4519060e-002 6.4595540e-002 -2.9855690e-002
+v 1.1471330e-002 6.7581440e-002 -3.0901170e-002
+v -1.7739360e-002 6.6260830e-002 -3.7657310e-002
+v -6.5059750e-002 1.3452104e-001 -8.0899900e-003
+v -7.5829320e-002 1.4244605e-001 -5.8090000e-003
+v -4.1362350e-002 6.1637330e-002 -1.2813770e-002
+v -5.6147890e-002 6.1921550e-002 -5.7541100e-003
+v -6.2126110e-002 6.2845360e-002 -4.5202600e-003
+v -3.7292480e-002 1.6449057e-001 -1.3627050e-002
+v -1.9818920e-002 1.6509494e-001 -1.7608980e-002
+v 6.2881100e-003 6.5416350e-002 -3.2563040e-002
+v -5.9250500e-003 6.9515630e-002 -3.5933480e-002
+v -1.0538630e-002 6.7999180e-002 -3.6517060e-002
+v -3.5385700e-002 6.6817430e-002 -1.5434860e-002
+v -5.3994500e-002 6.4638700e-002 -9.3254900e-003
+v -6.3852310e-002 6.5572310e-002 -6.9393300e-003
+v -6.3920880e-002 1.2774242e-001 -8.5494600e-003
+v -2.6940700e-002 3.6184050e-002 5.3351850e-002
+v 1.9618650e-002 6.7007390e-002 -2.8356120e-002
+v 1.2275180e-002 6.9933940e-002 -3.1553160e-002
+v 5.4265100e-003 6.8247960e-002 -3.2730520e-002
+v -4.4084200e-003 6.6619200e-002 -3.4870250e-002
+v -2.1911350e-002 6.7144790e-002 -3.6535750e-002
+v -4.5643150e-002 1.5466949e-001 -7.2969400e-003
+v -5.1673460e-002 6.6850660e-002 -1.2120350e-002
+v -5.8105180e-002 6.6465950e-002 -1.0044340e-002
+v -5.6992260e-002 1.4311862e-001 -2.2403000e-003
+v -8.0651110e-002 1.3119854e-001 -4.4397800e-003
+v -5.6544310e-002 1.2850938e-001 -6.2014700e-003
+v 1.7758080e-002 7.0138540e-002 -2.9404680e-002
+v 6.4980500e-003 7.0791870e-002 -3.3525310e-002
+v 7.5831000e-004 7.0434460e-002 -3.4462560e-002
+v -1.3235950e-002 6.9292820e-002 -3.7917490e-002
+v -6.7390780e-002 1.1889688e-001 -8.7301400e-003
+v -3.8119520e-002 6.4162310e-002 -1.3829140e-002
+v 1.8527400e-003 1.1303356e-001 -1.9794270e-002
+v -7.5950810e-002 6.8170610e-002 1.8117970e-002
+v -1.0001990e-002 7.2671480e-002 -3.7661370e-002
+v -1.7976070e-002 7.0613770e-002 -3.8443880e-002
+v -2.3035990e-002 7.2778460e-002 -3.8072640e-002
+v -2.6120100e-002 7.1177480e-002 -3.5451530e-002
+v -6.8535420e-002 1.3929375e-001 -7.8046600e-003
+v -3.5263040e-002 7.1067650e-002 -1.8011860e-002
+v -4.1558180e-002 6.9774010e-002 -1.6774100e-002
+v -5.2831730e-002 7.0298920e-002 -1.4864960e-002
+v -6.6978850e-002 6.7638980e-002 -6.8094400e-003
+v -1.0244470e-002 1.7895826e-001 -2.9538870e-002
+v -7.5272650e-002 1.2680098e-001 -8.0241700e-003
+v -8.7359900e-002 1.1248315e-001 4.2049490e-002
+v 8.7503000e-003 7.4301560e-002 -3.3398210e-002
+v -6.4249520e-002 1.6045024e-001 -5.7041470e-002
+v -4.4354010e-002 7.3372220e-002 -1.7874430e-002
+v -4.5762580e-002 6.9445320e-002 -1.5928780e-002
+v -4.7957440e-002 7.2542990e-002 -1.6106990e-002
+v -5.7822630e-002 6.9538010e-002 -1.4416470e-002
+v -7.2071600e-002 7.1538150e-002 -7.4714400e-003
+v 2.5472930e-002 7.4094500e-002 -2.4938540e-002
+v 1.5719730e-002 7.3756350e-002 -2.9747770e-002
+v 4.8214000e-003 7.3763980e-002 -3.4552450e-002
+v -2.2528600e-003 7.3921320e-002 -3.5887190e-002
+v -7.3834900e-003 7.4799620e-002 -3.7223830e-002
+v -2.0225340e-002 7.7095190e-002 -3.9044290e-002
+v -3.4016180e-002 7.2101270e-002 -2.0823150e-002
+v -3.8493370e-002 7.2839870e-002 -1.7502230e-002
+v -6.4392550e-002 7.3116330e-002 -1.5335340e-002
+v -6.4480660e-002 7.0187350e-002 -1.2261750e-002
+v -2.3854330e-002 1.6164528e-001 -1.4504190e-002
+v 2.2104450e-002 7.2692600e-002 -2.6900140e-002
+v 1.5532370e-002 7.6586960e-002 -2.9606940e-002
+v 1.1574050e-002 7.4860570e-002 -3.1383860e-002
+v -1.4731560e-002 7.7640750e-002 -3.8490670e-002
+v -1.6018820e-002 7.4288800e-002 -3.8864420e-002
+v -5.1103620e-002 7.3071950e-002 -1.6243060e-002
+v -5.7989540e-002 7.4017880e-002 -1.7522320e-002
+v -6.9608380e-002 7.2322890e-002 -1.0934430e-002
+v -7.5996110e-002 1.1714132e-001 -6.5577200e-003
+v -3.7987660e-002 1.0751453e-001 -1.9975760e-002
+v 1.0696210e-002 7.9889200e-002 -3.2009580e-002
+v -5.3433400e-003 7.8264580e-002 -3.7476940e-002
+v -2.6081990e-002 7.6191290e-002 -3.6780200e-002
+v -3.9161040e-002 1.5718885e-001 -1.0580510e-002
+v -6.5609880e-002 7.5860010e-002 -1.6750060e-002
+v -7.0177600e-002 7.5663330e-002 -1.3839210e-002
+v -7.4291360e-002 7.4808360e-002 -9.3537900e-003
+v -6.3428890e-002 1.7185387e-001 -6.1412170e-002
+v 3.0684890e-002 7.5726870e-002 -2.0778090e-002
+v 1.9305010e-002 7.9017870e-002 -2.7743990e-002
+v -8.5992100e-003 7.9338730e-002 -3.7905180e-002
+v -2.3200110e-002 7.6568500e-002 -3.8386500e-002
+v -3.8117820e-002 7.6390120e-002 -1.8644360e-002
+v -4.4231130e-002 7.7664130e-002 -1.9026580e-002
+v -5.1025500e-002 7.5705070e-002 -1.8186900e-002
+v -7.0595130e-002 1.2994832e-001 -8.7629200e-003
+v 2.8147660e-002 7.8785370e-002 -2.2432450e-002
+v 7.6016000e-003 7.9435920e-002 -3.3714560e-002
+v 4.9502400e-003 7.8027250e-002 -3.4409750e-002
+v -1.5858350e-002 8.1165550e-002 -3.9185590e-002
+v -1.8502080e-002 8.3343870e-002 -3.9010720e-002
+v -7.9739350e-002 1.3606854e-001 -4.1482100e-003
+v -3.0980180e-002 1.6634656e-001 -1.6241160e-002
+v -3.5749800e-002 7.7248350e-002 -1.9374020e-002
+v -4.8944740e-002 7.9086360e-002 -1.9575700e-002
+v -5.5065860e-002 7.8089190e-002 -1.9755480e-002
+v 2.3706000e-002 8.0240410e-002 -2.5450120e-002
+v 1.2254110e-002 8.3456700e-002 -3.0771580e-002
+v 1.8549900e-003 8.4692790e-002 -3.4838500e-002
+v -2.0857000e-004 7.8941410e-002 -3.5782080e-002
+v -4.2710000e-004 8.2947370e-002 -3.6380660e-002
+v -4.4101600e-003 8.2794510e-002 -3.7467250e-002
+v -3.3202320e-002 1.0578320e-001 -2.0647590e-002
+v -3.9206970e-002 8.1536380e-002 -2.0571000e-002
+v -6.0355410e-002 7.9766610e-002 -1.9375540e-002
+v -4.1771830e-002 1.0396706e-001 -2.0832940e-002
+v -1.1204010e-002 8.2713320e-002 -3.8489610e-002
+v -2.3181500e-002 8.1686990e-002 -3.8329160e-002
+v -2.7233190e-002 8.0570950e-002 -3.6620670e-002
+v -3.5470180e-002 8.0196070e-002 -2.2325910e-002
+v -4.4864210e-002 8.1997900e-002 -2.0473520e-002
+v -5.0647890e-002 8.2309430e-002 -2.1365890e-002
+v -5.5522610e-002 8.1927600e-002 -2.1353790e-002
+v -8.8089610e-002 1.1135484e-001 1.8516150e-002
+v -7.2036080e-002 1.1107918e-001 4.5361400e-002
+v -3.3359780e-002 1.6986395e-001 -1.5448990e-002
+v -6.6839030e-002 6.2170510e-002 2.1576840e-002
+v 3.0730560e-002 8.1968990e-002 -2.0040460e-002
+v 1.6224320e-002 8.6480380e-002 -2.8952010e-002
+v -6.9855630e-002 1.0027892e-001 -1.4847830e-002
+v -6.3836170e-002 8.1704600e-002 -1.8908860e-002
+v -6.7914820e-002 8.0136290e-002 -1.7128200e-002
+v -4.5752080e-002 1.6340754e-001 -8.1780500e-003
+v 1.1727540e-002 8.8010780e-002 -3.0860110e-002
+v 7.3334800e-003 8.5270000e-002 -3.2829380e-002
+v -3.4356500e-003 8.7017890e-002 -3.6461000e-002
+v -2.6964110e-002 8.4512810e-002 -3.6361740e-002
+v -3.6553370e-002 8.5316190e-002 -2.2576200e-002
+v -3.8791090e-002 8.5232710e-002 -2.1917600e-002
+v -5.7676940e-002 8.6258340e-002 -2.1098320e-002
+v -6.2581810e-002 8.6394530e-002 -1.9169290e-002
+v -7.1395340e-002 1.2468846e-001 -8.5944200e-003
+v 1.4801570e-002 9.9040900e-002 -2.2842920e-002
+v -2.1162860e-002 1.7491852e-001 -2.1977110e-002
+v -1.4824250e-002 8.7288840e-002 -3.8317070e-002
+v -2.3285750e-002 8.9468030e-002 -3.6027250e-002
+v -5.1595650e-002 8.4422070e-002 -2.1600960e-002
+v -6.9481040e-002 8.5656460e-002 -1.7198420e-002
+v -7.0917210e-002 1.0754846e-001 -1.1496630e-002
+v 3.0145320e-002 8.6284000e-002 -2.0408140e-002
+v -5.5578110e-002 1.1567692e-001 -1.4645990e-002
+v -8.0981100e-003 8.9070080e-002 -3.6552200e-002
+v -8.1206310e-002 1.1205088e-001 -8.8299000e-004
+v -1.8772170e-002 8.9838040e-002 -3.6991710e-002
+v -2.1100420e-002 8.6587670e-002 -3.7849050e-002
+v -2.5809910e-002 8.8889590e-002 -3.5082250e-002
+v -4.8984800e-002 9.0731760e-002 -2.1817170e-002
+v -3.5874870e-002 3.4776000e-002 -3.0845200e-002
+v -3.3164390e-002 3.3606540e-002 -2.9721880e-002
+v -2.5964020e-002 3.3487000e-002 -2.6321120e-002
+v -1.6717530e-002 3.3611640e-002 -2.4625420e-002
+v -5.3486300e-003 3.3829010e-002 -2.2600430e-002
+v 6.4843500e-003 3.4293000e-002 -2.0854930e-002
+v 1.3950350e-002 3.4880000e-002 -1.8612870e-002
+v -4.2465980e-002 3.4189100e-002 -2.7260650e-002
+v -3.3241100e-002 3.3578760e-002 -2.6719450e-002
+v 6.2813500e-003 3.4165800e-002 -1.8764230e-002
+v -4.4265790e-002 3.3663660e-002 -2.1914420e-002
+v -2.3671460e-002 3.3630970e-002 -2.3217760e-002
+v -1.1558580e-002 3.3895430e-002 -2.1054260e-002
+v -2.0406400e-003 3.4053940e-002 -1.9331070e-002
+v 1.7323900e-003 3.4459660e-002 -1.6607870e-002
+v -2.7316070e-002 3.3910070e-002 -2.1353750e-002
+v -1.3371080e-002 3.4361580e-002 -1.9023720e-002
+v 9.5887300e-003 3.4207220e-002 -1.5424050e-002
+v -1.4981540e-002 3.5878180e-002 -1.7992380e-002
+v -2.3474300e-003 3.5903130e-002 -1.5929740e-002
+v 2.2544300e-003 3.6411540e-002 -1.4783970e-002
+v -3.5199130e-002 3.3835210e-002 -2.0508290e-002
+v -2.6075450e-002 3.5918600e-002 -1.9405170e-002
+v 8.2740600e-003 3.5645200e-002 -1.2648700e-002
+v 1.0473640e-002 3.4742600e-002 -1.1262870e-002
+v 1.4055380e-002 3.4483430e-002 -1.4495730e-002
+v -3.6970520e-002 3.5680360e-002 -1.5007790e-002
+v -2.4719500e-003 3.8408770e-002 -1.4159030e-002
+v -3.9481890e-002 3.3618220e-002 -2.3612470e-002
+v -4.1091510e-002 3.4006000e-002 -1.1997540e-002
+v -3.1589810e-002 3.5592330e-002 -1.9204150e-002
+v -2.0086310e-002 3.8064450e-002 -1.7220790e-002
+v -1.1113250e-002 3.8290290e-002 -1.5646360e-002
+v 4.4522600e-003 3.7705190e-002 -1.2957650e-002
+v 1.5870480e-002 3.4416230e-002 -2.9666500e-003
+v -4.7872000e-002 3.4136300e-002 -1.5418250e-002
+v -4.7521640e-002 3.3622720e-002 -1.2804590e-002
+v -3.3407340e-002 3.7577040e-002 -1.6158190e-002
+v -2.7851470e-002 3.8404330e-002 -1.7210420e-002
+v -8.5065300e-003 3.9028950e-002 -1.3000800e-002
+v 6.4552500e-003 3.8165190e-002 -1.0164860e-002
+v 7.4147100e-003 3.4659190e-002 -3.0116800e-003
+v 1.1966200e-002 3.4335400e-002 -5.9571300e-003
+v 2.0414820e-002 3.5567580e-002 -3.7806900e-003
+v -1.9288780e-002 3.8762570e-002 -1.4202620e-002
+v -1.1390100e-003 3.9176760e-002 -1.0381370e-002
+v 3.8149200e-003 3.9024470e-002 -8.0827300e-003
+v 7.5208200e-003 3.6733400e-002 -6.7614300e-003
+v 1.9968120e-002 3.4843990e-002 -1.8984900e-003
+v -4.5058400e-002 3.3600490e-002 -1.2527510e-002
+v -3.0754850e-002 3.8639810e-002 -1.4050770e-002
+v -5.1499810e-002 3.3729110e-002 -1.2082510e-002
+v -2.3756860e-002 3.8585750e-002 -1.1093270e-002
+v 3.9734700e-003 3.8208550e-002 -3.7963500e-003
+v 9.5485400e-003 3.4232620e-002 1.7162000e-003
+v 2.9086550e-002 3.5799990e-002 3.5630900e-003
+v -5.5965200e-002 3.3529910e-002 -9.1246200e-003
+v -1.9523510e-002 3.8505210e-002 -4.5434500e-003
+v 1.6363470e-002 3.4394790e-002 2.2948600e-003
+v 2.1324740e-002 3.4624040e-002 5.6444000e-003
+v -3.9670300e-002 3.6174000e-002 -7.3397700e-003
+v -1.4251730e-002 3.8648030e-002 -4.3030400e-003
+v 2.3262300e-003 3.5348200e-002 2.3246000e-003
+v 1.4014300e-002 3.5703800e-002 3.8878900e-003
+v 1.5322800e-002 3.6239700e-002 3.6628500e-003
+v 2.3753130e-002 3.4670710e-002 3.9885300e-003
+v 3.2369180e-002 3.5816010e-002 7.0246300e-003
+v -6.3715900e-002 3.3776930e-002 -8.0065600e-003
+v -6.4266880e-002 3.3562500e-002 -5.1253200e-003
+v -3.8066600e-002 3.8518600e-002 -7.3079600e-003
+v -9.4308800e-003 3.8887690e-002 -7.4848700e-003
+v 3.9677800e-003 3.4200210e-002 4.9754500e-003
+v 9.4292600e-003 3.6030400e-002 4.5275100e-003
+v 2.9859020e-002 3.4980130e-002 9.8349300e-003
+v -5.2730060e-002 3.3497900e-002 -1.8117500e-003
+v -4.1271000e-002 3.3855400e-002 -1.8800800e-003
+v -3.1105000e-003 3.8946190e-002 -2.7793900e-003
+v 6.2194100e-003 3.5134100e-002 6.5492800e-003
+v 2.0897900e-002 3.5937100e-002 8.7849000e-003
+v 3.5606010e-002 3.6526640e-002 9.8155300e-003
+v -6.7078340e-002 3.3840100e-002 -6.1688300e-003
+v -8.1140000e-004 3.7424170e-002 4.7721500e-003
+v 3.1492300e-003 3.4125310e-002 1.1762220e-002
+v 4.9172000e-003 3.3997100e-002 9.1666100e-003
+v 2.5130800e-002 3.4546910e-002 1.1012580e-002
+v 2.8248620e-002 3.5046370e-002 1.6016700e-002
+v -6.7032970e-002 6.5145960e-002 2.7292860e-002
+v -4.6380170e-002 3.3605230e-002 -8.9435000e-004
+v -3.3163400e-002 3.8195400e-002 -5.2520000e-004
+v -3.2074200e-002 3.8323400e-002 -4.2109000e-004
+v -2.1692690e-002 3.8266010e-002 4.5100800e-003
+v 2.3930750e-002 3.4816710e-002 1.7739160e-002
+v 4.2719120e-002 3.9977070e-002 8.9321600e-003
+v -5.8604080e-002 3.3462230e-002 -2.1667000e-004
+v -3.7314400e-002 3.3633000e-002 4.5724700e-003
+v -1.0423990e-002 3.8488570e-002 6.2292700e-003
+v -1.3896900e-003 3.8651360e-002 2.3966500e-003
+v -3.0845000e-004 3.5462480e-002 8.2607200e-003
+v -1.4089000e-003 3.6193080e-002 1.2944550e-002
+v 2.2252900e-002 3.6583300e-002 1.3979700e-002
+v -7.0961830e-002 3.4345730e-002 -7.8374000e-004
+v -6.9066180e-002 3.3717630e-002 -1.9761000e-004
+v -6.4825640e-002 3.3505860e-002 2.8222500e-003
+v -4.7059660e-002 3.3501860e-002 3.5646400e-003
+v -3.6953800e-003 3.8172780e-002 1.3046800e-002
+v 3.3475850e-002 3.6447340e-002 1.6266960e-002
+v 3.7249610e-002 3.7509920e-002 1.4815820e-002
+v -4.5675940e-002 3.3703640e-002 6.4300300e-003
+v -3.8639270e-002 3.3937310e-002 8.5506500e-003
+v -9.5064100e-003 3.8352640e-002 1.5570660e-002
+v 2.1499800e-002 3.5807100e-002 1.8169400e-002
+v 4.4876460e-002 4.1230990e-002 1.6008250e-002
+v -7.2474010e-002 3.6255930e-002 1.5532600e-003
+v -7.1498130e-002 3.4452970e-002 4.2026500e-003
+v -2.7790900e-002 3.8062900e-002 7.9376100e-003
+v -1.6556410e-002 3.8286470e-002 1.0215790e-002
+v 8.1043500e-003 3.4842900e-002 1.8134600e-002
+v 2.3589460e-002 3.5890600e-002 2.5337690e-002
+v 4.1261350e-002 4.0585070e-002 2.0751930e-002
+v -5.1350870e-002 3.3645700e-002 8.0329400e-003
+v -4.7104300e-002 3.5549500e-002 8.0803900e-003
+v -1.4103500e-003 3.6999940e-002 1.6982030e-002
+v 9.1714000e-004 3.4803380e-002 1.5634690e-002
+v 2.8887900e-003 3.4636250e-002 1.8849770e-002
+v 1.3279200e-002 3.4379500e-002 2.1423700e-002
+v 1.4322700e-002 3.4425500e-002 2.1593200e-002
+v 1.7490100e-002 3.4646300e-002 2.2040900e-002
+v 2.9868460e-002 3.6248820e-002 1.9872200e-002
+v -3.9222000e-002 3.6326200e-002 1.0789900e-002
+v -3.0307100e-002 3.3995400e-002 1.4706400e-002
+v 2.0081230e-002 3.5172700e-002 2.8018770e-002
+v 2.4989010e-002 3.8104580e-002 2.9429570e-002
+v 3.3584130e-002 3.8303930e-002 2.2928670e-002
+v 4.9015720e-002 4.4573630e-002 2.0659450e-002
+v -5.8225970e-002 6.6607310e-002 3.5050280e-002
+v -6.7330830e-002 3.3846440e-002 8.7266300e-003
+v -3.4692330e-002 3.3828710e-002 1.2438580e-002
+v -2.9803200e-002 3.4287000e-002 1.6353100e-002
+v 1.7023800e-003 3.6310890e-002 2.1179600e-002
+v 4.5137020e-002 4.4625440e-002 2.5516510e-002
+v -6.8876490e-002 1.1022176e-001 3.9004630e-002
+v -5.7680560e-002 3.3622690e-002 1.4040310e-002
+v -5.3210500e-002 3.3585300e-002 1.3987000e-002
+v -3.5711600e-002 3.5891600e-002 1.5502900e-002
+v -2.8861500e-002 3.5396700e-002 1.7350000e-002
+v -2.6580500e-002 3.7742600e-002 1.5705300e-002
+v -1.0974400e-003 3.8147840e-002 2.0427010e-002
+v 3.5047710e-002 4.0973940e-002 2.6970390e-002
+v -6.9685460e-002 3.4478780e-002 9.7984300e-003
+v -5.4019000e-002 3.3309900e-002 1.5848000e-002
+v 4.4816800e-003 3.7117830e-002 2.4755300e-002
+v 6.6605500e-003 3.5204730e-002 2.4315930e-002
+v 8.3833000e-003 3.4748700e-002 2.4057310e-002
+v 3.8883100e-002 4.1032980e-002 2.4976570e-002
+v -2.6441900e-003 3.8727070e-002 2.5131260e-002
+v 3.2222300e-003 3.8708440e-002 2.5898750e-002
+v 9.0016500e-003 3.6890930e-002 2.8482190e-002
+v 1.3196980e-002 3.4835790e-002 3.1630980e-002
+v 2.2291600e-002 3.7053310e-002 3.3101020e-002
+v 2.8948390e-002 3.9160020e-002 2.7234810e-002
+v -8.7773470e-002 1.1181412e-001 3.7144310e-002
+v -1.7870490e-002 3.8203890e-002 2.0243220e-002
+v 1.0087420e-002 3.7047690e-002 3.0822500e-002
+v 4.2296550e-002 4.5435770e-002 2.9040920e-002
+v -8.4341340e-002 1.1388013e-001 4.6513480e-002
+v -7.3795710e-002 1.0895629e-001 3.9217250e-002
+v -5.1243340e-002 6.4239200e-002 3.4258040e-002
+v -6.1777390e-002 3.4017860e-002 1.6900580e-002
+v -3.6665100e-002 3.5304200e-002 2.3032000e-002
+v -1.4930180e-002 3.8643510e-002 2.9378330e-002
+v -8.0894520e-002 1.0967225e-001 3.7910230e-002
+v -8.9822620e-002 1.1387199e-001 3.2845310e-002
+v -6.9655510e-002 6.8728370e-002 3.1127880e-002
+v -7.8449800e-002 1.0988832e-001 4.2517920e-002
+v -7.5824140e-002 1.0794900e-001 3.7128750e-002
+v -5.5740630e-002 3.4128050e-002 2.6674360e-002
+v -3.8279600e-002 3.5429000e-002 2.4380600e-002
+v -3.5283340e-002 3.4179780e-002 2.2744860e-002
+v -2.5798070e-002 3.7865000e-002 1.9981460e-002
+v 6.9064300e-003 3.9004270e-002 2.9548510e-002
+v 1.5448990e-002 3.4852440e-002 3.6984890e-002
+v 1.9128230e-002 3.5640640e-002 3.6642280e-002
+v -6.3664970e-002 6.6047840e-002 3.1828080e-002
+v 3.9604800e-002 4.4939530e-002 2.9992360e-002
+v -8.0294310e-002 7.1702430e-002 1.5995300e-002
+v -5.4185430e-002 6.7322700e-002 3.6935610e-002
+v -7.3110210e-002 1.4847168e-001 -2.8748470e-002
+v -5.8999980e-002 7.3751550e-002 4.1197080e-002
+v -5.9520730e-002 6.1040260e-002 -2.3753800e-003
+v -6.2791800e-002 3.4596760e-002 2.3505640e-002
+v -4.1895500e-002 3.3668300e-002 2.6940000e-002
+v 8.9808200e-003 3.7639400e-002 3.3900800e-002
+v 8.5287800e-003 3.4888000e-002 3.6265100e-002
+v -8.9803890e-002 1.1498106e-001 4.2771650e-002
+v -6.5545420e-002 7.4430370e-002 3.9168070e-002
+v -6.4644190e-002 6.1723230e-002 2.2552000e-004
+v 5.2496900e-003 3.9507100e-002 3.3271200e-002
+v 2.0250320e-002 3.7033170e-002 3.9327190e-002
+v -6.7006400e-002 6.3292870e-002 -1.7493900e-003
+v -6.4479770e-002 6.0651470e-002 4.2343200e-003
+v -5.7219630e-002 5.7000470e-002 4.9175800e-003
+v -7.4362810e-002 7.2437050e-002 3.1430040e-002
+v -6.2019000e-002 3.4343180e-002 3.1883280e-002
+v -4.6870820e-002 3.4444130e-002 3.0513130e-002
+v -2.0814280e-002 3.8400960e-002 2.7868430e-002
+v 1.6439350e-002 3.5635110e-002 4.1281040e-002
+v -6.9087160e-002 1.1205014e-001 4.5320060e-002
+v -7.1811570e-002 1.4861318e-001 -3.4639490e-002
+v -6.9538770e-002 6.3074750e-002 3.5758200e-003
+v -8.4863890e-002 7.8392100e-002 1.6462010e-002
+v -9.1188780e-002 1.1588893e-001 2.4705540e-002
+v -8.8827760e-002 1.1359169e-001 2.3873640e-002
+v -7.1302830e-002 1.1325363e-001 4.9444530e-002
+v -5.4876950e-002 7.0282330e-002 3.8828200e-002
+v -7.7208880e-002 1.0715887e-001 3.4738290e-002
+v -6.1241780e-002 5.9007440e-002 8.0916600e-003
+v -6.5885650e-002 3.5025080e-002 2.9416520e-002
+v -5.7889430e-002 3.4419570e-002 3.6265760e-002
+v -5.1847710e-002 3.4470270e-002 3.4635180e-002
+v -3.4834600e-002 3.4721400e-002 3.4578200e-002
+v -3.0984700e-002 3.8191900e-002 3.2390100e-002
+v -4.9613100e-003 3.9364900e-002 3.6702200e-002
+v 1.2224170e-002 3.5177480e-002 4.2620580e-002
+v -7.4898220e-002 1.1458863e-001 5.0776480e-002
+v -8.0469100e-002 1.1357963e-001 4.6643440e-002
+v -7.4107560e-002 6.9586030e-002 2.7264400e-002
+v -7.9002620e-002 7.6339320e-002 2.9248090e-002
+v -6.5297080e-002 3.4778970e-002 3.3744340e-002
+v -3.3656400e-002 3.4344100e-002 3.6914100e-002
+v 4.9318500e-003 3.4814800e-002 4.3462110e-002
+v 1.1347440e-002 3.6213020e-002 4.4652280e-002
+v -6.0569260e-002 7.1154540e-002 3.8653760e-002
+v -8.8979470e-002 1.1450869e-001 2.8446030e-002
+v -6.8543520e-002 6.1090480e-002 1.0557760e-002
+v -8.2710960e-002 1.1648975e-001 4.8518530e-002
+v -4.1913210e-002 3.4467720e-002 3.3200040e-002
+v -1.1289800e-002 3.9529200e-002 3.8844100e-002
+v -2.8261900e-003 3.4885340e-002 4.5611410e-002
+v -6.4561210e-002 5.9484140e-002 1.3061680e-002
+v -5.8581440e-002 5.7801460e-002 1.3429540e-002
+v -2.3320000e-002 3.9169500e-002 3.8473300e-002
+v -1.8159900e-002 3.9322300e-002 3.9402900e-002
+v -1.6471400e-002 3.4812800e-002 4.3684700e-002
+v 3.2906600e-003 3.5833470e-002 4.6024610e-002
+v -8.5229630e-002 1.1200712e-001 3.0416940e-002
+v -8.5644730e-002 1.1131719e-001 3.4234780e-002
+v -7.4530360e-002 6.6680690e-002 4.6953300e-003
+v -7.1112970e-002 6.2751470e-002 8.7995500e-003
+v -6.1149380e-002 5.8834410e-002 1.6539440e-002
+v -4.6912270e-002 3.4627180e-002 3.9739710e-002
+v -4.0760350e-002 3.4668230e-002 4.0492530e-002
+v -2.6323100e-002 3.4658000e-002 4.3473500e-002
+v -3.1836600e-003 3.6229910e-002 4.7873100e-002
+v -7.9940490e-002 1.0916678e-001 3.4119800e-002
+v -5.9712170e-002 6.3165280e-002 2.8789180e-002
+v -5.1176600e-002 6.8061880e-002 3.7398330e-002
+v -5.0126580e-002 7.0933150e-002 3.9481010e-002
+v -7.2790130e-002 6.4399880e-002 1.5205950e-002
+v -6.8511230e-002 6.1214650e-002 1.5354080e-002
+v -3.9343210e-002 3.5440180e-002 4.2492560e-002
+v -8.1305900e-003 3.5008350e-002 4.7502400e-002
+v -6.6080670e-002 7.0202740e-002 3.5552860e-002
+v -6.8602600e-002 1.4992277e-001 -4.0051350e-002
+v -7.1722100e-002 6.7023040e-002 2.4959750e-002
+v -7.5115010e-002 6.6557040e-002 1.0244090e-002
+v -6.5146650e-002 3.5945650e-002 3.9775080e-002
+v -3.6898600e-002 3.5924640e-002 4.4794170e-002
+v -9.4780400e-003 3.5977600e-002 4.9434210e-002
+v -8.5175960e-002 1.1706809e-001 4.8139420e-002
+v -6.3366400e-002 6.2790260e-002 2.5647610e-002
+v -6.6633330e-002 6.1001700e-002 1.8101240e-002
+v -5.8167590e-002 5.9985190e-002 2.2606060e-002
+v -6.4212210e-002 3.4992560e-002 3.9401920e-002
+v -5.3425790e-002 3.4560020e-002 4.2782420e-002
+v -1.8031490e-002 3.4859970e-002 4.9264760e-002
+v -1.1440410e-002 3.7640770e-002 5.0275730e-002
+v -7.5165320e-002 1.1154286e-001 4.6707180e-002
+v -7.7168390e-002 6.9826450e-002 5.0605600e-003
+v -7.2801360e-002 6.4382590e-002 1.2089080e-002
+v -7.8022000e-002 7.0995160e-002 2.1322150e-002
+v -6.1263370e-002 3.4690410e-002 4.1994900e-002
+v -5.4403750e-002 3.5007310e-002 4.4874590e-002
+v -4.5754280e-002 3.5206980e-002 4.3518120e-002
+v -3.3832440e-002 3.5168820e-002 4.6957890e-002
+v -2.8657630e-002 3.5083380e-002 5.0549440e-002
+v -1.5306440e-002 3.5246410e-002 5.0133810e-002
+v -6.5283650e-002 1.5592447e-001 -4.9865930e-002
+v -6.6467860e-002 1.4871539e-001 -3.1579300e-002
+v -6.2095980e-002 1.6388324e-001 -5.8385930e-002
+v -6.3274890e-002 1.5245731e-001 -3.2221730e-002
+v -4.3755720e-002 1.4773408e-001 -2.1433200e-003
+v -6.5696940e-002 1.4561631e-001 -1.8974710e-002
+v -6.6713650e-002 1.5358824e-001 -4.9097100e-002
+v -1.0482810e-002 1.6668287e-001 -2.1746090e-002
+v -6.2744510e-002 1.6397531e-001 -5.9398280e-002
+v -7.0413230e-002 1.4129200e-001 -8.4590800e-003
+v -6.1530380e-002 1.4037628e-001 -6.2734700e-003
+v -1.1452460e-002 1.7220633e-001 -2.6844980e-002
+v -6.3731140e-002 1.6577037e-001 -6.0103610e-002
+v -2.8218820e-002 1.5758144e-001 -1.0999490e-002
+v -1.8471270e-002 1.5967716e-001 -1.1169510e-002
+v -6.6700710e-002 1.5236775e-001 -4.5266390e-002
+v -4.9896410e-002 1.4670859e-001 -1.8614200e-003
+v -3.1449640e-002 1.5460463e-001 -7.6802300e-003
+v -6.7447660e-002 1.5507675e-001 -5.1594250e-002
+v -1.0906650e-002 1.7649301e-001 -2.9246300e-002
+v -7.2083600e-002 1.4965550e-001 -3.9265860e-002
+v -6.4230830e-002 1.4877806e-001 -2.5899710e-002
+v -6.3056640e-002 1.4341650e-001 -7.4907700e-003
+v -5.3043350e-002 1.4092550e-001 -4.7408000e-004
+v -3.9269410e-002 1.5205232e-001 -6.6203800e-003
+v -6.4796930e-002 1.5210615e-001 -3.6185520e-002
+v -6.4400320e-002 1.5834400e-001 -5.4256370e-002
+v -6.6178120e-002 1.4218350e-001 -9.3766300e-003
+v -6.7751430e-002 1.4605207e-001 -2.3333300e-002
+v -6.4731580e-002 1.5410067e-001 -4.0464820e-002
+v -2.4265590e-002 1.5687690e-001 -7.8509300e-003
+v -1.5723180e-002 1.6312344e-001 -1.6396570e-002
+v -7.0887660e-002 1.4404618e-001 -1.4908480e-002
+v -4.4341830e-002 1.5113809e-001 -5.6859800e-003
+v -6.2896810e-002 1.4694778e-001 -1.3098620e-002
+v -6.3755400e-002 1.4428875e-001 -1.1395730e-002
+v -6.8214560e-002 1.4390932e-001 -1.4984170e-002
+v -5.0271440e-002 1.4336563e-001 1.5153000e-003
+v -2.8535590e-002 1.6208479e-001 -1.4786030e-002
+v -6.5810700e-002 1.4359119e-001 -1.2585380e-002
+v -5.6179200e-002 1.3774406e-001 -4.0674300e-003
+v -6.8866880e-002 1.4723338e-001 -2.8739870e-002
+v -6.0965420e-002 1.7002113e-001 -6.0839390e-002
+v -1.3895490e-002 1.6787168e-001 -2.1897230e-002
+v -6.9413000e-002 1.5121847e-001 -4.4538540e-002
+v -5.5039800e-002 5.7309700e-002 1.6990900e-002
+f 1069 1647 1578
+f 1058 909 939
+f 421 1176 238
+f 1055 1101 1042
+f 238 1059 1126
+f 1254 30 1261
+f 1065 1071 1
+f 1037 1130 1120
+f 1570 2381 1585
+f 2434 2502 2473
+f 1632 1654 1646
+f 1144 1166 669
+f 1202 1440 305
+f 1071 1090 1
+f 1555 1570 1584
+f 1184 1174 404
+f 65 432 12
+f 1032 1085 574
+f 1789 2207 2223
+f 1154 1118 1184
+f 1141 1086 1154
+f 99 1117 342
+f 404 1174 419
+f 489 2000 1998
+f 1118 1174 1184
+f 1196 403 136
+f 1495 717 1490
+f 1804 402 1207
+f 2272 1398 891
+f 1100 1002 804
+f 1596 1595 2381
+f 208 420 1207
+f 402 208 1207
+f 1455 1935 1925
+f 1176 1059 238
+f 1150 1040 348
+f 1957 1537 2051
+f 1124 1189 939
+f 1804 1207 1823
+f 1381 1300 1109
+f 383 384 1182
+f 1085 1086 1141
+f 1040 1046 132
+f 220 1495 1188
+f 420 261 1207
+f 261 420 1065
+f 1055 1133 1101
+f 1054 421 403
+f 182 1109 2
+f 1181 1207 320
+f 545 1570 1561
+f 35 342 432
+f 1024 574 1141
+f 432 342 12
+f 1489 1081 1547
+f 1181 320 1805
+f 1516 1683 1507
+f 357 1117 1047
+f 1561 1570 1555
+f 1090 1196 1206
+f 1047 1203 1051
+f 1165 202 1121
+f 1099 341 301
+f 1174 240 419
+f 922 921 833
+f 1121 1080 385
+f 815 21 1183
+f 35 99 342
+f 1083 398 262
+f 106 94 1317
+f 94 292 1317
+f 292 95 1317
+f 940 1039 1033
+f 1300 1306 433
+f 21 212 471
+f 1120 1131 1037
+f 833 921 688
+f 1117 357 342
+f 106 271 94
+f 386 227 1375
+f 1130 1044 1053
+f 419 240 219
+f 1255 1244 32
+f 1557 1081 1489
+f 2062 2120 2109
+f 2034 2110 430
+f 23 315 1111
+f 291 94 271
+f 291 292 94
+f 50 386 95
+f 964 734 665
+f 1616 1585 1611
+f 445 1084 402
+f 574 1085 1141
+f 1654 341 1653
+f 220 1188 1640
+f 342 69 12
+f 417 261 328
+f 292 50 95
+f 204 227 386
+f 50 204 386
+f 1276 1471 1311
+f 1206 1196 136
+f 1033 1055 1042
+f 1037 1044 1130
+f 1180 320 417
+f 1121 202 1080
+f 325 203 271
+f 291 76 292
+f 292 237 50
+f 2159 1696 1767
+f 583 929 850
+f 1584 1585 1616
+f 1495 1490 1188
+f 1557 1489 1660
+f 1078 1069 1494
+f 1972 1992 1971
+f 183 1226 2000
+f 325 429 203
+f 292 76 237
+f 1152 227 1143
+f 1488 1412 1489
+f 1638 1646 1653
+f 1947 1869 2468
+f 203 306 291
+f 306 76 291
+f 237 248 50
+f 204 1143 227
+f 2395 14 429
+f 1502 881 2500
+f 1 1090 202
+f 1652 1653 1099
+f 2117 1863 2496
+f 50 248 204
+f 160 792 994
+f 884 888 857
+f 544 2117 2496
+f 1090 1206 202
+f 2463 879 2492
+f 429 306 203
+f 498 188 418
+f 865 884 857
+f 994 998 1014
+f 884 897 888
+f 1795 948 1802
+f 208 1035 1071
+f 1065 1 1066
+f 377 435 1377
+f 304 429 14
+f 304 306 429
+f 73 60 74
+f 248 592 204
+f 846 2264 829
+f 897 912 906
+f 1004 991 992
+f 1422 1421 1233
+f 980 10 303
+f 1058 922 909
+f 2436 2449 2418
+f 394 435 377
+f 435 475 446
+f 475 474 446
+f 336 337 361
+f 338 235 372
+f 624 148 129
+f 812 306 596
+f 1726 992 1019
+f 945 1514 1511
+f 1069 1627 1628
+f 1812 1823 1181
+f 1165 1121 169
+f 447 475 435
+f 2487 2458 901
+f 42 59 46
+f 401 7 187
+f 1010 970 797
+f 1513 220 1640
+f 2474 2491 2462
+f 594 307 1014
+f 398 1513 1640
+f 307 594 1026
+f 545 2381 1570
+f 403 421 238
+f 445 402 127
+f 1611 1631 1616
+f 1805 1180 1148
+f 394 447 435
+f 2341 2413 2376
+f 75 74 60
+f 541 47 42
+f 47 59 42
+f 541 42 28
+f 917 931 1103
+f 897 906 883
+f 2484 2068 779
+f 888 883 857
+f 261 1065 328
+f 363 1307 349
+f 377 363 394
+f 444 747 464
+f 323 338 362
+f 92 116 74
+f 592 634 97
+f 982 1027 1004
+f 1020 982 1004
+f 1084 1054 1035
+f 208 402 1084
+f 421 1119 1176
+f 1207 1181 1823
+f 1179 1187 1160
+f 263 296 1343
+f 1298 296 1307
+f 1307 296 349
+f 405 363 349
+f 405 394 363
+f 405 447 394
+f 362 372 384
+f 338 372 362
+f 983 1004 987
+f 122 134 139
+f 415 440 414
+f 75 92 74
+f 226 186 246
+f 796 787 700
+f 1119 1059 1176
+f 122 114 91
+f 624 129 116
+f 641 558 631
+f 1311 1318 1487
+f 100 1162 1170
+f 1653 341 1099
+f 1316 1983 273
+f 263 277 296
+f 296 358 349
+f 436 447 405
+f 109 554 570
+f 504 1385 2501
+f 115 122 91
+f 2068 2460 779
+f 43 777 163
+f 378 405 349
+f 358 378 349
+f 448 447 436
+f 448 476 447
+f 78 77 108
+f 75 60 47
+f 1764 2481 1795
+f 717 714 1512
+f 1490 717 1501
+f 238 1126 168
+f 1878 1866 826
+f 2025 2360 2367
+f 251 278 263
+f 278 277 263
+f 277 318 296
+f 296 318 358
+f 318 350 358
+f 378 436 405
+f 384 372 1182
+f 454 440 415
+f 987 1004 992
+f 493 476 448
+f 323 788 338
+f 403 238 136
+f 1565 1503 1474
+f 297 277 278
+f 297 318 277
+f 358 350 378
+f 378 388 436
+f 476 493 500
+f 73 105 60
+f 323 337 312
+f 953 1573 2358
+f 142 161 119
+f 454 443 440
+f 1862 1871 1405
+f 297 319 318
+f 560 47 541
+f 170 1323 111
+f 357 1047 1050
+f 1119 98 1059
+f 1838 1877 1900
+f 2359 230 251
+f 350 364 378
+f 449 448 436
+f 449 493 448
+f 185 186 226
+f 443 469 479
+f 874 165 2480
+f 463 444 464
+f 64 105 91
+f 1182 440 1129
+f 1958 1651 2502
+f 1238 2034 191
+f 251 279 278
+f 278 279 297
+f 364 388 378
+f 483 493 449
+f 134 148 139
+f 244 268 259
+f 910 942 930
+f 105 115 91
+f 24 30 18
+f 1132 487 1059
+f 1869 1947 2021
+f 2497 2494 2463
+f 2359 2385 230
+f 230 280 251
+f 251 280 279
+f 279 308 297
+f 297 308 319
+f 319 364 318
+f 364 350 318
+f 388 395 436
+f 436 395 449
+f 493 472 500
+f 122 129 134
+f 125 142 124
+f 373 400 393
+f 24 557 30
+f 2264 2278 2251
+f 1261 30 1269
+f 1730 1862 1877
+f 252 280 230
+f 343 364 319
+f 364 343 388
+f 63 64 91
+f 399 393 416
+f 416 444 463
+f 162 189 142
+f 768 373 326
+f 189 661 177
+f 189 199 661
+f 847 887 864
+f 533 747 444
+f 1744 1022 1418
+f 1170 524 729
+f 121 1342 128
+f 1236 1244 26
+f 280 281 279
+f 281 308 279
+f 343 319 308
+f 343 365 388
+f 388 365 395
+f 365 406 395
+f 406 449 395
+f 483 477 493
+f 477 491 472
+f 493 477 472
+f 78 109 77
+f 166 174 196
+f 481 150 814
+f 63 59 64
+f 326 373 393
+f 643 260 43
+f 230 253 252
+f 449 441 483
+f 441 477 483
+f 415 416 463
+f 226 246 245
+f 464 470 454
+f 323 362 337
+f 52 37 1283
+f 253 281 252
+f 281 280 252
+f 309 308 281
+f 330 343 308
+f 366 365 343
+f 441 449 406
+f 464 814 15
+f 883 906 887
+f 337 362 371
+f 479 498 290
+f 247 746 1003
+f 25 37 557
+f 640 930 669
+f 2486 2499 2459
+f 309 330 308
+f 343 330 366
+f 441 437 477
+f 290 498 418
+f 124 119 108
+f 77 124 108
+f 589 125 109
+f 570 589 109
+f 125 162 142
+f 1045 433 1034
+f 1207 261 320
+f 2004 2474 2495
+f 1215 1228 2285
+f 365 396 406
+f 396 422 406
+f 422 437 441
+f 406 422 441
+f 59 47 60
+f 51 78 66
+f 361 371 383
+f 196 215 214
+f 463 454 415
+f 27 41 535
+f 53 1283 37
+f 84 1299 1283
+f 1805 320 1180
+f 254 253 222
+f 254 281 253
+f 309 366 330
+f 396 365 366
+f 456 477 437
+f 484 491 477
+f 2480 2485 2493
+f 418 188 187
+f 53 85 1283
+f 85 84 1283
+f 420 1071 1065
+f 264 281 254
+f 298 309 281
+f 368 366 367
+f 368 396 366
+f 1639 1564 1139
+f 560 48 47
+f 82 471 212
+f 25 38 37
+f 202 1206 1080
+f 264 298 281
+f 298 331 309
+f 309 331 366
+f 331 367 366
+f 396 368 422
+f 422 456 437
+f 491 1192 313
+f 1699 2064 1710
+f 462 443 479
+f 371 362 384
+f 2502 2476 2464
+f 371 384 383
+f 21 732 212
+f 1571 1629 1627
+f 38 39 53
+f 37 38 53
+f 39 85 53
+f 1173 1184 404
+f 1006 2142 1674
+f 201 255 254
+f 255 264 254
+f 368 407 422
+f 450 456 422
+f 450 484 456
+f 456 484 477
+f 314 1192 491
+f 2027 2501 2489
+f 2475 2471 2488
+f 551 492 732
+f 464 481 814
+f 1081 1494 1547
+f 201 231 255
+f 407 450 422
+f 484 494 491
+f 494 327 491
+f 327 314 491
+f 876 797 995
+f 847 856 829
+f 125 143 162
+f 134 129 148
+f 1564 1571 1627
+f 417 320 261
+f 328 1065 1066
+f 170 156 201
+f 156 231 201
+f 231 282 255
+f 282 264 255
+f 450 485 484
+f 484 485 494
+f 2463 2486 2479
+f 159 185 167
+f 492 68 212
+f 732 492 212
+f 68 82 212
+f 1311 1471 1296
+f 101 156 111
+f 332 264 282
+f 332 298 264
+f 332 331 298
+f 331 332 367
+f 407 423 450
+f 450 423 485
+f 804 1002 1443
+f 2484 779 946
+f 689 443 462
+f 440 689 1129
+f 166 167 174
+f 38 31 39
+f 112 145 101
+f 101 145 156
+f 156 256 231
+f 332 423 368
+f 367 332 368
+f 368 423 407
+f 946 779 920
+f 1432 1261 1449
+f 461 478 453
+f 464 15 470
+f 31 54 39
+f 39 54 85
+f 86 101 85
+f 145 210 156
+f 282 283 332
+f 283 369 332
+f 369 423 332
+f 423 408 485
+f 854 876 965
+f 78 108 66
+f 440 443 689
+f 374 2465 961
+f 929 519 979
+f 54 86 85
+f 156 241 256
+f 256 282 231
+f 256 283 282
+f 389 423 369
+f 389 408 423
+f 408 457 485
+f 457 49 485
+f 485 49 494
+f 494 135 327
+f 175 83 314
+f 1167 1140 1483
+f 196 174 215
+f 697 16 68
+f 1038 82 16
+f 140 117 141
+f 1654 1653 1646
+f 1234 54 31
+f 86 112 101
+f 210 241 156
+f 923 917 911
+f 697 34 16
+f 145 193 210
+f 256 265 283
+f 265 310 283
+f 283 310 369
+f 310 344 369
+f 344 370 369
+f 370 389 369
+f 409 408 389
+f 409 466 408
+f 466 457 408
+f 466 49 457
+f 49 135 494
+f 174 225 215
+f 1014 766 602
+f 826 2220 2215
+f 1078 1494 1081
+f 1273 70 86
+f 120 112 86
+f 146 145 112
+f 146 193 145
+f 265 256 241
+f 223 265 241
+f 486 49 466
+f 175 327 135
+f 105 122 115
+f 480 15 681
+f 225 234 215
+f 731 34 697
+f 86 54 1273
+f 70 120 86
+f 193 241 210
+f 299 310 265
+f 310 333 344
+f 344 351 370
+f 424 466 409
+f 135 49 175
+f 214 215 234
+f 48 75 47
+f 34 9 1038
+f 16 34 1038
+f 203 291 271
+f 9 558 754
+f 1195 397 1120
+f 120 146 112
+f 146 194 193
+f 266 265 223
+f 266 299 265
+f 299 333 310
+f 333 351 344
+f 382 383 392
+f 399 416 415
+f 266 333 299
+f 351 352 370
+f 424 486 466
+f 487 175 49
+f 7 117 187
+f 1182 414 440
+f 41 42 46
+f 290 289 497
+f 2502 2464 2473
+f 372 399 414
+f 1570 1585 1584
+f 1066 1 1165
+f 1 202 1165
+f 120 70 102
+f 157 146 120
+f 194 223 193
+f 223 241 193
+f 352 379 370
+f 370 379 389
+f 410 409 389
+f 2478 1409 1958
+f 806 945 1002
+f 157 194 146
+f 267 266 223
+f 267 333 266
+f 379 410 389
+f 410 438 409
+f 438 424 409
+f 190 205 143
+f 337 371 361
+f 2215 830 826
+f 1631 1646 1638
+f 102 157 120
+f 157 195 194
+f 195 223 194
+f 195 211 223
+f 223 211 267
+f 267 300 333
+f 300 334 351
+f 333 300 351
+f 351 334 352
+f 410 411 438
+f 438 486 424
+f 487 49 486
+f 875 594 989
+f 108 581 66
+f 225 245 244
+f 312 336 335
+f 151 754 107
+f 274 1386 300
+f 352 334 379
+f 923 1729 1096
+f 244 245 268
+f 463 464 454
+f 414 399 415
+f 15 480 470
+f 1647 1069 1078
+f 909 922 833
+f 387 417 328
+f 133 157 102
+f 1314 133 102
+f 133 195 157
+f 1148 1179 1160
+f 1046 1167 182
+f 379 411 410
+f 792 339 229
+f 391 7 668
+f 185 226 174
+f 461 290 497
+f 2027 504 2501
+f 1196 1054 403
+f 728 1019 752
+f 2459 2483 2461
+f 1291 1264 55
+f 133 1356 195
+f 195 1356 211
+f 412 438 411
+f 4 486 438
+f 458 4 438
+f 4 487 486
+f 1720 1572 1771
+f 245 275 268
+f 1869 2021 2059
+f 235 399 372
+f 64 60 105
+f 836 2492 879
+f 1315 133 1314
+f 1331 1382 1356
+f 1310 926 1128
+f 7 1121 117
+f 119 161 611
+f 380 379 334
+f 379 380 411
+f 467 4 458
+f 495 487 4
+f 495 1126 487
+f 416 400 533
+f 479 469 498
+f 74 116 73
+f 478 461 497
+f 393 400 416
+f 61 1291 55
+f 505 1999 2474
+f 1999 2491 2474
+f 199 189 36
+f 1164 1165 169
+f 1179 387 249
+f 390 411 380
+f 411 390 412
+f 458 438 412
+f 495 168 1126
+f 480 469 470
+f 116 122 105
+f 418 187 140
+f 185 174 167
+f 166 148 167
+f 470 469 443
+f 40 55 32
+f 61 71 1291
+f 71 103 1291
+f 1184 1173 1154
+f 634 514 97
+f 425 458 412
+f 917 923 931
+f 2472 2489 853
+f 754 641 567
+f 44 567 1163
+f 454 470 443
+f 40 32 1249
+f 33 40 1249
+f 56 55 40
+f 56 61 55
+f 451 1265 439
+f 1180 417 1179
+f 1099 301 1077
+f 1189 1058 939
+f 1059 221 1132
+f 598 1074 1075
+f 412 426 425
+f 650 186 185
+f 234 244 259
+f 226 245 225
+f 1033 1042 1030
+f 2492 836 247
+f 7 169 1121
+f 1462 1322 1482
+f 425 467 458
+f 496 4 467
+f 1751 2468 2480
+f 290 418 140
+f 326 789 762
+f 142 177 161
+f 165 1751 2480
+f 87 103 71
+f 103 87 104
+f 1180 1179 1148
+f 417 387 1179
+f 2081 2060 2031
+f 1154 1173 1141
+f 181 131 197
+f 442 425 426
+f 614 144 143
+f 876 1010 797
+f 40 45 56
+f 56 45 61
+f 87 71 61
+f 1563 1437 1590
+f 1121 385 117
+f 1148 1160 1137
+f 1449 1459 1439
+f 1028 2462 929
+f 442 459 425
+f 459 467 425
+f 168 495 4
+f 496 168 4
+f 1763 1403 1444
+f 140 187 117
+f 244 234 225
+f 246 740 269
+f 372 414 1182
+f 40 547 45
+f 45 62 61
+f 62 87 61
+f 87 88 104
+f 1084 517 1054
+f 387 328 1064
+f 2467 2497 2485
+f 286 1363 302
+f 205 189 162
+f 290 140 289
+f 214 234 224
+f 393 399 809
+f 315 1131 397
+f 302 321 353
+f 1164 169 391
+f 427 459 442
+f 217 496 467
+f 217 168 496
+f 978 969 2074
+f 361 383 382
+f 269 276 245
+f 1440 11 305
+f 62 88 87
+f 328 1066 1064
+f 1066 1165 1164
+f 242 287 302
+f 1363 242 302
+f 287 321 302
+f 1179 249 1187
+f 983 1020 1004
+f 464 747 481
+f 788 323 276
+f 269 245 246
+f 88 89 1325
+f 171 172 242
+f 360 353 321
+f 360 1354 353
+f 1057 1064 1164
+f 2184 2188 2183
+f 460 459 451
+f 460 467 459
+f 149 168 217
+f 149 136 168
+f 116 129 122
+f 109 124 77
+f 159 167 148
+f 28 42 41
+f 57 88 62
+f 45 57 62
+f 1336 1325 89
+f 89 72 1336
+f 147 172 171
+f 172 258 242
+f 258 257 242
+f 257 287 242
+f 257 321 287
+f 345 360 321
+f 360 381 1354
+f 1069 938 1655
+f 387 473 249
+f 270 217 467
+f 130 136 149
+f 851 847 829
+f 983 987 975
+f 189 177 142
+f 88 72 89
+f 184 258 172
+f 257 288 321
+f 1265 451 459
+f 270 149 217
+f 226 225 174
+f 27 28 41
+f 109 125 124
+f 547 57 45
+f 57 58 88
+f 88 58 72
+f 2476 2484 2458
+f 147 184 172
+f 184 213 258
+f 258 243 257
+f 243 288 257
+f 345 321 288
+f 391 169 7
+f 468 460 451
+f 468 488 460
+f 270 467 460
+f 488 270 460
+f 1206 136 130
+f 481 793 150
+f 143 205 162
+f 142 119 124
+f 58 90 72
+f 90 128 72
+f 147 173 184
+f 173 213 184
+f 213 233 258
+f 258 233 243
+f 354 360 345
+f 354 381 360
+f 1026 991 307
+f 268 312 259
+f 1206 130 1080
+f 116 105 73
+f 139 148 166
+f 275 312 268
+f 188 401 187
+f 2479 2459 2461
+f 58 63 90
+f 1064 1066 1164
+f 1064 473 387
+f 288 311 345
+f 311 354 345
+f 996 994 307
+f 452 468 439
+f 452 478 468
+f 478 488 468
+f 141 130 149
+f 1564 1639 1563
+f 547 41 57
+f 2081 2107 2060
+f 382 381 354
+f 497 270 488
+f 289 149 270
+f 289 141 149
+f 114 122 139
+f 59 60 64
+f 275 323 312
+f 401 668 7
+f 41 46 57
+f 57 46 58
+f 1459 1345 1269
+f 1342 121 158
+f 166 173 158
+f 213 224 233
+f 233 259 243
+f 243 322 288
+f 322 311 288
+f 453 478 452
+f 497 289 270
+f 912 911 906
+f 276 323 275
+f 276 275 245
+f 46 63 58
+f 90 121 128
+f 173 214 213
+f 213 214 224
+f 259 322 243
+f 336 311 322
+f 336 354 311
+f 361 382 354
+f 1043 439 1290
+f 497 488 478
+f 385 130 141
+f 385 1080 130
+f 144 190 143
+f 535 41 547
+f 121 166 158
+f 335 336 322
+f 354 336 361
+f 2004 2481 1764
+f 698 439 1043
+f 289 140 141
+f 923 1096 931
+f 650 185 159
+f 46 59 63
+f 63 91 90
+f 90 114 121
+f 121 139 166
+f 173 196 214
+f 259 335 322
+f 2478 2502 2434
+f 312 337 336
+f 90 91 114
+f 114 139 121
+f 166 196 173
+f 224 234 233
+f 234 259 233
+f 259 312 335
+f 1124 916 1189
+f 542 541 530
+f 462 479 290
+f 269 783 276
+f 813 567 641
+f 276 783 788
+f 82 1038 1333
+f 816 701 703
+f 672 137 603
+f 625 635 624
+f 2457 2439 1973
+f 767 533 529
+f 2468 1869 2480
+f 662 190 639
+f 711 720 719
+f 630 639 614
+f 161 654 638
+f 781 991 982
+f 1227 31 516
+f 648 639 630
+f 630 614 590
+f 2098 544 1899
+f 578 579 586
+f 697 492 551
+f 529 533 400
+f 869 859 870
+f 1732 924 914
+f 1004 1027 991
+f 801 591 603
+f 636 676 651
+f 876 949 965
+f 2207 1789 1859
+f 76 739 237
+f 188 681 15
+f 578 604 599
+f 797 616 995
+f 510 2035 1365
+f 76 812 617
+f 617 739 76
+f 1468 93 1765
+f 596 546 812
+f 1457 1305 1477
+f 760 197 150
+f 671 773 765
+f 586 609 604
+f 591 700 632
+f 476 2312 474
+f 2084 2027 2489
+f 582 590 571
+f 1555 2449 1996
+f 674 546 596
+f 812 655 617
+f 161 177 661
+f 599 604 636
+f 700 787 576
+f 776 675 572
+f 776 674 675
+f 617 634 739
+f 591 632 649
+f 612 546 674
+f 617 655 634
+f 728 752 706
+f 571 2311 2305
+f 775 674 776
+f 775 612 674
+f 612 628 546
+f 546 628 812
+f 812 628 655
+f 620 630 615
+f 620 648 630
+f 667 653 646
+f 810 782 785
+f 150 197 814
+f 534 1517 2000
+f 702 572 2378
+f 748 776 572
+f 655 613 634
+f 911 917 905
+f 648 679 662
+f 727 771 713
+f 750 807 799
+f 639 190 144
+f 662 679 200
+f 702 748 572
+f 775 776 748
+f 628 718 655
+f 626 658 645
+f 791 778 790
+f 612 811 628
+f 613 514 634
+f 1380 1756 1673
+f 570 590 614
+f 720 741 719
+f 1074 795 835
+f 614 639 144
+f 612 775 811
+f 718 735 655
+f 655 735 613
+f 798 338 788
+f 636 652 676
+f 571 590 555
+f 528 730 687
+f 690 702 2312
+f 476 690 2312
+f 811 718 628
+f 721 778 727
+f 748 702 690
+f 735 686 613
+f 1517 2002 2127
+f 654 685 667
+f 569 588 606
+f 513 531 538
+f 538 549 548
+f 549 553 548
+f 550 588 549
+f 1903 869 870
+f 691 775 748
+f 691 600 775
+f 600 811 775
+f 811 563 718
+f 563 736 718
+f 718 736 735
+f 736 647 735
+f 735 647 686
+f 686 745 613
+f 745 514 613
+f 569 606 605
+f 654 667 638
+f 851 857 847
+f 588 569 549
+f 690 691 748
+f 680 514 745
+f 2127 2002 2094
+f 747 701 481
+f 400 373 529
+f 600 536 811
+f 536 563 811
+f 1306 227 1152
+f 522 24 18
+f 523 24 522
+f 865 857 851
+f 2031 2060 1540
+f 767 701 747
+f 618 652 609
+f 652 636 609
+f 573 22 710
+f 642 699 730
+f 1522 1518 2476
+f 500 629 691
+f 690 500 691
+f 691 629 600
+f 780 644 641
+f 579 578 561
+f 131 668 197
+f 197 668 814
+f 789 809 798
+f 622 760 150
+f 621 563 536
+f 673 745 686
+f 673 818 745
+f 818 680 745
+f 680 96 514
+f 2495 2462 1028
+f 1028 583 575
+f 663 794 664
+f 629 761 600
+f 761 757 600
+f 600 757 536
+f 621 696 563
+f 755 736 563
+f 696 755 563
+f 633 736 755
+f 633 647 736
+f 623 686 647
+f 633 623 647
+f 686 623 673
+f 819 680 818
+f 680 819 96
+f 1729 1677 1096
+f 2482 1899 2471
+f 537 536 757
+f 536 537 621
+f 673 819 818
+f 2428 222 230
+f 25 24 523
+f 25 557 24
+f 38 25 19
+f 710 22 272
+f 663 759 794
+f 1120 878 1195
+f 537 696 621
+f 696 633 755
+f 822 2215 2220
+f 97 96 1053
+f 750 784 743
+f 887 905 864
+f 768 784 373
+f 512 513 548
+f 573 664 22
+f 696 715 633
+f 673 521 819
+f 2454 2453 2445
+f 883 887 847
+f 306 812 76
+f 642 528 759
+f 798 809 235
+f 994 792 998
+f 587 626 586
+f 1900 1918 1937
+f 645 652 618
+f 537 786 696
+f 521 593 819
+f 515 19 523
+f 741 749 719
+f 789 326 809
+f 539 581 550
+f 657 777 723
+f 684 713 660
+f 692 712 720
+f 652 666 692
+f 507 761 629
+f 472 507 629
+f 507 757 761
+f 623 633 673
+f 724 521 673
+f 515 516 19
+f 304 675 674
+f 178 778 721
+f 947 1447 2358
+f 626 645 618
+f 586 626 618
+f 784 768 742
+f 753 537 757
+f 537 753 786
+f 724 981 521
+f 521 981 593
+f 979 559 850
+f 637 660 677
+f 787 631 576
+f 141 117 385
+f 809 399 235
+f 641 754 558
+f 542 553 561
+f 742 768 762
+f 444 416 533
+f 528 687 796
+f 813 598 566
+f 1490 1501 1557
+f 753 757 507
+f 786 715 696
+f 633 724 673
+f 2090 2062 2109
+f 646 653 660
+f 660 694 683
+f 677 660 683
+f 1872 839 838
+f 1224 18 30
+f 326 393 809
+f 799 529 373
+f 313 507 472
+f 715 774 633
+f 974 699 841
+f 703 820 816
+f 692 711 676
+f 1014 355 766
+f 875 752 1019
+f 627 646 660
+f 711 692 720
+f 652 692 676
+f 799 373 784
+f 813 566 567
+f 2462 2482 2475
+f 764 644 780
+f 1479 1924 1916
+f 753 738 786
+f 738 607 786
+f 786 607 715
+f 715 524 774
+f 633 774 724
+f 559 979 672
+f 758 798 783
+f 683 694 705
+f 820 703 562
+f 764 687 644
+f 744 743 725
+f 313 753 507
+f 607 524 715
+f 664 801 22
+f 646 627 610
+f 800 820 562
+f 750 769 807
+f 767 747 533
+f 578 586 604
+f 862 593 981
+f 688 2382 1083
+f 306 304 674
+f 738 584 607
+f 168 136 238
+f 773 552 765
+f 2473 2464 2458
+f 773 793 552
+f 626 619 658
+f 1007 1139 1013
+f 562 529 799
+f 744 750 743
+f 659 683 693
+f 677 683 659
+f 313 737 753
+f 753 737 738
+f 607 729 524
+f 27 518 28
+f 553 569 580
+f 657 163 777
+f 580 569 605
+f 789 798 758
+f 769 562 807
+f 820 671 816
+f 638 646 611
+f 1074 598 644
+f 750 799 784
+f 1931 907 898
+f 2483 2487 2461
+f 737 584 738
+f 1439 1438 1431
+f 2098 1213 544
+f 48 578 75
+f 796 631 787
+f 815 732 21
+f 581 588 550
+f 625 636 651
+f 778 1011 810
+f 693 705 725
+f 693 683 705
+f 236 1921 1966
+f 584 729 607
+f 2237 1866 2227
+f 530 541 28
+f 237 739 248
+f 512 530 28
+f 727 778 771
+f 684 727 713
+f 2237 2220 826
+f 542 561 560
+f 528 796 700
+f 808 785 671
+f 739 592 248
+f 895 905 896
+f 740 246 186
+f 272 137 979
+f 770 769 744
+f 712 742 720
+f 1213 2026 544
+f 1888 1235 2438
+f 555 554 2311
+f 737 313 1192
+f 1585 1612 1611
+f 695 721 685
+f 518 17 28
+f 769 770 562
+f 719 749 740
+f 648 669 679
+f 773 657 723
+f 606 637 619
+f 2072 2062 2042
+f 606 619 626
+f 549 569 553
+f 161 638 611
+f 910 917 942
+f 917 1103 942
+f 991 1026 992
+f 979 137 672
+f 785 163 657
+f 710 2488 2472
+f 611 581 119
+f 808 671 820
+f 1820 1900 1870
+f 759 700 591
+f 637 677 619
+f 2494 2490 2463
+f 671 765 816
+f 687 764 780
+f 1019 992 1026
+f 1726 1719 987
+f 713 771 694
+f 51 2355 78
+f 510 526 525
+f 525 526 1249
+f 526 33 1249
+f 2311 554 2335
+f 827 848 840
+f 603 591 649
+f 758 269 740
+f 1595 1612 1586
+f 1694 1048 1699
+f 682 740 186
+f 22 801 603
+f 555 570 554
+f 1053 110 97
+f 615 582 601
+f 814 668 188
+f 725 705 744
+f 528 700 759
+f 640 648 620
+f 703 701 562
+f 886 892 582
+f 631 731 576
+f 1087 1835 1747
+f 882 864 895
+f 956 950 1103
+f 1502 2500 2470
+f 205 190 200
+f 815 878 616
+f 616 878 995
+f 1183 878 815
+f 1601 1827 881
+f 527 535 526
+f 2184 2183 2175
+f 1142 1125 1133
+f 235 338 798
+f 160 339 792
+f 599 92 75
+f 598 1116 566
+f 631 558 731
+f 771 770 744
+f 730 528 642
+f 841 699 642
+f 668 401 188
+f 510 527 526
+f 749 758 740
+f 706 721 695
+f 694 726 705
+f 694 744 726
+f 906 911 905
+f 661 695 161
+f 708 815 616
+f 535 547 33
+f 794 759 591
+f 778 808 790
+f 269 758 783
+f 771 744 694
+f 800 808 820
+f 571 886 582
+f 854 948 1010
+f 906 905 887
+f 625 651 635
+f 2000 1226 534
+f 2140 1504 2016
+f 601 620 615
+f 620 601 640
+f 648 640 669
+f 698 452 439
+f 671 785 657
+f 1561 2356 545
+f 685 653 667
+f 685 727 684
+f 568 616 797
+f 708 732 815
+f 93 229 339
+f 865 851 839
+f 942 1103 950
+f 589 614 125
+f 606 610 627
+f 951 834 873
+f 92 599 625
+f 1878 830 1902
+f 2482 2098 1899
+f 568 708 616
+f 708 551 732
+f 2434 2487 2483
+f 160 964 665
+f 2316 2391 2309
+f 762 758 749
+f 570 614 589
+f 888 897 883
+f 2000 1517 1388
+f 685 721 727
+f 588 610 606
+f 653 685 684
+f 651 650 635
+f 760 1151 6
+f 793 622 150
+f 651 676 650
+f 744 769 750
+f 541 542 560
+f 476 500 690
+f 473 1064 1057
+f 561 578 560
+f 636 625 599
+f 876 995 949
+f 829 856 846
+f 682 704 740
+f 791 790 770
+f 2466 2500 2460
+f 579 587 586
+f 1352 1208 1095
+f 1684 1479 1916
+f 604 609 636
+f 751 721 706
+f 810 608 782
+f 672 603 649
+f 475 447 476
+f 794 591 801
+f 682 186 650
+f 808 800 790
+f 644 598 813
+f 704 719 740
+f 1011 608 810
+f 1192 584 737
+f 687 780 796
+f 2337 474 2312
+f 638 667 646
+f 706 1186 728
+f 733 575 568
+f 595 551 708
+f 595 540 551
+f 1308 501 1852
+f 665 339 160
+f 527 2447 535
+f 558 9 731
+f 723 793 773
+f 660 713 694
+f 693 725 666
+f 562 767 529
+f 550 538 531
+f 2267 2287 2233
+f 996 964 160
+f 2068 2470 2466
+f 704 711 719
+f 741 762 749
+f 605 606 626
+f 548 542 530
+f 995 878 709
+f 1898 1684 1916
+f 778 791 771
+f 782 163 785
+f 789 758 762
+f 857 883 847
+f 733 970 1028
+f 838 829 825
+f 2447 511 535
+f 22 603 137
+f 705 726 744
+f 605 587 580
+f 512 548 530
+f 743 784 742
+f 790 800 770
+f 778 810 808
+f 1014 998 355
+f 708 568 595
+f 656 697 551
+f 540 656 551
+f 143 125 614
+f 1000 1020 983
+f 778 178 1011
+f 676 704 682
+f 637 627 660
+f 606 627 637
+f 701 552 481
+f 808 810 785
+f 590 570 555
+f 716 595 568
+f 2355 2335 554
+f 912 1729 911
+f 1076 1456 1546
+f 697 68 492
+f 676 711 704
+f 839 851 838
+f 1028 575 733
+f 1020 844 982
+f 716 568 575
+f 844 781 982
+f 1238 2156 2034
+f 553 580 561
+f 580 579 561
+f 452 461 453
+f 560 578 48
+f 564 540 595
+f 632 656 540
+f 564 632 540
+f 75 578 599
+f 518 27 535
+f 511 518 535
+f 783 798 788
+f 642 759 663
+f 720 742 741
+f 605 626 587
+f 580 587 579
+f 725 712 666
+f 562 701 767
+f 1729 923 911
+f 712 743 742
+f 619 677 658
+f 161 695 654
+f 770 800 562
+f 2084 2489 2472
+f 575 559 716
+f 716 564 595
+f 654 695 685
+f 843 855 2064
+f 34 731 9
+f 527 510 1973
+f 723 622 793
+f 992 1726 987
+f 693 666 652
+f 2472 853 573
+f 624 159 148
+f 671 657 773
+f 681 188 498
+f 797 970 733
+f 565 656 632
+f 565 697 656
+f 565 731 697
+f 1949 951 920
+f 85 111 84
+f 662 200 190
+f 44 324 754
+f 33 547 40
+f 658 693 652
+f 658 652 645
+f 664 794 801
+f 666 712 692
+f 639 648 662
+f 611 646 610
+f 850 559 575
+f 1447 2490 1106
+f 1972 1955 1935
+f 582 615 590
+f 66 581 539
+f 780 641 631
+f 796 780 631
+f 1049 1192 83
+f 1348 13 1519
+f 799 807 562
+f 581 611 588
+f 687 795 644
+f 663 8 642
+f 1936 1972 1935
+f 650 676 682
+f 615 630 590
+f 730 795 687
+f 742 762 741
+f 548 553 542
+f 1048 1692 1074
+f 658 659 693
+f 37 52 30
+f 611 610 588
+f 649 632 564
+f 565 576 731
+f 2138 922 1058
+f 1204 854 965
+f 725 743 712
+f 644 813 641
+f 660 653 684
+f 771 791 770
+f 644 795 1074
+f 469 480 681
+f 559 672 564
+f 716 559 564
+f 672 649 564
+f 2161 1378 2171
+f 474 475 476
+f 816 765 701
+f 765 552 701
+f 513 538 548
+f 754 324 107
+f 609 586 618
+f 25 523 19
+f 677 659 658
+f 689 452 698
+f 1334 1115 1353
+f 700 565 632
+f 700 576 565
+f 481 552 793
+f 763 901 2458
+f 550 549 538
+f 781 964 996
+f 1596 1634 1595
+f 198 916 1124
+f 198 1124 341
+f 842 973 1025
+f 842 1025 836
+f 1009 1024 934
+f 573 710 2472
+f 1100 971 1002
+f 1501 1081 1557
+f 1225 1219 955
+f 413 2138 284
+f 955 1630 522
+f 341 1124 301
+f 2333 2376 2350
+f 1107 218 284
+f 398 925 1513
+f 1513 1442 1495
+f 1935 1455 1744
+f 1723 1935 1744
+f 825 1872 838
+f 1495 1442 1496
+f 963 1024 1009
+f 1511 1514 966
+f 1775 1729 912
+f 688 262 1067
+f 714 1007 1512
+f 919 1732 914
+f 2319 2331 2304
+f 2400 2407 2391
+f 1674 2164 1780
+f 843 927 899
+f 1660 988 1188
+f 1067 262 1640
+f 1381 1109 1483
+f 1437 1381 1483
+f 2495 1010 948
+f 1514 1289 1313
+f 899 374 961
+f 1438 1430 1422
+f 1634 1095 1632
+f 2487 973 2461
+f 1003 499 874
+f 849 848 827
+f 1430 1462 1453
+f 2496 2084 2471
+f 909 10 980
+f 730 927 835
+f 2031 1540 1536
+f 831 849 2178
+f 881 834 951
+f 1841 1722 1803
+f 1005 670 1020
+f 1021 670 1005
+f 1869 2059 2467
+f 903 902 1939
+f 2476 2502 1651
+f 853 8 573
+f 1850 831 2178
+f 934 746 247
+f 934 65 746
+f 301 285 1077
+f 968 944 977
+f 970 2495 1028
+f 974 2465 374
+f 899 927 374
+f 1882 1898 1916
+f 1613 1634 1596
+f 909 833 1396
+f 2492 247 1003
+f 919 914 1931
+f 1459 1299 1458
+f 1634 1632 1633
+f 844 670 228
+f 2494 2497 2467
+f 901 973 2487
+f 228 1772 734
+f 1701 1709 1666
+f 963 574 1024
+f 847 864 856
+f 1730 1736 2239
+f 870 859 848
+f 2074 2111 2103
+f 1140 1590 1483
+f 927 730 974
+f 2103 978 2074
+f 756 1745 1718
+f 848 859 840
+f 1296 1482 1320
+f 2331 51 66
+f 1067 988 962
+f 1396 833 1445
+f 1001 1005 1000
+f 901 1009 973
+f 1099 1077 817
+f 933 944 936
+f 952 958 1828
+f 988 1660 986
+f 833 1067 1445
+f 1067 1640 988
+f 218 413 284
+f 1843 180 347
+f 1846 1708 1798
+f 2469 2477 855
+f 1006 1021 1005
+f 381 382 250
+f 2369 828 531
+f 968 977 1001
+f 2460 1949 779
+f 1194 1441 1115
+f 1001 1000 968
+f 756 678 1745
+f 963 1009 901
+f 2471 2084 2472
+f 841 642 8
+f 982 991 1027
+f 670 844 1020
+f 1289 1514 945
+f 869 904 890
+f 1161 1115 1639
+f 823 2178 849
+f 746 12 499
+f 263 428 2366
+f 1685 1075 1692
+f 1002 926 806
+f 1799 1755 216
+f 944 968 993
+f 943 944 993
+f 31 38 19
+f 531 828 550
+f 1501 1078 1081
+f 1921 1149 431
+f 936 943 932
+f 1660 1489 1412
+f 301 980 285
+f 903 918 902
+f 869 890 868
+f 890 903 867
+f 1003 746 499
+f 951 1949 2500
+f 990 841 853
+f 1595 1634 1611
+f 374 927 974
+f 836 1025 247
+f 1653 1652 1638
+f 1303 1545 1142
+f 1616 1631 1638
+f 1629 1546 1628
+f 936 932 913
+f 513 506 531
+f 868 890 867
+f 2330 2369 2353
+f 924 918 914
+f 907 914 904
+f 1258 1421 1267
+f 301 939 980
+f 1472 1482 1296
+f 868 867 859
+f 472 491 313
+f 272 519 2488
+f 1471 1472 1296
+f 1025 934 247
+f 1634 1633 1611
+f 2176 1847 2177
+f 1310 1289 806
+f 924 933 918
+f 1969 1968 902
+f 2107 2128 2118
+f 1428 1436 1287
+f 1139 1564 1617
+f 2378 572 2384
+f 853 841 8
+f 2501 961 2465
+f 1221 1240 1408
+f 1069 1578 1627
+f 1006 1005 1001
+f 1617 1564 1578
+f 828 539 550
+f 1791 2168 2160
+f 1829 1718 1739
+f 1968 1939 902
+f 756 1718 665
+f 1998 2000 1388
+f 2451 545 2356
+f 178 997 1011
+f 1275 325 1270
+f 1709 872 1666
+f 2176 1959 1847
+f 944 943 936
+f 2424 518 511
+f 1445 1067 962
+f 2007 952 1828
+f 2052 2061 2081
+f 828 2303 539
+f 835 1699 1048
+f 1709 1706 872
+f 885 574 963
+f 1318 1296 1320
+f 859 867 1902
+f 1452 1448 1421
+f 943 993 976
+f 993 1000 983
+f 854 1010 876
+f 988 986 962
+f 2031 2052 2081
+f 924 1732 1828
+f 965 949 1060
+f 781 228 734
+f 1718 1765 665
+f 943 976 932
+f 1680 1794 1783
+f 1448 1471 1276
+f 1276 1267 1421
+f 1931 914 907
+f 991 781 996
+f 1276 1421 1448
+f 10 909 1396
+f 831 860 849
+f 1523 1762 1774
+f 924 1828 937
+f 307 994 1014
+f 946 963 901
+f 978 2103 977
+f 977 1006 1001
+f 1007 1161 1639
+f 1639 1294 1437
+f 885 1032 574
+f 1294 1381 1437
+f 733 568 797
+f 792 229 1112
+f 119 581 108
+f 843 835 927
+f 1889 860 831
+f 2211 2216 2204
+f 2400 2431 2422
+f 2103 1006 977
+f 840 1902 830
+f 827 840 830
+f 827 830 822
+f 1003 874 2492
+f 1432 1439 1431
+f 781 734 964
+f 1937 1936 1723
+f 918 913 902
+f 958 977 944
+f 1850 2178 2177
+f 1005 1020 1000
+f 991 996 307
+f 1396 1445 340
+f 2179 1763 889
+f 939 909 980
+f 1828 958 937
+f 978 977 958
+f 1590 1571 1563
+f 779 1949 920
+f 1551 1362 1573
+f 2103 2142 1006
+f 920 885 963
+f 946 920 963
+f 1584 1616 1583
+f 1453 1472 1452
+f 1647 1617 1578
+f 1578 1564 1627
+f 1628 938 1069
+f 869 868 859
+f 993 983 976
+f 912 1762 1775
+f 752 751 706
+f 1628 1546 938
+f 844 228 781
+f 840 859 1902
+f 898 907 904
+f 1025 973 1009
+f 663 664 573
+f 763 946 901
+f 898 904 869
+f 2172 889 1763
+f 1128 926 971
+f 860 848 849
+f 904 903 890
+f 2486 2459 2479
+f 577 782 608
+f 933 936 918
+f 2177 1847 1851
+f 665 1765 339
+f 937 958 944
+f 894 981 724
+f 968 1000 993
+f 2192 2195 2205
+f 1652 1099 817
+f 997 608 1011
+f 997 577 608
+f 577 163 782
+f 1112 998 792
+f 2177 1851 1850
+f 1257 1421 1258
+f 951 873 920
+f 822 830 2215
+f 1899 2496 2471
+f 1773 1668 1558
+f 904 914 903
+f 932 1671 913
+f 873 885 920
+f 1013 1617 1647
+f 873 1032 885
+f 894 862 981
+f 2469 855 961
+f 913 1671 1969
+f 2477 2064 855
+f 918 936 913
+f 860 870 848
+f 937 944 933
+f 1501 1013 1647
+f 824 178 751
+f 824 997 178
+f 824 577 997
+f 643 163 577
+f 863 856 882
+f 2128 2153 2134
+f 722 774 880
+f 722 894 774
+f 864 905 895
+f 850 575 583
+f 914 918 903
+f 924 937 933
+f 1501 717 1013
+f 1587 1324 928
+f 717 1512 1013
+f 602 577 824
+f 766 643 577
+f 894 709 862
+f 709 878 862
+f 976 975 932
+f 1324 1596 928
+f 880 524 1060
+f 2434 2459 2499
+f 1324 1613 1596
+f 752 824 751
+f 602 766 577
+f 1014 602 594
+f 1387 1226 2152
+f 2153 1387 2152
+f 669 930 950
+f 1710 1694 1699
+f 768 326 762
+f 582 892 601
+f 974 990 2465
+f 624 116 625
+f 835 795 730
+f 2458 2484 763
+f 989 602 824
+f 2064 2477 1710
+f 976 983 975
+f 949 722 880
+f 996 160 994
+f 2305 863 556
+f 556 863 886
+f 601 910 640
+f 2264 825 829
+f 989 824 752
+f 856 864 882
+f 1595 1586 2381
+f 1627 1629 1628
+f 2174 2180 2173
+f 2128 2134 2118
+f 137 272 22
+f 949 880 1060
+f 995 894 722
+f 894 995 709
+f 894 724 774
+f 886 895 892
+f 640 910 930
+f 871 870 860
+f 846 856 863
+f 1026 875 1019
+f 838 851 829
+f 1024 1171 934
+f 36 189 205
+f 863 882 886
+f 886 882 895
+f 875 1026 594
+f 52 1459 1269
+f 896 917 910
+f 1025 1009 934
+f 949 995 722
+f 2152 1226 1636
+f 895 896 892
+f 892 910 601
+f 942 950 930
+f 875 989 752
+f 594 602 989
+f 766 355 643
+f 355 260 643
+f 905 917 896
+f 965 1060 1162
+f 892 896 910
+f 1101 1052 1042
+f 1029 1031 834
+f 1101 1133 1118
+f 342 357 376
+f 516 515 2454
+f 1656 2494 2467
+f 1056 1303 1133
+f 1120 1130 862
+f 69 342 376
+f 1055 1056 1133
+f 499 69 165
+f 85 101 111
+f 1031 1032 834
+f 200 679 1166
+f 1031 1042 1032
+f 1171 65 934
+f 1822 1204 1177
+f 1096 956 1103
+f 514 96 97
+f 956 1145 1144
+f 1185 1166 1144
+f 1145 1185 1144
+f 1185 200 1166
+f 375 132 1041
+f 1153 1202 305
+f 32 1244 1249
+f 1096 1087 956
+f 554 78 2355
+f 1191 138 110
+f 65 35 432
+f 1087 1110 956
+f 1110 1146 956
+f 956 1146 1145
+f 1146 1156 1145
+f 1145 1156 1185
+f 950 956 1144
+f 2481 2495 948
+f 1156 1193 1185
+f 1050 1047 1051
+f 239 151 107
+f 1185 1193 36
+f 1747 1110 1087
+f 1134 1146 1110
+f 1146 1157 1156
+f 1156 1157 1193
+f 1041 1045 1034
+f 1397 1134 1110
+f 1157 1146 1134
+f 1157 1175 1193
+f 1193 199 36
+f 1090 1035 1196
+f 1456 1150 1051
+f 1175 199 1193
+f 1186 695 199
+f 1186 199 1175
+f 1175 1157 1134
+f 728 1186 1175
+f 197 760 6
+f 1130 593 862
+f 1167 1109 182
+f 1194 1115 1161
+f 2140 1928 1504
+f 921 922 2138
+f 1147 1134 1397
+f 1719 1147 1397
+f 1147 1175 1134
+f 1175 1147 728
+f 341 1654 1208
+f 754 151 9
+f 284 2138 1058
+f 1188 1557 1660
+f 1191 110 1053
+f 916 284 1189
+f 284 1058 1189
+f 2094 1465 2127
+f 1726 1019 1147
+f 1147 1019 728
+f 593 1130 96
+f 239 305 1038
+f 1036 1131 315
+f 397 1131 1120
+f 1053 96 1130
+f 2467 2485 1869
+f 517 1089 421
+f 834 1827 1029
+f 419 1047 1117
+f 1034 433 1306
+f 2239 1862 1730
+f 1453 1462 1472
+f 1408 1422 1399
+f 471 23 1111
+f 1205 1150 1456
+f 1205 1040 1150
+f 1131 1036 293
+f 293 1068 1044
+f 375 1041 138
+f 1205 1140 1046
+f 1040 1205 1046
+f 1140 1167 1046
+f 1104 1049 83
+f 1052 1085 1032
+f 1044 1068 1191
+f 1167 1483 1109
+f 208 1084 1035
+f 1040 132 375
+f 1834 20 3
+f 1050 1051 1070
+f 1133 1125 1174
+f 11 1440 1401
+f 420 208 1071
+f 1135 1079 1094
+f 1086 1101 1118
+f 1029 1030 1031
+f 1200 1061 294
+f 1191 1068 138
+f 1171 1141 65
+f 1141 1172 65
+f 1172 35 65
+f 1172 404 35
+f 404 99 35
+f 221 1104 1063
+f 802 398 1083
+f 20 1089 3
+f 2064 1699 835
+f 1042 1052 1032
+f 1433 1261 1432
+f 1323 2338 155
+f 1076 1205 1456
+f 1088 1402 1056
+f 1150 348 1070
+f 1200 1089 20
+f 1097 1162 100
+f 1032 873 834
+f 21 471 1111
+f 294 1097 1104
+f 1072 100 584
+f 1151 760 622
+f 132 1045 1041
+f 1050 1070 1135
+f 1088 1039 940
+f 650 159 635
+f 100 1170 729
+f 729 584 100
+f 1103 931 1096
+f 925 1443 1513
+f 138 1102 110
+f 1034 1306 1152
+f 1071 1035 1090
+f 100 1072 1097
+f 23 1158 315
+f 1068 375 138
+f 1586 1612 1585
+f 1819 1030 1029
+f 1041 1034 1102
+f 232 375 1068
+f 348 1079 1070
+f 1061 1097 294
+f 1513 1443 1442
+f 1200 294 1119
+f 376 1050 1062
+f 1094 1036 315
+f 1200 1119 1089
+f 1111 1183 21
+f 1044 1191 1053
+f 698 295 689
+f 1079 232 1036
+f 404 1117 99
+f 1495 1496 717
+f 1119 294 98
+f 3 1089 517
+f 1132 1063 83
+f 1132 83 175
+f 132 1046 182
+f 1111 1195 1183
+f 1131 1044 1037
+f 127 402 1804
+f 219 1272 1047
+f 1697 1135 1094
+f 2140 1854 2117
+f 1111 397 1195
+f 1177 1162 1097
+f 1061 1177 1097
+f 717 1509 714
+f 2 1300 433
+f 462 290 461
+f 98 294 221
+f 294 1104 221
+f 714 1161 1007
+f 1073 1152 1143
+f 1697 1094 1360
+f 1223 1423 1218
+f 836 2479 842
+f 1097 1072 1049
+f 348 1040 375
+f 3 517 316
+f 180 1061 1201
+f 348 375 232
+f 1432 1431 1415
+f 220 1513 1495
+f 1104 1097 1049
+f 306 674 596
+f 777 455 723
+f 2170 2151 1641
+f 1047 419 219
+f 1102 1034 1073
+f 1073 1034 1152
+f 1035 1054 1196
+f 1177 1204 1162
+f 746 65 12
+f 751 178 721
+f 1054 517 421
+f 1051 1150 1070
+f 1102 1073 110
+f 998 1136 355
+f 567 566 1163
+f 1111 315 397
+f 1048 1074 835
+f 1158 1094 315
+f 1374 1107 1252
+f 1112 1136 998
+f 472 629 500
+f 355 1136 260
+f 260 118 43
+f 1104 83 1063
+f 376 357 1050
+f 1463 1142 1545
+f 1036 232 293
+f 1030 1042 1031
+f 1079 348 232
+f 221 1063 1132
+f 1094 1079 1036
+f 1076 1629 1205
+f 1136 1197 260
+f 260 1197 118
+f 1204 965 1162
+f 293 232 1068
+f 1590 1205 1629
+f 1205 1590 1140
+f 250 382 392
+f 1296 1318 1311
+f 347 1201 20
+f 1201 1200 20
+f 132 182 1045
+f 1101 1086 1052
+f 1033 1039 1055
+f 138 1041 1102
+f 970 1010 2495
+f 455 777 43
+f 1992 1948 2023
+f 20 1834 347
+f 1072 584 1049
+f 584 1192 1049
+f 182 2 1045
+f 1163 324 44
+f 1360 1094 1158
+f 1450 1360 1158
+f 1091 1112 229
+f 509 723 455
+f 207 509 455
+f 1251 1257 1266
+f 1488 1489 1547
+f 2157 1541 1875
+f 305 107 324
+f 1045 2 433
+f 1070 1079 1135
+f 1136 1168 1197
+f 1197 359 118
+f 118 359 43
+f 359 356 43
+f 356 455 43
+f 356 207 455
+f 1240 1422 1408
+f 1163 1153 324
+f 1201 1061 1200
+f 1052 1086 1085
+f 1024 1141 1171
+f 1112 1105 1136
+f 1050 1135 1062
+f 1105 1168 1136
+f 1168 1178 1197
+f 1197 1178 359
+f 1173 404 1172
+f 465 356 359
+f 1174 1125 240
+f 1240 1431 1422
+f 1098 1113 1105
+f 1112 1098 1105
+f 1105 1178 1168
+f 1178 465 359
+f 1091 1098 1112
+f 1133 1174 1118
+f 98 221 1059
+f 487 1132 175
+f 980 1017 285
+f 465 207 356
+f 180 1201 347
+f 1060 524 1170
+f 445 127 316
+f 1431 1438 1422
+f 498 469 681
+f 940 1807 1759
+f 381 250 1290
+f 1113 1122 1105
+f 1105 1122 1178
+f 1151 509 207
+f 1236 2035 525
+f 1131 293 1044
+f 346 207 465
+f 346 1151 207
+f 1822 1796 1204
+f 1143 204 97
+f 123 1128 971
+f 2153 2152 2134
+f 126 1151 346
+f 517 445 316
+f 1450 1158 23
+f 1458 1462 1430
+f 1129 152 1182
+f 1122 1159 1178
+f 1178 1198 465
+f 79 346 465
+f 126 1155 1151
+f 1151 1155 6
+f 295 1129 689
+f 1073 1143 97
+f 1098 1123 1113
+f 1113 1123 1122
+f 1123 1169 1122
+f 1178 1159 1198
+f 1198 79 465
+f 392 383 152
+f 1822 1061 180
+f 116 92 625
+f 421 1089 1119
+f 1129 295 152
+f 110 1073 97
+f 1173 1172 1141
+f 1122 1169 1159
+f 79 126 346
+f 1155 181 6
+f 971 926 1002
+f 295 1043 152
+f 1039 1088 1056
+f 1428 1266 1436
+f 404 419 1117
+f 836 879 2479
+f 2464 2476 2458
+f 1198 317 79
+f 1124 939 301
+f 44 754 567
+f 1039 1056 1055
+f 1439 1459 1458
+f 1660 1412 986
+f 1169 1160 1159
+f 179 1155 126
+f 1155 131 181
+f 1061 1822 1177
+f 1153 305 324
+f 175 314 327
+f 1160 1187 1159
+f 1159 1187 1198
+f 1198 1187 317
+f 79 179 126
+f 1043 250 392
+f 152 1043 392
+f 96 819 593
+f 1123 1127 1169
+f 317 179 79
+f 1057 1155 179
+f 1155 391 131
+f 131 391 668
+f 2381 1586 1585
+f 12 69 499
+f 262 398 1640
+f 2107 2118 2060
+f 2130 2094 2002
+f 1187 249 317
+f 1155 1057 391
+f 1290 439 1265
+f 305 239 107
+f 1127 1160 1169
+f 317 473 179
+f 473 1057 179
+f 83 1192 314
+f 1043 1290 250
+f 1807 940 1030
+f 517 1084 445
+f 1057 1164 391
+f 2492 2480 2493
+f 163 643 43
+f 1056 1545 1303
+f 1069 1655 1023
+f 249 473 317
+f 1162 1060 1170
+f 1086 1118 1154
+f 82 68 16
+f 1989 1990 1536
+f 1633 1632 1611
+f 1487 2372 1305
+f 1494 1069 1023
+f 1137 1160 1127
+f 669 1166 679
+f 390 1285 426
+f 1955 1972 1971
+f 1219 1223 2437
+f 1254 1261 1223
+f 1319 1545 1056
+f 1320 1328 2443
+f 1261 1433 1223
+f 1219 1254 1223
+f 254 222 2428
+f 1237 1290 1265
+f 1284 1273 1263
+f 1277 1291 1301
+f 1314 102 1301
+f 1280 363 377
+f 1313 1353 1514
+f 468 451 439
+f 1918 1964 1956
+f 2026 29 2140
+f 1354 381 1279
+f 1224 30 1254
+f 147 158 173
+f 1247 1253 274
+f 1271 380 334
+f 2043 2072 2042
+f 274 300 267
+f 1356 1392 211
+f 13 240 1142
+f 1382 1330 1392
+f 1312 1323 155
+f 240 1125 1142
+f 2358 1573 1362
+f 1236 1249 1244
+f 1272 219 1348
+f 1271 1274 380
+f 191 2034 1982
+f 1992 2052 1990
+f 462 452 689
+f 2262 2286 2261
+f 183 489 1642
+f 2485 2480 1869
+f 84 111 1323
+f 1190 353 1354
+f 446 434 435
+f 1336 171 1341
+f 2021 430 2059
+f 862 878 1120
+f 1263 1273 1248
+f 1966 1921 2144
+f 1312 84 1323
+f 240 13 1348
+f 1359 1274 1271
+f 1392 1330 1247
+f 1520 1333 11
+f 1368 1253 1247
+f 1279 1285 1190
+f 2465 990 2489
+f 1272 1519 805
+f 1369 1272 805
+f 1317 95 1344
+f 1242 1248 1234
+f 1368 242 1363
+f 274 1262 1386
+f 532 597 1886
+f 2117 2026 2140
+f 1392 1247 274
+f 2162 508 985
+f 1964 1469 1965
+f 1315 104 1331
+f 1392 1356 1382
+f 128 1342 1336
+f 1285 427 426
+f 1219 1224 1254
+f 1320 1322 1321
+f 1320 1321 1328
+f 153 2443 1328
+f 1321 153 1328
+f 1235 1244 1243
+f 1225 1224 1219
+f 1359 353 1190
+f 1312 1473 1458
+f 1336 1342 147
+f 305 1333 1038
+f 1336 147 171
+f 516 31 19
+f 2479 2461 842
+f 1237 1265 427
+f 1263 1278 1284
+f 881 1827 834
+f 1237 427 1285
+f 1299 1312 1458
+f 1190 1285 1274
+f 1363 286 1253
+f 2330 2303 828
+f 427 442 426
+f 2493 2463 2492
+f 1285 380 1274
+f 522 18 1225
+f 2471 2472 2488
+f 2338 154 1321
+f 1423 1415 1218
+f 1225 18 1224
+f 1253 286 1262
+f 286 353 1359
+f 171 1368 1383
+f 1273 54 1234
+f 1973 2447 527
+f 1322 155 1321
+f 1203 1369 1413
+f 1307 363 1298
+f 1364 1375 1329
+f 1329 227 1306
+f 296 1298 1343
+f 947 2499 1447
+f 1203 1047 1272
+f 1098 1748 1123
+f 1519 1272 1348
+f 1277 70 1273
+f 1282 1337 1361
+f 286 302 353
+f 103 104 1315
+f 1377 435 434
+f 1449 1261 1345
+f 926 1310 806
+f 1263 1248 1242
+f 985 508 597
+f 1415 1222 1218
+f 88 1325 104
+f 170 111 156
+f 1384 1282 1361
+f 274 1253 1262
+f 1371 1317 1344
+f 1371 1366 1337
+f 1345 1459 1449
+f 171 1383 1341
+f 2438 1235 1227
+f 2134 1582 2118
+f 428 1260 1379
+f 1336 1341 1325
+f 1235 1242 1227
+f 1228 1687 2284
+f 1854 2140 2016
+f 1866 1887 1873
+f 1343 1298 1370
+f 1384 1361 2440
+f 171 242 1368
+f 1344 1309 1366
+f 1371 1344 1366
+f 1280 1377 1293
+f 200 1185 205
+f 1330 1383 1368
+f 1255 1264 1263
+f 543 1367 1876
+f 1343 1370 1260
+f 1293 1326 1370
+f 2440 1361 1302
+f 1282 1384 2406
+f 271 1337 1282
+f 170 2338 1323
+f 1528 1503 2470
+f 515 1347 2453
+f 1997 1705 1998
+f 2285 1228 2284
+f 1229 1250 1228
+f 1330 1368 1247
+f 1919 1619 2045
+f 1344 1364 1335
+f 1222 1240 1221
+f 1212 858 1741
+f 2388 1222 1221
+f 1528 2470 2068
+f 501 1308 2171
+f 1295 1311 1487
+f 2116 1619 1655
+f 1220 1229 1228
+f 8 663 573
+f 1343 1260 428
+f 1337 1366 1361
+f 1298 1280 1293
+f 1269 1345 1261
+f 1279 381 1290
+f 1230 1229 1220
+f 1230 1245 1229
+f 1245 1250 1229
+f 1227 1234 31
+f 1302 1361 1350
+f 1245 1266 1428
+f 1992 2023 2052
+f 2482 2471 2475
+f 452 462 461
+f 271 1282 1275
+f 1991 1989 1934
+f 1366 1309 1350
+f 1344 1335 1309
+f 730 699 974
+f 1374 1252 1208
+f 597 508 1912
+f 1363 1253 1368
+f 1386 1271 300
+f 1211 1218 1222
+f 1376 1377 434
+f 2399 2437 1211
+f 1284 1291 1277
+f 1230 1251 1245
+f 1251 1266 1245
+f 1317 1371 1337
+f 1288 1286 1095
+f 1095 1286 1352
+f 1241 1208 1352
+f 1241 1374 1208
+f 1284 1278 1291
+f 211 1392 267
+f 1344 1375 1364
+f 929 583 1028
+f 1361 1366 1350
+f 1115 1294 1639
+f 1291 103 1301
+f 1220 1231 1230
+f 1231 1251 1230
+f 1234 1248 1273
+f 1255 55 1264
+f 1360 1450 1702
+f 363 1280 1298
+f 1369 1203 1272
+f 1415 1240 1222
+f 1216 1231 1220
+f 1243 1263 1235
+f 1375 227 1329
+f 1264 1278 1263
+f 855 899 961
+f 1286 1241 1352
+f 2081 2128 2107
+f 1223 1433 1423
+f 1473 1312 155
+f 154 153 1321
+f 1377 1376 1293
+f 1392 274 267
+f 334 300 1271
+f 1955 1991 1934
+f 1613 1327 1288
+f 1327 1286 1288
+f 1349 1374 1241
+f 2370 2025 2367
+f 1315 1331 133
+f 434 446 1256
+f 1232 1251 1231
+f 1243 1244 1255
+f 1286 1304 1241
+f 1349 1107 1374
+f 1359 1271 1386
+f 1227 516 2431
+f 219 240 1348
+f 1270 271 1275
+f 1255 1263 1243
+f 2026 1926 29
+f 1683 2157 1212
+f 1326 1293 1376
+f 1255 32 55
+f 104 1325 1341
+f 519 2462 2475
+f 2154 2161 2137
+f 1376 434 1246
+f 1246 434 1256
+f 1257 1251 1232
+f 1262 1359 1386
+f 2195 2192 2186
+f 1308 534 1226
+f 2026 2117 544
+f 1327 1613 1324
+f 1327 1326 1286
+f 1286 1326 1304
+f 104 1341 1331
+f 774 524 880
+f 837 1517 534
+f 1127 1123 1567
+f 1279 1237 1285
+f 1297 1381 1294
+f 1217 1232 1216
+f 1142 1519 13
+f 1436 1267 1287
+f 1324 1372 1327
+f 1304 1246 1241
+f 1246 1349 1241
+f 1246 1373 1349
+f 286 1359 1262
+f 1382 1383 1330
+f 1284 1277 1273
+f 489 1998 1799
+f 1675 1116 1075
+f 106 1317 1337
+f 1311 1295 1281
+f 1292 1364 1329
+f 1335 1364 1292
+f 1334 1294 1115
+f 1334 1297 1294
+f 1300 1381 1297
+f 973 842 2461
+f 1217 1239 1232
+f 1232 1239 1257
+f 1258 1267 1436
+f 1359 1190 1274
+f 1862 1405 1877
+f 1372 1339 1327
+f 1339 1326 1327
+f 1373 1351 1349
+f 1276 1311 1281
+f 1256 2386 1351
+f 2 1109 1300
+f 482 1731 520
+f 803 1604 2022
+f 1223 1218 1211
+f 1341 1383 1382
+f 1298 1293 1370
+f 1190 1354 1279
+f 1324 2398 1372
+f 1714 1700 2173
+f 183 2000 489
+f 1701 1666 192
+f 1227 1242 1234
+f 1332 1289 1310
+f 1517 2005 2130
+f 1331 1341 1382
+f 525 1249 1236
+f 23 1268 1450
+f 1264 1291 1278
+f 1281 1287 1267
+f 1295 1305 1287
+f 1281 1295 1287
+f 1487 1305 1295
+f 1605 2097 2058
+f 1326 1376 1304
+f 1304 1376 1246
+f 1316 1919 1984
+f 2500 1949 2460
+f 1332 1313 1289
+f 2189 2181 2177
+f 1335 1334 1353
+f 1292 1297 1334
+f 1428 1250 1245
+f 969 958 952
+f 1217 1233 1239
+f 1233 1257 1239
+f 1876 1367 1338
+f 1379 1260 1372
+f 1372 1260 1339
+f 1128 1302 1310
+f 1310 1302 1332
+f 1335 1353 1313
+f 1292 1334 1335
+f 1297 1329 1300
+f 1279 1290 1237
+f 1301 103 1314
+f 70 1301 102
+f 23 1333 1268
+f 380 1285 390
+f 772 325 1275
+f 1314 103 1315
+f 2473 2458 2487
+f 1276 1281 1267
+f 1344 95 1375
+f 2053 1771 1572
+f 1246 1256 1373
+f 1373 1256 1351
+f 1340 1302 1128
+f 1350 1313 1332
+f 1329 1297 1292
+f 2434 2473 2487
+f 106 1337 271
+f 23 471 1333
+f 622 723 509
+f 1388 1517 2127
+f 1991 1990 1989
+f 183 1636 1226
+f 2133 1605 2151
+f 1260 1370 1339
+f 1339 1370 1326
+f 867 1894 1902
+f 390 426 412
+f 1235 1263 1242
+f 1399 1422 1233
+f 305 11 1333
+f 1300 1329 1306
+f 1302 1350 1332
+f 1350 1309 1313
+f 1309 1335 1313
+f 2470 2102 1502
+f 1787 1531 1599
+f 1724 1725 1691
+f 1827 1601 1927
+f 1678 1358 1476
+f 1823 1812 1846
+f 1805 1824 1708
+f 1746 1676 1797
+f 325 2395 429
+f 1835 1677 1826
+f 1507 1790 1722
+f 1526 1672 858
+f 158 147 1342
+f 1462 1473 1322
+f 1474 1414 1565
+f 1761 1900 1877
+f 940 1759 1008
+f 1565 1015 1008
+f 1924 1533 1933
+f 1878 826 830
+f 1565 1414 1015
+f 1402 1088 1008
+f 1538 1532 1651
+f 1015 1552 1008
+f 1538 1591 1474
+f 1532 1538 1474
+f 1474 1591 1414
+f 1484 1402 1008
+f 1552 1484 1008
+f 1414 1460 1015
+f 1015 1460 1552
+f 806 1289 945
+f 1597 1538 1659
+f 1484 1319 1402
+f 1056 1402 1319
+f 1538 1597 1591
+f 1591 960 1414
+f 1414 960 1460
+f 1925 1466 1455
+f 1552 1400 1484
+f 1484 1400 1319
+f 1400 113 1319
+f 1597 1580 1591
+f 1460 1400 1552
+f 1514 1441 966
+f 1597 1659 1409
+f 1657 113 1400
+f 1460 1657 1400
+f 1288 1095 1634
+f 1551 1597 1409
+f 1580 1598 1591
+f 1591 1598 960
+f 1536 1990 2031
+f 960 1657 1460
+f 1809 1746 1797
+f 1423 1433 1432
+f 2478 1362 1409
+f 1463 1545 113
+f 1657 1463 113
+f 1457 1287 1305
+f 1682 1716 1746
+f 1434 1761 1885
+f 1013 1139 1617
+f 2379 1362 2478
+f 1420 1597 1551
+f 1420 1580 1597
+f 1664 1808 1712
+f 2256 2250 2231
+f 1362 1551 1409
+f 2196 2214 2213
+f 1691 1725 1777
+f 1626 192 1666
+f 1534 1574 2058
+f 1574 1600 1605
+f 1600 1606 1605
+f 1606 1641 1605
+f 1573 1420 1551
+f 1657 1485 1463
+f 678 1806 1742
+f 1534 1553 1574
+f 1574 1575 1600
+f 1810 2170 585
+f 1623 1641 1606
+f 1407 1657 960
+f 1598 1407 960
+f 1485 1142 1463
+f 1716 1581 1676
+f 1738 1743 1733
+f 843 2064 835
+f 1539 1575 1574
+f 1553 1539 1574
+f 1575 1592 1600
+f 1592 1624 1606
+f 1600 1592 1606
+f 1642 585 1641
+f 1623 1642 1641
+f 1485 164 1142
+f 1738 1516 1743
+f 1809 1720 1798
+f 1533 1535 1534
+f 1592 1607 1624
+f 1624 1623 1606
+f 1163 566 1116
+f 1407 1485 1657
+f 1432 1449 1439
+f 1100 802 2382
+f 1743 1516 1722
+f 1746 1716 1676
+f 1535 1539 1534
+f 1534 1539 1553
+f 1642 1623 1624
+f 1095 1208 1654
+f 967 1407 1598
+f 1580 967 1598
+f 1809 1797 1720
+f 1924 1524 1535
+f 1533 1924 1535
+f 1539 1576 1575
+f 1642 216 585
+f 1407 1529 1485
+f 1485 1529 164
+f 1472 1462 1482
+f 1415 1431 1240
+f 966 1194 714
+f 383 1182 152
+f 474 2337 446
+f 1743 1841 1757
+f 1486 1524 1924
+f 1535 1525 1539
+f 1575 1576 1592
+f 1420 967 1580
+f 1288 1634 1613
+f 459 427 1265
+f 1404 2179 1393
+f 1404 1403 1800
+f 1404 1410 1403
+f 1410 1749 1403
+f 1349 1351 218
+f 1486 1498 1524
+f 1535 1524 1525
+f 1607 1636 1624
+f 183 1642 1624
+f 1636 183 1624
+f 1107 1349 218
+f 1351 845 218
+f 164 1519 1142
+f 845 413 218
+f 1525 1576 1539
+f 1576 1582 1592
+f 1592 2134 1607
+f 2134 1636 1607
+f 2147 1491 1401
+f 1407 1589 1529
+f 1529 1519 164
+f 1693 1763 1444
+f 1924 1479 1486
+f 1592 1582 2134
+f 499 165 874
+f 2176 1857 1959
+f 2327 2368 2326
+f 2358 821 953
+f 953 821 1573
+f 1824 1704 1464
+f 1731 1358 1678
+f 1394 1410 1404
+f 1394 1418 1410
+f 1466 1479 1839
+f 1486 1479 1498
+f 1498 1525 1524
+f 1576 2080 1582
+f 1785 1684 1898
+f 804 398 802
+f 804 925 398
+f 1447 1562 2358
+f 2358 1562 821
+f 821 1620 1573
+f 1620 1420 1573
+f 1420 1556 967
+f 1393 1394 1404
+f 1525 2080 1576
+f 1621 1420 1620
+f 1621 1556 1420
+f 967 1589 1407
+f 1505 5 1357
+f 1266 1258 1436
+f 1393 1395 1394
+f 2176 2175 1848
+f 1455 1466 1839
+f 1525 1540 2080
+f 1582 2080 2118
+f 1100 804 802
+f 1556 1589 967
+f 1589 1082 1529
+f 1093 1685 1357
+f 1504 1093 1357
+f 1425 1418 1394
+f 1475 1479 1466
+f 1479 1506 1498
+f 1789 1784 1730
+f 2501 2465 2489
+f 1438 1458 1430
+f 1462 1458 1473
+f 1454 805 1529
+f 1082 1454 1529
+f 1529 805 1519
+f 1425 1394 1395
+f 1425 1744 1418
+f 1479 1475 1506
+f 1540 2060 2080
+f 1556 1082 1589
+f 1443 945 1511
+f 1506 1536 1498
+f 1498 1536 1525
+f 1525 1536 1540
+f 1670 852 1672
+f 1998 1388 1389
+f 1511 966 1509
+f 1509 966 714
+f 1442 1443 1496
+f 1562 1635 821
+f 155 1322 1473
+f 1439 1458 1438
+f 1426 1425 1395
+f 1475 1499 1506
+f 1735 1588 1776
+f 2422 2454 2421
+f 1423 1432 1415
+f 1559 2101 2073
+f 845 866 413
+f 1429 1620 821
+f 1620 1429 1621
+f 1228 1250 1687
+f 1002 945 1443
+f 2382 802 1083
+f 1859 1411 1395
+f 1411 1426 1395
+f 1426 1744 1425
+f 1590 1437 1483
+f 1480 1475 1466
+f 1480 1499 1475
+f 1510 1733 1743
+f 1663 1696 1658
+f 1430 1453 1452
+f 1452 1472 1471
+f 1452 1471 1448
+f 1430 1452 1421
+f 1430 1421 1422
+f 1429 1082 1556
+f 1621 1429 1556
+f 1351 2386 845
+f 1126 1059 487
+f 1639 1437 1563
+f 1504 1928 1093
+f 1499 1536 1506
+f 1588 1770 1727
+f 1110 1747 1397
+f 1776 1588 1531
+f 1322 1320 1482
+f 1590 1629 1571
+f 1730 1877 1838
+f 1429 935 1082
+f 1082 935 1454
+f 804 1443 925
+f 1139 1007 1639
+f 1925 1480 1466
+f 1934 1989 1480
+f 1499 1989 1536
+f 1727 1526 1531
+f 1593 1614 502
+f 2455 2431 2400
+f 1755 1680 908
+f 1563 1571 1564
+f 1647 1078 1501
+f 2490 1635 1106
+f 1496 1511 717
+f 2454 2431 516
+f 1478 1153 1093
+f 1870 1426 1411
+f 1426 1723 1744
+f 962 986 1412
+f 717 1511 1509
+f 1825 1704 1824
+f 2225 2234 2253
+f 1490 1557 1188
+f 1635 80 821
+f 805 1454 935
+f 1186 706 695
+f 1194 1161 714
+f 1512 1007 1013
+f 592 97 204
+f 1258 1266 1257
+f 82 1333 471
+f 1694 1710 1505
+f 1643 490 1661
+f 1661 490 1114
+f 1518 2068 2484
+f 1750 1808 1664
+f 1656 1635 2490
+f 935 1521 805
+f 1546 1629 1076
+f 1301 70 1277
+f 966 1441 1194
+f 1148 1825 1824
+f 1614 1609 1643
+f 1114 1092 1921
+f 1770 1739 1670
+f 1631 1632 1646
+f 821 1016 1429
+f 1429 1016 935
+f 1632 1095 1654
+f 1083 262 688
+f 1724 1686 1725
+f 1644 490 1643
+f 1092 1149 1921
+f 3 893 1832
+f 988 1640 1188
+f 916 1107 284
+f 1656 80 1635
+f 1016 821 80
+f 1016 1521 935
+f 1478 1202 1153
+f 1401 1928 29
+f 1440 1478 1928
+f 1849 1700 1865
+f 1595 1611 1612
+f 1208 198 341
+f 1464 1704 1746
+f 2143 984 1721
+f 1848 1849 1868
+f 1662 1114 490
+f 1669 1787 1682
+f 1656 1618 80
+f 198 1208 916
+f 1440 1928 1401
+f 1521 1369 805
+f 1252 1107 916
+f 1745 678 1672
+f 1703 1779 1721
+f 1750 1465 1808
+f 1609 1644 1643
+f 1092 1114 1662
+f 1826 1523 1793
+f 2262 2261 2224
+f 1696 2166 1767
+f 1016 1648 1521
+f 1208 1252 916
+f 833 688 1067
+f 1794 1803 1558
+f 28 17 512
+f 1750 861 1566
+f 1594 1644 1609
+f 1644 1645 490
+f 490 1645 1662
+f 2229 2262 2224
+f 1602 861 1760
+f 1530 1777 1760
+f 872 1706 1673
+f 1696 1668 2166
+f 1708 1809 1798
+f 1581 1716 1814
+f 1709 1794 1680
+f 1233 1421 1257
+f 1724 1476 1686
+f 1469 1481 1965
+f 1965 1481 1492
+f 2073 1549 1559
+f 1594 1615 1644
+f 1799 1706 1755
+f 1725 1686 1837
+f 1720 1797 1572
+f 1618 2467 2022
+f 1618 1579 80
+f 1648 1016 80
+f 2134 2152 1636
+f 1611 1632 1631
+f 1761 1434 1470
+f 1559 1577 1594
+f 1603 1615 1594
+f 1615 1645 1644
+f 1637 1662 1645
+f 1662 1199 1092
+f 1199 1149 1092
+f 1451 1108 1149
+f 665 734 756
+f 1865 1700 1714
+f 1709 1841 1794
+f 1618 2022 1579
+f 1648 1413 1369
+f 1521 1648 1369
+f 1520 11 1401
+f 1446 1470 1434
+f 1798 1691 1754
+f 2063 1544 2073
+f 2073 1544 1549
+f 1594 1577 1603
+f 1615 1637 1645
+f 1637 1199 1662
+f 1427 1149 1199
+f 2167 1108 1451
+f 1997 1673 1705
+f 1706 1799 1705
+f 1841 1709 1757
+f 1604 1579 2022
+f 1579 707 80
+f 80 707 1648
+f 1520 1401 1491
+f 1649 1520 1491
+f 1435 1434 1885
+f 1470 1469 1461
+f 1481 1508 2024
+f 2370 1544 2063
+f 1549 1568 1559
+f 1559 1568 1577
+f 1603 1610 1615
+f 1615 1610 1637
+f 999 1199 1637
+f 1451 1149 1427
+f 1137 1825 1148
+f 1706 1705 1673
+f 1138 1604 2116
+f 1138 1579 1604
+f 1413 1648 707
+f 2360 2024 1508
+f 598 1075 1116
+f 229 93 1468
+f 1839 1479 1684
+f 2216 2229 2224
+f 1610 1625 1637
+f 329 999 1637
+f 1199 1017 1427
+f 1017 303 1427
+f 303 1451 1427
+f 1792 1754 1777
+f 2309 2391 2301
+f 1655 1138 2116
+f 1138 707 1579
+f 1649 1491 206
+f 1406 1885 1398
+f 1406 1419 1885
+f 1419 1435 1885
+f 1434 1435 1446
+f 1470 1481 1469
+f 1577 1583 1603
+f 999 1017 1199
+f 81 67 941
+f 67 1650 941
+f 1259 1815 2164
+f 1619 2116 2045
+f 1424 707 1138
+f 1702 1649 206
+f 1687 1406 1398
+f 1477 1481 1470
+f 1568 1569 1577
+f 1577 1569 1583
+f 1603 1583 1610
+f 1625 329 1637
+f 2167 340 273
+f 81 273 340
+f 81 962 67
+f 1547 1619 1488
+f 1830 1739 1770
+f 938 1424 1138
+f 1424 1413 707
+f 1527 1649 1702
+f 1527 1520 1649
+f 1527 1268 1520
+f 1250 1406 1687
+f 1441 1353 1115
+f 1203 1413 1051
+f 1250 1419 1406
+f 1477 2372 1481
+f 1481 2372 1508
+f 2449 1560 1568
+f 1549 2449 1568
+f 1568 1560 1569
+f 1569 1584 1583
+f 1652 329 1625
+f 329 817 999
+f 285 1017 999
+f 303 10 1451
+f 10 2167 1451
+f 1412 1650 67
+f 1412 1488 1650
+f 1547 1023 1619
+f 1023 1655 1619
+f 1655 938 1138
+f 1456 1413 1424
+f 1457 1470 1446
+f 1457 1477 1470
+f 329 1652 817
+f 10 340 2167
+f 938 1546 1424
+f 1546 1456 1424
+f 1259 1548 1779
+f 2052 2031 1990
+f 1440 1202 1478
+f 1428 1419 1250
+f 1428 1435 1419
+f 1428 1446 1435
+f 1934 1935 1955
+f 1560 1584 1569
+f 1610 1638 1625
+f 1638 1652 1625
+f 817 1077 999
+f 1077 285 999
+f 980 303 1017
+f 962 1412 67
+f 1494 1023 1547
+f 325 271 1270
+f 1443 1511 1496
+f 1450 1268 1527
+f 1514 1353 1441
+f 1287 1446 1428
+f 1446 1287 1457
+f 1305 2372 1477
+f 1992 1990 1991
+f 1992 1991 1971
+f 1971 1991 1955
+f 2449 1549 2418
+f 1583 1616 1610
+f 1610 1616 1638
+f 10 1396 340
+f 340 1445 81
+f 1445 962 81
+f 1790 984 1753
+f 984 2148 1753
+f 1588 1713 1770
+f 969 978 958
+f 1741 1779 1703
+f 1758 1846 1754
+f 1827 1819 1029
+f 1818 1530 1712
+f 1750 1566 2127
+f 2459 2434 2483
+f 1798 1720 1771
+f 1794 1841 1803
+f 216 1755 1810
+f 1098 1735 1748
+f 1735 1497 1748
+f 1502 2102 1601
+f 881 1502 1601
+f 1455 1839 1744
+f 1706 1709 1680
+f 1212 1741 1703
+f 1788 1969 1671
+f 1075 1074 1692
+f 951 2500 881
+f 2490 2486 2463
+f 1748 1497 1781
+f 1721 984 1840
+f 1815 1259 1741
+f 1626 1756 1837
+f 975 987 1542
+f 2230 2236 2235
+f 1772 678 734
+f 1542 1671 975
+f 1806 1772 1780
+f 678 1772 1806
+f 2218 2225 2268
+f 1828 1732 2007
+f 1526 1688 1531
+f 1752 1526 1554
+f 1844 1818 1712
+f 1823 1846 1804
+f 1781 1669 1704
+f 1721 1779 2143
+f 1770 1670 1526
+f 1497 1669 1781
+f 1098 1713 1735
+f 1742 1815 1741
+f 1526 858 1875
+f 1599 1531 1688
+f 1803 1790 1558
+f 1703 1721 1683
+f 1832 1766 957
+f 1542 1679 1671
+f 1679 1788 1671
+f 1927 1819 1827
+f 1718 1745 1739
+f 1684 1022 1839
+f 1459 1283 1299
+f 1022 1410 1418
+f 2368 2393 2326
+f 1669 1497 1776
+f 1875 858 1212
+f 1739 1745 852
+f 1964 1918 1461
+f 1356 133 1331
+f 1765 1829 1468
+f 858 1742 1741
+f 1006 1674 1021
+f 1723 1936 1935
+f 1468 1713 1098
+f 1724 1678 1476
+f 1680 1783 908
+f 1731 1543 520
+f 1683 1721 1840
+f 1467 1679 1542
+f 1812 1708 1846
+f 1679 1975 1788
+f 1713 1830 1770
+f 1803 1722 1790
+f 2301 2391 2349
+f 1713 1588 1735
+f 1836 1530 1818
+f 1837 1756 861
+f 886 571 556
+f 1181 1805 1812
+f 1706 1680 1755
+f 1677 1729 1775
+f 1776 1787 1669
+f 1526 1670 1672
+f 1727 1770 1526
+f 987 1467 1542
+f 1567 1704 1137
+f 1693 1865 1714
+f 897 1762 912
+f 1135 1697 1062
+f 1697 376 1062
+f 1543 1731 1678
+f 1793 1679 1467
+f 1777 1602 1760
+f 1846 1798 1754
+f 1835 1096 1677
+f 1033 1030 940
+f 1450 1527 1702
+f 1717 376 1697
+f 1711 1717 1697
+f 1717 165 376
+f 1840 984 1790
+f 1669 1746 1704
+f 1669 1682 1746
+f 2301 2349 2308
+f 1882 1444 1898
+f 1820 1789 1730
+f 861 1380 1566
+f 2301 2308 2266
+f 1771 1543 1691
+f 1958 1659 1651
+f 1697 1360 1711
+f 1711 1737 1717
+f 1717 1737 165
+f 1790 1753 1558
+f 1668 1696 1663
+f 1360 1702 1711
+f 1702 1707 1711
+f 1707 1737 1711
+f 1737 1751 165
+f 1444 1782 1693
+f 1716 1787 1599
+f 1744 1839 1022
+f 1898 1444 1785
+f 206 1707 1702
+f 1764 2468 1751
+f 316 1844 893
+f 893 1844 915
+f 1845 1804 1758
+f 1380 861 1756
+f 1780 670 1021
+f 1714 2172 1763
+f 1783 1558 1663
+f 1750 2127 1465
+f 1798 1771 1691
+f 1691 1543 1724
+f 1872 1910 839
+f 1737 2044 1751
+f 1751 2044 1764
+f 1757 1701 482
+f 1725 1602 1777
+f 1836 1845 1530
+f 2102 2470 1503
+f 2496 1899 544
+f 763 2484 946
+f 987 1719 1467
+f 1845 1758 1792
+f 1725 1837 1602
+f 1872 1866 1873
+f 1712 1530 1760
+f 489 1799 216
+f 1760 861 1750
+f 2068 2466 2460
+f 1696 2159 2168
+f 377 1377 1280
+f 1797 1676 1572
+f 1581 2053 1572
+f 1676 1581 1572
+f 1764 2498 2468
+f 2468 2498 1994
+f 1861 1695 1860
+f 2481 2004 2495
+f 1826 1677 1523
+f 1670 1739 852
+f 2234 2269 2253
+f 1724 1543 1678
+f 1658 2168 1791
+f 1397 1747 1719
+f 1696 2168 1658
+f 979 519 272
+f 1774 1975 1679
+f 975 1671 932
+f 1787 1716 1682
+f 1835 1826 1747
+f 2501 2469 961
+f 1810 908 1791
+f 1982 1768 191
+f 1137 1704 1825
+f 1804 1846 1758
+f 2004 2044 1737
+f 913 1969 902
+f 2498 1795 1801
+f 915 1844 1712
+f 1689 915 1712
+f 1740 1752 1541
+f 695 661 199
+f 1865 1693 1782
+f 1824 1464 1809
+f 1829 1765 1718
+f 1816 1768 1982
+f 1816 1622 1768
+f 1622 2165 1681
+f 1768 1622 1681
+f 670 1772 228
+f 1283 1459 52
+f 1785 1444 1749
+f 1675 1075 1685
+f 1567 1781 1704
+f 1858 1857 1848
+f 1526 1752 1688
+f 1791 2160 1810
+f 908 1658 1791
+f 1813 1773 1558
+f 1845 1792 1530
+f 69 376 165
+f 3 1832 1834
+f 1722 1516 1507
+f 1801 1821 1994
+f 1833 1982 2046
+f 1821 1833 2046
+f 1833 1816 1982
+f 1022 1785 1749
+f 2160 2170 1810
+f 1147 1719 1726
+f 1683 1840 1507
+f 1467 1719 1793
+f 1795 1802 1801
+f 1802 1811 1801
+f 1801 1811 1821
+f 1690 2165 1622
+f 1934 1480 1925
+f 229 1468 1091
+f 1780 2164 1742
+f 1672 1742 858
+f 1833 1417 1816
+f 1417 1622 1816
+f 1831 2165 1690
+f 1668 1663 1558
+f 1719 1747 1826
+f 1760 1750 1664
+f 1817 1690 1622
+f 1530 1792 1777
+f 948 1796 1802
+f 1796 1811 1802
+f 1515 1817 1622
+f 1695 1861 1831
+f 1783 1663 1658
+f 1749 1410 1022
+f 854 1796 948
+f 1811 1842 1833
+f 1821 1811 1833
+f 1833 1842 1417
+f 1622 1417 1515
+f 127 1804 1845
+f 1686 1626 1837
+f 1608 1690 1817
+f 1523 1775 1762
+f 127 1845 1836
+f 1812 1805 1708
+f 1523 1677 1775
+f 1780 1772 670
+f 1758 1754 1792
+f 1204 1796 854
+f 1822 1842 1811
+f 1608 1831 1690
+f 1822 1811 1796
+f 1842 1416 1417
+f 1417 1416 1515
+f 1515 1608 1817
+f 1728 1831 1608
+f 908 1783 1658
+f 127 1836 316
+f 1805 1148 1824
+f 852 1745 1672
+f 1478 1093 1928
+f 1822 1843 1842
+f 1843 959 1842
+f 1842 959 1416
+f 1728 1695 1831
+f 1728 1860 1695
+f 2346 446 2337
+f 1602 1837 861
+f 1087 1096 1835
+f 1708 1824 1809
+f 2004 1737 505
+f 1567 1748 1781
+f 520 1543 1883
+f 1760 1664 1712
+f 128 1336 72
+f 2053 1883 1543
+f 1822 180 1843
+f 1786 1608 1515
+f 929 2462 519
+f 512 2402 506
+f 1212 1703 1683
+f 1830 1829 1739
+f 2053 1543 1771
+f 1416 1769 1515
+f 1769 1786 1515
+f 1786 1728 1608
+f 1712 1808 1689
+f 1794 1558 1783
+f 1497 1735 1776
+f 1127 1567 1137
+f 1123 1748 1567
+f 36 205 1185
+f 959 1734 1416
+f 1738 1733 1541
+f 1774 1762 1974
+f 1752 1554 1541
+f 1752 1740 1688
+f 1526 1875 1554
+f 1468 1829 1830
+f 1755 908 1810
+f 1716 1599 1814
+f 1806 1780 1742
+f 2308 2349 2340
+f 1832 915 1689
+f 1713 1468 1830
+f 1814 1599 1346
+f 1832 1689 1766
+f 1022 1684 1785
+f 1093 1153 1116
+f 1672 678 1742
+f 1675 1685 1093
+f 1841 1743 1722
+f 1814 2053 1581
+f 1464 1746 1809
+f 2485 2497 2493
+f 1416 1734 1769
+f 1665 1728 1786
+f 1665 1951 1728
+f 1951 1860 1728
+f 1951 2094 1860
+f 1844 1836 1818
+f 316 1836 1844
+f 1776 1531 1787
+f 1719 1826 1793
+f 2147 1401 29
+f 2111 2121 1548
+f 1741 1259 1779
+f 1843 347 1834
+f 1843 1734 959
+f 1766 1769 1734
+f 957 1766 1734
+f 1766 1786 1769
+f 1766 1689 1786
+f 1689 1665 1786
+f 1754 1691 1777
+f 1507 1840 1790
+f 1761 1470 1461
+f 1523 1679 1793
+f 1091 1468 1098
+f 1820 1730 1838
+f 1843 1834 1734
+f 1808 1951 1665
+f 1588 1727 1531
+f 893 915 1832
+f 1523 1774 1679
+f 272 2488 710
+f 1093 1116 1675
+f 2340 2349 2348
+f 1832 1734 1834
+f 1832 957 1734
+f 1951 1808 2094
+f 1685 1692 1505
+f 1043 295 698
+f 2143 1779 2121
+f 1689 1808 1665
+f 1693 1714 1763
+f 1738 2157 1516
+f 1114 1921 236
+f 1268 1333 1520
+f 1149 1108 431
+f 508 2144 1912
+f 1957 1108 1537
+f 431 1108 1957
+f 1018 1108 2167
+f 1338 1957 1681
+f 2163 1957 1338
+f 1983 1390 2093
+f 30 557 37
+f 1714 2173 2172
+f 1983 1984 1390
+f 1984 2065 1390
+f 884 1762 897
+f 2065 1984 1214
+f 1950 1974 1762
+f 884 1950 1762
+f 2012 1698 1861
+f 1214 2116 803
+f 1950 1938 1974
+f 1938 1967 1974
+f 1900 1761 1461
+f 865 1929 884
+f 884 1929 1950
+f 2062 2071 2042
+f 919 1985 1732
+f 1593 502 2146
+f 1995 1213 2098
+f 1522 2476 1651
+f 2174 1849 2175
+f 1480 1989 1499
+f 1929 1938 1950
+f 1605 2058 1574
+f 2097 1605 2133
+f 1912 2014 1886
+f 2092 2082 2083
+f 206 1930 505
+f 2101 2100 2092
+f 2073 2101 2092
+f 839 1910 865
+f 1910 1901 1929
+f 865 1910 1929
+f 1967 1788 1975
+f 2073 2092 2063
+f 2101 1593 2100
+f 2015 1876 1698
+f 1853 1884 2014
+f 1831 1698 2165
+f 1316 273 81
+f 1901 1920 1929
+f 1929 1920 1938
+f 1920 1968 1967
+f 1938 1920 1967
+f 1849 2174 1700
+f 2173 1700 2174
+f 2062 2072 2091
+f 803 2467 2059
+f 2239 1736 2240
+f 1505 1357 1685
+f 1358 1686 1476
+f 1967 1968 1788
+f 1968 1969 1788
+f 2065 2110 2156
+f 2065 1214 2110
+f 2110 1214 503
+f 273 2093 1018
+f 273 1983 2093
+f 532 1886 2155
+f 2034 2021 1947
+f 216 1810 585
+f 1912 543 2014
+f 1390 2051 1537
+f 1872 1873 1910
+f 1984 2045 1214
+f 597 1912 1886
+f 1593 2146 2100
+f 2071 2062 2090
+f 2034 2046 1982
+f 2034 1947 2046
+f 1214 2045 2116
+f 1873 1887 1910
+f 1887 1901 1910
+f 1562 1447 1106
+f 2163 431 1957
+f 1948 1972 1936
+f 1972 1948 1992
+f 2014 2015 2013
+f 1853 2014 2013
+f 1550 1884 1853
+f 1947 2468 1994
+f 1355 1550 2154
+f 1355 1884 1550
+f 2081 2108 2128
+f 2024 1965 1492
+f 2024 2032 1965
+f 2116 1604 803
+f 1901 1911 1920
+f 1939 1968 1920
+f 1911 1939 1920
+f 872 1626 1666
+f 2062 2091 2120
+f 1819 1927 1759
+f 1021 1674 1780
+f 872 1673 1756
+f 1550 501 2171
+f 1378 1550 2171
+f 2146 2162 2145
+f 1358 482 192
+f 2109 2120 2119
+f 1866 1872 2227
+f 1391 2012 1860
+f 2136 2137 2161
+f 2162 1661 236
+f 1887 1894 1901
+f 1901 1894 1911
+f 505 1707 206
+f 2120 2137 2136
+f 2142 2164 1674
+f 1860 2012 1861
+f 1894 1939 1911
+f 2080 2060 2118
+f 2162 236 508
+f 2164 1815 1742
+f 1018 2093 1537
+f 2154 1378 2161
+f 2041 2098 2491
+f 2043 2042 2032
+f 1108 1018 1537
+f 1465 2094 1808
+f 502 1643 1661
+f 2467 1618 1656
+f 2119 2136 2135
+f 2119 2108 2071
+f 878 1183 1195
+f 2101 1594 1593
+f 2033 2370 2063
+f 2482 2491 2098
+f 1282 2406 1275
+f 2003 1948 1956
+f 2043 2032 2024
+f 2025 2043 2024
+f 2154 1550 1378
+f 1795 2498 1764
+f 2142 1548 2164
+f 2431 2454 2422
+f 1981 2011 1993
+f 2349 2391 2362
+f 502 2162 2146
+f 2025 2024 2360
+f 2129 2120 2091
+f 1732 1985 2007
+f 2171 1308 209
+f 1930 1995 2041
+f 1390 1238 2051
+f 1866 1878 1887
+f 1878 1894 1887
+f 1965 2032 2011
+f 874 2480 2492
+f 2071 2108 2069
+f 1358 1731 482
+f 430 2021 2034
+f 1965 2003 1964
+f 1855 1889 831
+f 1668 1773 2150
+f 1390 2156 1238
+f 898 869 1903
+f 2391 2407 2362
+f 2121 2111 2074
+f 1548 1259 2164
+f 2099 2129 2091
+f 1550 1853 501
+f 1853 1852 501
+f 952 2017 969
+f 2085 2121 2074
+f 2130 2006 1391
+f 2144 1367 543
+f 2100 2146 2099
+f 1545 1319 113
+f 1903 1922 898
+f 1922 1931 898
+f 585 2170 1641
+f 2007 2017 952
+f 2017 2074 969
+f 1558 1753 1813
+f 837 2005 1517
+f 2005 2006 2130
+f 1532 1474 1528
+f 2003 1981 1948
+f 2070 2071 2069
+f 1922 919 1931
+f 2017 2085 2074
+f 2085 2104 2121
+f 2100 2099 2082
+f 2156 2110 2034
+f 505 2474 2004
+f 1903 871 1922
+f 1922 1952 919
+f 919 1952 1985
+f 1985 2001 2007
+f 2001 2036 2017
+f 2007 2001 2017
+f 2017 2036 2085
+f 2036 2047 2085
+f 2047 2075 2085
+f 2075 2104 2085
+f 1948 1993 2023
+f 2400 2422 2407
+f 2011 2070 1993
+f 2033 2043 2025
+f 2012 2015 1698
+f 1876 1338 2165
+f 871 1940 1922
+f 1985 1976 2001
+f 2121 2104 2143
+f 1051 1413 1456
+f 2358 1362 2379
+f 1859 1789 1870
+f 2090 2109 2071
+f 1405 1398 1885
+f 1886 1884 1355
+f 1922 1960 1952
+f 1952 1960 1985
+f 1960 1976 1985
+f 1956 1948 1936
+f 2135 209 2128
+f 2157 1875 1212
+f 2160 2168 2169
+f 1900 1461 1918
+f 2001 2018 2036
+f 2075 2086 2104
+f 2111 2142 2103
+f 1937 1956 1936
+f 2023 2070 2061
+f 2135 2128 2108
+f 2042 2071 2011
+f 2138 413 2383
+f 2033 2072 2043
+f 1922 1940 1960
+f 2070 2069 2061
+f 2069 2108 2061
+f 2108 2119 2135
+f 1855 1904 1889
+f 1889 1904 871
+f 871 1904 1940
+f 1976 2018 2001
+f 2036 2018 2047
+f 2122 2143 2104
+f 216 1642 489
+f 2148 984 2143
+f 1975 1974 1967
+f 2157 1683 1516
+f 1614 1593 1594
+f 2269 2270 2276
+f 1926 2147 29
+f 2082 2091 2072
+f 430 503 2059
+f 1904 1905 1940
+f 1940 1961 1960
+f 1961 1976 1960
+f 2087 2086 2075
+f 2065 2156 1390
+f 1820 1838 1900
+f 534 1308 837
+f 2167 273 1018
+f 831 1850 1855
+f 2019 2037 2018
+f 2018 2037 2047
+f 2037 2075 2047
+f 2086 2095 2104
+f 2095 2122 2104
+f 2122 2148 2143
+f 1926 1213 1995
+f 1405 1885 1761
+f 2006 2013 2012
+f 2211 2233 2216
+f 1855 1890 1904
+f 1904 1895 1905
+f 1905 1932 1940
+f 1961 1977 1976
+f 1976 1986 2018
+f 2484 2476 1518
+f 1870 1411 1859
+f 1548 2142 2111
+f 1904 1890 1895
+f 1895 1932 1905
+f 1940 1932 1961
+f 1976 1977 1986
+f 1986 2008 2018
+f 2018 2008 2019
+f 2087 2075 2037
+f 2087 2095 2086
+f 2094 1391 1860
+f 1852 1853 2006
+f 1853 2013 2006
+f 929 979 850
+f 1855 1874 1890
+f 2008 2028 2019
+f 1993 2070 2023
+f 1705 1799 1998
+f 1491 2147 206
+f 1851 1856 1855
+f 1895 1890 1874
+f 2038 2019 2028
+f 2038 2048 2037
+f 2019 2038 2037
+f 2048 2067 2087
+f 2037 2048 2087
+f 2087 2067 2095
+f 2095 2149 2122
+f 2149 2148 2122
+f 1308 2005 837
+f 209 1308 1387
+f 1601 2102 1927
+f 254 170 201
+f 1800 1403 1763
+f 1510 1346 1740
+f 870 871 1903
+f 1919 1650 1619
+f 2148 1667 1753
+f 1932 1923 1961
+f 1977 1953 1986
+f 2067 2112 2095
+f 2112 2149 2095
+f 2148 2149 1667
+f 2422 2421 2407
+f 1926 2026 1213
+f 1912 2144 543
+f 2128 1387 2153
+f 1733 1510 1740
+f 990 853 2489
+f 503 1214 803
+f 1921 431 2163
+f 2146 2145 2129
+f 2144 1921 2163
+f 1855 1856 1874
+f 1895 1923 1932
+f 1923 1941 1961
+f 1961 1941 1977
+f 2048 2076 2067
+f 2076 2113 2067
+f 2067 2113 2112
+f 1723 1900 1937
+f 1870 1900 1723
+f 1367 2163 1338
+f 520 1346 1510
+f 1698 1831 1861
+f 1984 1919 2045
+f 1895 1891 1923
+f 2008 1986 2028
+f 1948 1981 1993
+f 1883 1346 520
+f 1883 1814 1346
+f 1930 206 2147
+f 2499 2486 1447
+f 1891 1906 1923
+f 1923 1953 1941
+f 1953 1977 1941
+f 1953 1987 1986
+f 2113 2123 2112
+f 2123 2149 2112
+f 1387 1308 1226
+f 1599 1688 1346
+f 2093 1390 1537
+f 2003 2011 1981
+f 1987 2028 1986
+f 2038 2049 2048
+f 2048 2049 2076
+f 1813 1667 2149
+f 2123 1813 2149
+f 1461 1469 1964
+f 1757 1510 1743
+f 505 1930 1999
+f 2223 1784 1789
+f 1532 1522 1651
+f 1906 1913 1923
+f 1913 1943 1923
+f 1943 1942 1923
+f 1923 1942 1953
+f 1942 1987 1953
+f 1308 1852 2005
+f 2053 1814 1883
+f 1733 1740 1541
+f 2154 1886 1355
+f 1503 1528 1474
+f 1874 1879 1895
+f 1895 1879 1891
+f 2076 2124 2113
+f 2113 2124 2123
+f 1896 1891 1879
+f 1891 1896 1906
+f 1942 1962 1987
+f 1962 2009 2028
+f 1987 1962 2028
+f 2009 2038 2028
+f 2109 2119 2071
+f 1918 1956 1937
+f 1851 1864 1856
+f 1896 1897 1906
+f 1906 1897 1913
+f 1943 1962 1942
+f 2049 2077 2076
+f 2124 2125 2123
+f 1930 2147 1926
+f 1902 1894 1878
+f 482 1510 1757
+f 2129 2137 2120
+f 503 803 2059
+f 1847 1857 1851
+f 1851 1857 1864
+f 2039 2038 2009
+f 2038 2039 2049
+f 2076 2077 2124
+f 2150 1813 2123
+f 482 520 1510
+f 1994 1821 2046
+f 2044 2004 1764
+f 1864 1867 1856
+f 1867 1874 1856
+f 1897 1944 1913
+f 1943 1944 1962
+f 2124 2126 2125
+f 2150 2123 2125
+f 2099 2146 2129
+f 2041 1995 2098
+f 1605 1641 2151
+f 1847 1959 1857
+f 1874 1867 1879
+f 1913 1944 1943
+f 1944 1963 1962
+f 2077 2096 2124
+f 2096 2126 2124
+f 2126 2150 2125
+f 941 1650 1919
+f 2135 2136 209
+f 1884 1886 2014
+f 2049 2029 2077
+f 1388 2127 1389
+f 1389 2127 1566
+f 1930 1926 1995
+f 941 1919 1316
+f 2110 503 430
+f 1867 1880 1879
+f 1879 1880 1896
+f 1897 1907 1944
+f 1963 1978 1962
+f 1962 1978 2009
+f 2039 2029 2049
+f 2077 2078 2096
+f 822 823 827
+f 2166 1668 2150
+f 81 941 1316
+f 2204 2216 2203
+f 2011 2071 2070
+f 1880 1892 1896
+f 1892 1907 1897
+f 1896 1892 1897
+f 1907 1914 1944
+f 1978 2010 2009
+f 2010 2039 2009
+f 1688 1740 1346
+f 1789 1820 1870
+f 2130 1391 2094
+f 1944 1945 1963
+f 2029 2078 2077
+f 1767 2150 2126
+f 1767 2166 2150
+f 803 2022 2467
+f 1503 1927 2102
+f 1914 1954 1944
+f 1944 1954 1945
+f 1963 1970 1978
+f 2078 2105 2096
+f 2105 2126 2096
+f 1965 2011 2003
+f 192 1626 1358
+f 2101 1559 1594
+f 1930 2041 1999
+f 1698 1876 2165
+f 1398 1871 891
+f 2165 1338 1681
+f 1970 2010 1978
+f 2010 2030 2029
+f 2039 2010 2029
+f 2030 2055 2078
+f 2029 2030 2078
+f 1849 1848 2175
+f 1871 1862 891
+f 543 2015 2014
+f 1857 1858 1864
+f 1864 1858 1867
+f 1963 1945 1970
+f 2055 2088 2078
+f 2078 2088 2105
+f 2105 2131 2126
+f 2126 2131 1767
+f 2063 2083 2033
+f 2161 2171 209
+f 2032 2042 2011
+f 1813 2150 1773
+f 1914 1908 1954
+f 1970 1979 2010
+f 2088 2131 2105
+f 2015 543 1876
+f 1694 1692 1048
+f 1395 2207 1859
+f 1395 1393 2207
+f 1730 1784 1736
+f 2500 2466 2470
+f 1709 1701 1757
+f 1945 1979 1970
+f 2030 2050 2055
+f 2350 2317 2286
+f 2154 2155 1886
+f 871 860 1889
+f 2161 209 2136
+f 2497 2463 2493
+f 2190 2204 2203
+f 1800 2179 1404
+f 2477 2469 1385
+f 1385 1715 2477
+f 2128 209 1387
+f 1858 1868 1867
+f 1867 1881 1880
+f 1893 1892 1880
+f 1881 1893 1880
+f 1893 1907 1892
+f 1907 1908 1914
+f 1954 1979 1945
+f 1979 1980 2010
+f 2131 2159 1767
+f 1765 93 339
+f 1761 1877 1405
+f 523 1347 515
+f 1541 2157 1738
+f 2144 2163 1367
+f 1380 1389 1566
+f 2317 2392 2316
+f 1994 2498 1801
+f 1867 1868 1881
+f 1980 2050 2030
+f 2010 1980 2030
+f 2050 2089 2055
+f 2055 2089 2088
+f 2088 2114 2131
+f 1538 1651 1659
+f 2145 2155 2129
+f 2140 29 1928
+f 2370 2033 2025
+f 2252 2239 2240
+f 2239 2252 1862
+f 2392 2391 2316
+f 2469 2501 1385
+f 2477 1715 1710
+f 502 1614 1643
+f 2438 1227 2431
+f 1915 1907 1893
+f 1915 1908 1907
+f 1954 1908 1979
+f 1908 1988 1979
+f 1979 1988 1980
+f 2114 2159 2131
+f 2155 2154 2129
+f 508 1966 2144
+f 872 1756 1626
+f 1710 1715 1505
+f 236 1966 508
+f 2272 2284 1398
+f 2325 2355 2319
+f 1548 2121 1779
+f 1532 1528 1522
+f 1980 2056 2050
+f 2050 2056 2089
+f 2013 2015 2012
+f 1964 2003 1956
+f 2006 2012 1391
+f 1565 1927 1503
+f 2244 2243 2226
+f 5 1715 1385
+f 1858 1848 1868
+f 1915 1946 1908
+f 1946 1988 1908
+f 1980 2020 2056
+f 2115 2159 2114
+f 2092 2083 2063
+f 1398 2284 1687
+f 2162 2155 2145
+f 519 2475 2488
+f 2158 5 1385
+f 5 1505 1715
+f 1692 1694 1505
+f 1988 2020 1980
+f 2115 2169 2159
+f 2169 2168 2159
+f 2083 2082 2072
+f 1316 1984 1983
+f 1488 1619 1650
+f 2083 2072 2033
+f 2361 1210 1233
+f 1933 1946 1915
+f 2056 2079 2089
+f 2088 2115 2114
+f 2099 2091 2082
+f 2162 532 2155
+f 1852 2006 2005
+f 2023 2061 2052
+f 2176 2184 2175
+f 2162 985 532
+f 1909 1893 1881
+f 1909 1915 1893
+f 1988 2040 2020
+f 2040 2056 2020
+f 2089 2079 2088
+f 2088 2079 2115
+f 1782 1444 1882
+f 1216 1215 2320
+f 867 1939 1894
+f 867 903 1939
+f 1372 2398 1379
+f 1863 504 2027
+f 2158 1385 504
+f 1868 1782 1881
+f 1909 1933 1915
+f 2040 1988 1946
+f 1481 2024 1492
+f 2120 2136 2119
+f 1522 1528 1518
+f 1871 1398 1405
+f 1221 1408 1399
+f 1357 5 2158
+f 2179 1800 1763
+f 1868 1865 1782
+f 1882 1881 1782
+f 1882 1909 1881
+f 2040 2057 2056
+f 2106 2079 2056
+f 2057 2106 2056
+f 2106 2132 2079
+f 2132 2115 2079
+f 2115 2132 2169
+f 532 985 597
+f 2092 2100 2082
+f 1210 1221 1399
+f 1399 1233 1210
+f 2130 2002 1517
+f 1849 1865 1868
+f 1933 2040 1946
+f 52 1269 30
+f 1667 1813 1753
+f 1997 1380 1673
+f 940 1008 1088
+f 1947 1994 2046
+f 1882 1916 1909
+f 1924 1933 1909
+f 1533 2040 1933
+f 1533 1534 2040
+f 2058 2040 1534
+f 2058 2057 2040
+f 1238 191 1768
+f 1997 1389 1380
+f 1875 1541 1554
+f 1854 504 1863
+f 1854 2158 504
+f 2396 1275 2406
+f 2426 2443 153
+f 1916 1924 1909
+f 1925 1935 1934
+f 1870 1723 1426
+f 2058 2097 2057
+f 2097 2106 2057
+f 2132 2151 2169
+f 2151 2160 2169
+f 1106 1635 1562
+f 1957 1768 1681
+f 1957 2051 1768
+f 526 535 33
+f 1614 1594 1609
+f 2233 2229 2216
+f 2496 2027 2084
+f 2496 1863 2027
+f 2117 1854 1863
+f 2016 2158 1854
+f 2016 1504 1357
+f 2158 2016 1357
+f 1114 236 1661
+f 2129 2154 2137
+f 2133 2106 2097
+f 2491 1999 2041
+f 2051 1238 1768
+f 2061 2108 2081
+f 2189 2195 2186
+f 2348 2349 2362
+f 1701 192 482
+f 505 1737 1707
+f 2133 2132 2106
+f 2132 2133 2151
+f 2151 2170 2160
+f 502 1661 2162
+f 1998 1389 1997
+f 2297 2352 2329
+f 2352 2364 2329
+f 2394 2414 2364
+f 2352 2394 2364
+f 2402 512 2415
+f 2255 2254 2243
+f 2446 1365 2456
+f 2271 2282 2298
+f 846 2283 2264
+f 2293 2310 2318
+f 2254 2295 2294
+f 2283 2290 2278
+f 2270 2294 2293
+f 2423 2455 2400
+f 2281 2287 2267
+f 2190 2191 2204
+f 2271 2263 2282
+f 2334 2329 2364
+f 2424 2432 2409
+f 2282 2263 2298
+f 1409 1659 1958
+f 2263 2302 2298
+f 2297 2329 2296
+f 1256 446 2346
+f 1958 2502 2478
+f 2437 2399 2444
+f 263 2366 2359
+f 849 827 823
+f 2311 2325 2290
+f 2499 2379 2434
+f 2446 2456 2423
+f 947 2358 2379
+f 2499 947 2379
+f 2205 2195 2212
+f 2245 2237 2227
+f 2245 2256 2237
+f 2256 2263 2271
+f 556 571 2305
+f 1528 2068 1518
+f 2424 2439 2432
+f 2302 2352 2297
+f 1866 2237 826
+f 2248 2242 2211
+f 2334 2364 2363
+f 2235 2244 2226
+f 2255 2295 2254
+f 2329 2324 2296
+f 2439 2447 1973
+f 2329 2334 2324
+f 2409 2432 2414
+f 2293 2318 2276
+f 866 2425 2416
+f 1487 1493 2372
+f 2237 2231 2230
+f 2415 512 17
+f 2035 1236 26
+f 921 2138 688
+f 2491 2482 2462
+f 6 181 197
+f 2481 948 1795
+f 2138 2383 2382
+f 2377 2394 2352
+f 2377 506 2394
+f 2394 506 2402
+f 2401 2402 2415
+f 2394 2402 2401
+f 2318 2326 2276
+f 2439 2457 2432
+f 2298 2302 2297
+f 2244 2249 2243
+f 2404 1100 2382
+f 2238 2245 2227
+f 2245 2257 2256
+f 2257 2263 2256
+f 2324 2334 2328
+f 2257 2289 2263
+f 2289 2302 2263
+f 2236 2231 2250
+f 2138 2382 688
+f 2383 2404 2382
+f 1100 2404 2343
+f 2353 2352 2302
+f 2353 2377 2352
+f 2237 2230 2220
+f 2335 2355 2325
+f 2308 2340 2315
+f 2253 2269 2276
+f 2311 2335 2325
+f 2439 2424 511
+f 2268 2267 2248
+f 2383 413 2404
+f 123 971 832
+f 2234 2243 2269
+f 2225 2213 2234
+f 2219 2213 2225
+f 2195 2196 2212
+f 1544 2418 1549
+f 413 866 2404
+f 2404 866 2416
+f 2416 2417 2404
+f 2404 2417 2343
+f 2415 2409 2401
+f 2196 2219 2212
+f 2268 2248 2218
+f 2206 2214 2197
+f 2417 2332 2343
+f 2343 2332 832
+f 2330 2302 2289
+f 2330 2353 2302
+f 2453 2454 515
+f 2218 2248 2217
+f 2218 2217 2205
+f 2276 2281 2268
+f 2178 2197 2177
+f 2197 2189 2177
+f 2332 2066 832
+f 832 2066 123
+f 2231 2236 2230
+f 669 950 1144
+f 2217 2211 2199
+f 1216 1209 1217
+f 2066 2365 123
+f 2230 2226 2214
+f 2290 2325 2304
+f 2325 2319 2304
+f 2217 2248 2211
+f 2191 2192 2199
+f 510 525 2035
+f 2417 1917 2332
+f 2332 1917 2066
+f 2408 2413 2341
+f 2248 2267 2242
+f 2326 2333 2281
+f 1340 2365 2066
+f 2440 1302 1340
+f 2226 2230 2235
+f 1153 1163 1116
+f 2431 2455 2438
+f 2416 2425 2417
+f 2495 2474 2462
+f 2290 2304 2277
+f 825 2227 1872
+f 151 239 1038
+f 9 151 1038
+f 545 928 2381
+f 2440 2406 1384
+f 928 1596 2381
+f 2186 2188 2185
+f 2456 26 1888
+f 2287 2333 2262
+f 2425 2342 2417
+f 2342 1917 2417
+f 1917 877 2066
+f 2336 1340 2066
+f 2336 2440 1340
+f 2328 2351 2327
+f 825 2238 2227
+f 2351 2368 2327
+f 1222 2388 1211
+f 678 756 734
+f 428 263 1343
+f 2188 2191 2190
+f 2341 2376 2333
+f 2066 877 2336
+f 2290 2277 2278
+f 739 634 592
+f 675 304 14
+f 2384 675 14
+f 2199 2211 2204
+f 2191 2199 2204
+f 2322 2318 2310
+f 2287 2262 2233
+f 2185 2188 2184
+f 2386 2425 845
+f 2384 572 675
+f 1128 123 2365
+f 832 971 2343
+f 2188 2186 2191
+f 2185 2184 2176
+f 2345 1917 2342
+f 2345 877 1917
+f 2336 2406 2440
+f 971 1100 2343
+f 2299 2289 2257
+f 2299 2303 2289
+f 2249 2255 2243
+f 506 513 512
+f 2437 955 1219
+f 1587 2398 1324
+f 877 2396 2336
+f 2336 2396 2406
+f 2463 2479 879
+f 2376 2412 2350
+f 2281 2267 2268
+f 2303 2330 2289
+f 624 635 159
+f 1996 2356 1561
+f 2449 2436 1996
+f 2356 2054 2451
+f 928 2398 1587
+f 2333 2350 2262
+f 2035 26 2456
+f 2346 2342 2425
+f 2346 2345 2342
+f 1544 2380 2418
+f 2412 2392 2350
+f 622 509 1151
+f 2436 2054 1996
+f 545 2451 928
+f 2326 2341 2333
+f 2346 2425 2386
+f 1365 2035 2456
+f 2369 2377 2353
+f 2369 506 2377
+f 2451 900 928
+f 900 2398 928
+f 1235 1888 1244
+f 2337 2345 2346
+f 877 772 2396
+f 772 1275 2396
+f 2432 2446 2414
+f 2294 2295 2310
+f 2369 2330 828
+f 2418 2419 2436
+f 2450 2429 2436
+f 2436 2429 2054
+f 2490 2494 1656
+f 1321 155 2338
+f 1256 2346 2386
+f 2448 877 2345
+f 877 2448 772
+f 2446 2423 2414
+f 2351 2334 2363
+f 2243 2254 2269
+f 2380 2419 2418
+f 2419 2450 2436
+f 2283 2278 2264
+f 822 2197 823
+f 1008 1759 1565
+f 2448 2345 2337
+f 2270 2293 2276
+f 2323 2324 2328
+f 2429 1012 2054
+f 2226 2243 2213
+f 2395 325 772
+f 2370 2367 2380
+f 2054 2435 2451
+f 2435 2397 2451
+f 2451 2397 900
+f 1774 1974 1975
+f 2305 2290 2283
+f 846 2305 2283
+f 2320 1215 2285
+f 2139 2448 2337
+f 2448 2395 772
+f 1232 1231 1216
+f 2272 2285 2284
+f 2367 2371 2380
+f 2371 2405 2380
+f 2380 2405 2419
+f 2419 2429 2450
+f 2429 176 1012
+f 2397 2373 900
+f 2373 2398 900
+f 2373 1379 2398
+f 2372 1500 1508
+f 1133 1303 1142
+f 2252 2273 2272
+f 891 2252 2272
+f 2419 2405 2429
+f 2405 2430 2429
+f 2429 2430 176
+f 2189 2186 2181
+f 2212 2219 2218
+f 2312 2139 2337
+f 2139 2384 2448
+f 2448 2384 2395
+f 899 855 843
+f 2272 2273 2285
+f 2331 2303 2299
+f 176 2435 2054
+f 1012 176 2054
+f 2177 2185 2176
+f 2218 2219 2225
+f 1216 1220 1215
+f 2378 2139 2312
+f 2384 14 2395
+f 2324 2295 2255
+f 2240 2273 2252
+f 2371 2387 2405
+f 2410 2430 2405
+f 2430 2442 176
+f 2435 2344 2397
+f 2397 2344 2373
+f 2456 1888 2455
+f 2242 2267 2233
+f 2233 2262 2229
+f 2378 2384 2139
+f 2323 2310 2295
+f 2323 2322 2310
+f 2240 2274 2273
+f 974 841 990
+f 2490 1447 2486
+f 2387 2410 2405
+f 2442 2141 176
+f 2344 1778 2373
+f 972 1379 2373
+f 1778 972 2373
+f 1379 972 428
+f 1211 2437 1223
+f 1228 1215 1220
+f 702 2378 2312
+f 17 518 2415
+f 1888 26 1244
+f 2324 2323 2295
+f 2305 2311 2290
+f 2307 2285 2273
+f 2274 2307 2273
+f 2307 2320 2285
+f 2369 531 506
+f 2435 2258 2344
+f 2296 2324 2288
+f 1233 1217 2361
+f 2360 2371 2367
+f 2410 2442 2430
+f 176 2141 2258
+f 176 2258 2435
+f 539 2331 66
+f 2350 2392 2317
+f 2268 2225 2253
+f 1508 1500 2371
+f 2360 1508 2371
+f 2371 1500 2387
+f 972 2366 428
+f 1626 1686 1358
+f 1759 1807 1819
+f 2277 2257 2245
+f 2277 2299 2257
+f 1784 2228 1736
+f 2265 2240 1736
+f 2228 2265 1736
+f 2265 2274 2240
+f 1209 2320 2307
+f 2320 1209 1216
+f 1555 1584 1560
+f 2387 1500 2372
+f 2410 2420 2442
+f 2433 972 1778
+f 2433 2366 972
+f 955 522 1225
+f 2339 2307 2274
+f 2372 1493 2387
+f 2411 2420 2410
+f 2420 954 2442
+f 2442 954 2141
+f 2344 2433 1778
+f 2205 2212 2218
+f 2328 2334 2351
+f 2394 2401 2414
+f 2250 2256 2271
+f 2339 1209 2307
+f 2328 2322 2323
+f 866 845 2425
+f 3 316 893
+f 2387 2411 2410
+f 2441 2141 954
+f 2141 2441 2258
+f 2354 2433 2344
+f 2254 2294 2270
+f 2269 2254 2270
+f 863 2305 846
+f 2441 2354 2258
+f 2258 2354 2344
+f 2319 2355 51
+f 2223 2228 1784
+f 1493 2411 2387
+f 1560 2449 1555
+f 2288 2324 2255
+f 825 2251 2238
+f 2251 2245 2238
+f 1299 84 1312
+f 2246 2265 2228
+f 2313 2274 2265
+f 2313 2339 2274
+f 2251 2277 2245
+f 2319 51 2331
+f 891 1862 2252
+f 2443 954 2420
+f 2443 2441 954
+f 511 2447 2439
+f 2242 2233 2211
+f 188 15 814
+f 2443 2426 2441
+f 2426 2354 2441
+f 2306 2403 2433
+f 2433 2403 2366
+f 539 2303 2331
+f 2246 2228 2223
+f 1030 1819 1807
+f 2354 2306 2433
+f 2413 2412 2376
+f 2438 2455 1888
+f 1848 1857 2176
+f 2207 2208 2223
+f 2208 2246 2223
+f 1209 2339 1217
+f 2339 2361 1217
+f 1221 1210 2388
+f 554 109 78
+f 386 1375 95
+f 2327 2326 2318
+f 2179 2182 1393
+f 2182 2208 1393
+f 1393 2208 2207
+f 2361 2399 2388
+f 2388 2399 1211
+f 2306 2354 2426
+f 2403 2359 2366
+f 2214 2226 2213
+f 2268 2253 2276
+f 889 2200 2179
+f 2200 2182 2179
+f 2200 2221 2182
+f 2221 2208 2182
+f 2314 2265 2246
+f 2314 2313 2265
+f 2339 2374 2361
+f 2478 2434 2379
+f 2205 2217 2199
+f 2208 2259 2246
+f 2259 2275 2246
+f 2314 2321 2313
+f 2313 2347 2339
+f 2347 2374 2339
+f 2374 2399 2361
+f 153 154 2426
+f 154 2306 2426
+f 2385 2359 2403
+f 2221 2259 2208
+f 2306 2357 2403
+f 2357 2385 2403
+f 2237 2256 2231
+f 2172 2180 889
+f 2180 2200 889
+f 2200 2201 2221
+f 2246 2291 2314
+f 2374 2444 2399
+f 571 555 2311
+f 2192 2205 2199
+f 2173 2180 2172
+f 2279 2246 2275
+f 2279 2291 2246
+f 2292 2314 2291
+f 2321 2362 2313
+f 2362 2347 2313
+f 2347 2389 2374
+f 2444 955 2437
+f 2292 2291 2279
+f 2452 2444 2374
+f 2054 2356 1996
+f 2338 2306 154
+f 2186 2192 2191
+f 2193 2201 2200
+f 2259 2221 2201
+f 2247 2259 2201
+f 2452 955 2444
+f 2278 2277 2251
+f 2338 2357 2306
+f 2181 2186 2185
+f 2276 2326 2281
+f 2432 2457 2446
+f 2198 2201 2193
+f 2198 2232 2201
+f 2232 2247 2201
+f 2389 2452 2374
+f 2452 1630 955
+f 1403 1749 1444
+f 1555 1996 1561
+f 2357 2427 2385
+f 2385 2428 230
+f 2409 2415 2424
+f 2304 2331 2299
+f 2193 2200 2180
+f 2445 2452 2389
+f 1565 1759 1927
+f 2380 1544 2370
+f 2338 2427 2357
+f 2427 2428 2385
+f 230 222 253
+f 2202 2198 2193
+f 2202 2209 2198
+f 2209 2241 2198
+f 2241 2232 2198
+f 2266 2275 2259
+f 2365 1340 1128
+f 2415 518 2424
+f 2338 170 2427
+f 170 2428 2427
+f 2181 2185 2177
+f 2196 2195 2189
+f 2183 2193 2180
+f 2453 1630 2452
+f 2197 2214 2189
+f 2401 2409 2414
+f 822 2220 2197
+f 1210 2361 2388
+f 2187 2193 2183
+f 2187 2202 2193
+f 2266 2279 2275
+f 2279 2300 2292
+f 2375 2347 2362
+f 2375 2390 2347
+f 2390 2389 2347
+f 2453 2452 2445
+f 1347 1630 2453
+f 1630 1347 522
+f 2220 2206 2197
+f 2262 2350 2286
+f 170 254 2428
+f 2457 1973 2446
+f 1973 1365 2446
+f 2174 2183 2180
+f 2194 2202 2187
+f 2222 2241 2209
+f 2222 2260 2241
+f 2266 2259 2247
+f 2390 2445 2389
+f 2264 2251 825
+f 2363 2368 2351
+f 2326 2393 2341
+f 1855 1850 1851
+f 2210 2209 2202
+f 2210 2222 2209
+f 2261 2260 2222
+f 2280 2279 2266
+f 2280 2300 2279
+f 251 263 2359
+f 2277 2304 2299
+f 2220 2230 2206
+f 2202 2194 2210
+f 2213 2243 2234
+f 2328 2327 2322
+f 2294 2310 2293
+f 2214 2196 2189
+f 2196 2213 2219
+f 2224 2222 2210
+f 2421 2390 2375
+f 2206 2230 2214
+f 2194 2203 2210
+f 2224 2261 2222
+f 2421 2445 2390
+f 2322 2327 2318
+f 2393 2408 2341
+f 1365 1973 510
+f 2216 2210 2203
+f 2216 2224 2210
+f 2266 2308 2280
+f 2280 2308 2300
+f 2407 2421 2375
+f 2175 2183 2174
+f 2194 2190 2203
+f 2454 2445 2421
+f 522 1347 523
+f 2456 2455 2423
+f 823 2197 2178
+f 2281 2333 2287
+f 2188 2187 2183
+f 2188 2190 2194
+f 2187 2188 2194
+f 2308 2315 2300
+f 2407 2375 2362
+f 2443 2420 2503
+f 2420 2411 2503
+f 2411 1493 2503
+f 1493 1487 2503
+f 1487 1318 2503
+f 1318 1320 2503
+f 1320 2443 2503
diff --git a/demo/model3D/files/Duck.glb b/demo/model3D/files/Duck.glb
new file mode 100644
index 0000000000000000000000000000000000000000..217170d2bd67051270be974292dc3b834eefe206
Binary files /dev/null and b/demo/model3D/files/Duck.glb differ
diff --git a/demo/model3D/files/Fox.gltf b/demo/model3D/files/Fox.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..ff3115c05d97ac673c511affe1b3fecc64e1c3d3
--- /dev/null
+++ b/demo/model3D/files/Fox.gltf
@@ -0,0 +1,1777 @@
+{
+ "asset": {
+ "copyright": "CC-BY 4.0 Model by PixelMannen https://opengameart.org/content/fox-and-shiba and @tomkranis https://sketchfab.com/3d-models/low-poly-fox-by-pixelmannen-animated-371dea88d7e04a76af5763f2a36866bc and @AsoboStudio with @scurest https://github.com/KhronosGroup/glTF-Sample-Models/pull/150#issuecomment-406300118",
+ "version": "2.0"
+ },
+ "accessors": [
+ {
+ "bufferView": 0,
+ "componentType": 5126,
+ "count": 1728,
+ "type": "VEC3",
+ "byteOffset": 0,
+ "min": [
+ -12.592718124389648,
+ -0.12174476683139801,
+ -88.09500122070312
+ ],
+ "max": [
+ 12.592718124389648,
+ 78.90718841552734,
+ 66.62486267089844
+ ]
+ },
+ {
+ "bufferView": 1,
+ "componentType": 5126,
+ "count": 1728,
+ "type": "VEC2",
+ "byteOffset": 0
+ },
+ {
+ "bufferView": 1,
+ "componentType": 5123,
+ "count": 1728,
+ "type": "VEC4",
+ "byteOffset": 13824
+ },
+ {
+ "bufferView": 2,
+ "byteOffset": 0,
+ "componentType": 5126,
+ "count": 1728,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 3,
+ "byteOffset": 0,
+ "componentType": 5126,
+ "count": 24,
+ "type": "MAT4"
+ },
+ {
+ "bufferView": 4,
+ "byteOffset": 0,
+ "componentType": 5126,
+ "count": 83,
+ "type": "SCALAR",
+ "min": [
+ 0.0
+ ],
+ "max": [
+ 3.4166667461395264
+ ]
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 0,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 1328,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 2656,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 3984,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 5312,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 6640,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 7968,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 9296,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 10624,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 11952,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 13280,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 14608,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 15936,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 17264,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 18592,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 19920,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 21248,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 22576,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 23904,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 6,
+ "byteOffset": 0,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC3"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 25232,
+ "componentType": 5126,
+ "count": 83,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 4,
+ "byteOffset": 332,
+ "componentType": 5126,
+ "count": 18,
+ "type": "SCALAR",
+ "min": [
+ 0.0
+ ],
+ "max": [
+ 0.7083333134651184
+ ]
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 26560,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 26848,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 27136,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 27424,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 27712,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 28000,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 28288,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 28576,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 28864,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 29152,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 29440,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 29728,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 30016,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 30304,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 30592,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 30880,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 31168,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 31456,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 31744,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 6,
+ "byteOffset": 996,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC3"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 32032,
+ "componentType": 5126,
+ "count": 18,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 4,
+ "byteOffset": 404,
+ "componentType": 5126,
+ "count": 25,
+ "type": "SCALAR",
+ "min": [
+ 0.0
+ ],
+ "max": [
+ 1.1583333015441895
+ ]
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 32320,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 32720,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 33120,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 33520,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 33920,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 34320,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 34720,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 35120,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 35520,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 35920,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 36320,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 36720,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 37120,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 37520,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 37920,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 38320,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 38720,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 39120,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 39520,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ },
+ {
+ "bufferView": 6,
+ "byteOffset": 1212,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC3"
+ },
+ {
+ "bufferView": 5,
+ "byteOffset": 39920,
+ "componentType": 5126,
+ "count": 25,
+ "type": "VEC4"
+ }
+ ],
+ "animations": [
+ {
+ "channels": [
+ {
+ "sampler": 0,
+ "target": {
+ "node": 8,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 1,
+ "target": {
+ "node": 7,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 2,
+ "target": {
+ "node": 11,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 3,
+ "target": {
+ "node": 10,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 4,
+ "target": {
+ "node": 9,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 5,
+ "target": {
+ "node": 14,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 6,
+ "target": {
+ "node": 13,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 7,
+ "target": {
+ "node": 12,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 8,
+ "target": {
+ "node": 6,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 9,
+ "target": {
+ "node": 5,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 10,
+ "target": {
+ "node": 17,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 11,
+ "target": {
+ "node": 16,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 12,
+ "target": {
+ "node": 15,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 13,
+ "target": {
+ "node": 20,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 14,
+ "target": {
+ "node": 19,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 15,
+ "target": {
+ "node": 18,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 16,
+ "target": {
+ "node": 24,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 17,
+ "target": {
+ "node": 23,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 18,
+ "target": {
+ "node": 22,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 19,
+ "target": {
+ "node": 4,
+ "path": "translation"
+ }
+ },
+ {
+ "sampler": 20,
+ "target": {
+ "node": 4,
+ "path": "rotation"
+ }
+ }
+ ],
+ "samplers": [
+ {
+ "input": 5,
+ "output": 6
+ },
+ {
+ "input": 5,
+ "output": 7
+ },
+ {
+ "input": 5,
+ "output": 8
+ },
+ {
+ "input": 5,
+ "output": 9
+ },
+ {
+ "input": 5,
+ "output": 10
+ },
+ {
+ "input": 5,
+ "output": 11
+ },
+ {
+ "input": 5,
+ "output": 12
+ },
+ {
+ "input": 5,
+ "output": 13
+ },
+ {
+ "input": 5,
+ "output": 14
+ },
+ {
+ "input": 5,
+ "output": 15
+ },
+ {
+ "input": 5,
+ "output": 16
+ },
+ {
+ "input": 5,
+ "output": 17
+ },
+ {
+ "input": 5,
+ "output": 18
+ },
+ {
+ "input": 5,
+ "output": 19
+ },
+ {
+ "input": 5,
+ "output": 20
+ },
+ {
+ "input": 5,
+ "output": 21
+ },
+ {
+ "input": 5,
+ "output": 22
+ },
+ {
+ "input": 5,
+ "output": 23
+ },
+ {
+ "input": 5,
+ "output": 24
+ },
+ {
+ "input": 5,
+ "output": 25
+ },
+ {
+ "input": 5,
+ "output": 26
+ }
+ ],
+ "name": "Survey"
+ },
+ {
+ "channels": [
+ {
+ "sampler": 0,
+ "target": {
+ "node": 8,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 1,
+ "target": {
+ "node": 7,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 2,
+ "target": {
+ "node": 11,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 3,
+ "target": {
+ "node": 10,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 4,
+ "target": {
+ "node": 9,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 5,
+ "target": {
+ "node": 14,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 6,
+ "target": {
+ "node": 13,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 7,
+ "target": {
+ "node": 12,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 8,
+ "target": {
+ "node": 6,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 9,
+ "target": {
+ "node": 5,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 10,
+ "target": {
+ "node": 17,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 11,
+ "target": {
+ "node": 16,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 12,
+ "target": {
+ "node": 15,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 13,
+ "target": {
+ "node": 20,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 14,
+ "target": {
+ "node": 19,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 15,
+ "target": {
+ "node": 18,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 16,
+ "target": {
+ "node": 24,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 17,
+ "target": {
+ "node": 23,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 18,
+ "target": {
+ "node": 22,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 19,
+ "target": {
+ "node": 4,
+ "path": "translation"
+ }
+ },
+ {
+ "sampler": 20,
+ "target": {
+ "node": 4,
+ "path": "rotation"
+ }
+ }
+ ],
+ "samplers": [
+ {
+ "input": 27,
+ "output": 28
+ },
+ {
+ "input": 27,
+ "output": 29
+ },
+ {
+ "input": 27,
+ "output": 30
+ },
+ {
+ "input": 27,
+ "output": 31
+ },
+ {
+ "input": 27,
+ "output": 32
+ },
+ {
+ "input": 27,
+ "output": 33
+ },
+ {
+ "input": 27,
+ "output": 34
+ },
+ {
+ "input": 27,
+ "output": 35
+ },
+ {
+ "input": 27,
+ "output": 36
+ },
+ {
+ "input": 27,
+ "output": 37
+ },
+ {
+ "input": 27,
+ "output": 38
+ },
+ {
+ "input": 27,
+ "output": 39
+ },
+ {
+ "input": 27,
+ "output": 40
+ },
+ {
+ "input": 27,
+ "output": 41
+ },
+ {
+ "input": 27,
+ "output": 42
+ },
+ {
+ "input": 27,
+ "output": 43
+ },
+ {
+ "input": 27,
+ "output": 44
+ },
+ {
+ "input": 27,
+ "output": 45
+ },
+ {
+ "input": 27,
+ "output": 46
+ },
+ {
+ "input": 27,
+ "output": 47
+ },
+ {
+ "input": 27,
+ "output": 48
+ }
+ ],
+ "name": "Walk"
+ },
+ {
+ "channels": [
+ {
+ "sampler": 0,
+ "target": {
+ "node": 8,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 1,
+ "target": {
+ "node": 7,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 2,
+ "target": {
+ "node": 11,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 3,
+ "target": {
+ "node": 10,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 4,
+ "target": {
+ "node": 9,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 5,
+ "target": {
+ "node": 14,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 6,
+ "target": {
+ "node": 13,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 7,
+ "target": {
+ "node": 12,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 8,
+ "target": {
+ "node": 6,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 9,
+ "target": {
+ "node": 5,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 10,
+ "target": {
+ "node": 17,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 11,
+ "target": {
+ "node": 16,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 12,
+ "target": {
+ "node": 15,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 13,
+ "target": {
+ "node": 20,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 14,
+ "target": {
+ "node": 19,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 15,
+ "target": {
+ "node": 18,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 16,
+ "target": {
+ "node": 24,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 17,
+ "target": {
+ "node": 23,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 18,
+ "target": {
+ "node": 22,
+ "path": "rotation"
+ }
+ },
+ {
+ "sampler": 19,
+ "target": {
+ "node": 4,
+ "path": "translation"
+ }
+ },
+ {
+ "sampler": 20,
+ "target": {
+ "node": 4,
+ "path": "rotation"
+ }
+ }
+ ],
+ "samplers": [
+ {
+ "input": 49,
+ "output": 50
+ },
+ {
+ "input": 49,
+ "output": 51
+ },
+ {
+ "input": 49,
+ "output": 52
+ },
+ {
+ "input": 49,
+ "output": 53
+ },
+ {
+ "input": 49,
+ "output": 54
+ },
+ {
+ "input": 49,
+ "output": 55
+ },
+ {
+ "input": 49,
+ "output": 56
+ },
+ {
+ "input": 49,
+ "output": 57
+ },
+ {
+ "input": 49,
+ "output": 58
+ },
+ {
+ "input": 49,
+ "output": 59
+ },
+ {
+ "input": 49,
+ "output": 60
+ },
+ {
+ "input": 49,
+ "output": 61
+ },
+ {
+ "input": 49,
+ "output": 62
+ },
+ {
+ "input": 49,
+ "output": 63
+ },
+ {
+ "input": 49,
+ "output": 64
+ },
+ {
+ "input": 49,
+ "output": 65
+ },
+ {
+ "input": 49,
+ "output": 66
+ },
+ {
+ "input": 49,
+ "output": 67
+ },
+ {
+ "input": 49,
+ "output": 68
+ },
+ {
+ "input": 49,
+ "output": 69
+ },
+ {
+ "input": 49,
+ "output": 70
+ }
+ ],
+ "name": "Run"
+ }
+ ],
+ "bufferViews": [
+ {
+ "buffer": 0,
+ "byteOffset": 0,
+ "byteLength": 20736,
+ "byteStride": 12
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 20736,
+ "byteLength": 27648,
+ "byteStride": 8
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 48384,
+ "byteLength": 27648,
+ "byteStride": 16
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 76032,
+ "byteLength": 1536
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 77568,
+ "byteLength": 504,
+ "byteStride": 4
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 78072,
+ "byteLength": 40320,
+ "byteStride": 16
+ },
+ {
+ "buffer": 0,
+ "byteOffset": 118392,
+ "byteLength": 1512,
+ "byteStride": 12
+ }
+ ],
+ "buffers": [
+ {
+ "uri": "data:application/octet-stream;base64,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AgACAAoABAACAAIAAgAQAAIAAgACABAAAgACAAIADQACAAIABAAFAAcACgAKAAQAAgACAAoAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAKAAIAAgACAAUABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAAgAQAAIAAgADAAIAAgACAAIAEAARAAIABAAFAAcACgAEAAoABwACAAoABAACAAIAAgANAAIAAgACABAAAgACAAIADQACAAIAAwACAAIAAgADAAIAAgACAAIAEAACAAIAAgAQABEAAgADAAIAAgACAAIAAgACAAIACgACAAIAAgAKAAQAAgACAAoAAgACAAIADwACAAIAAgAPAA4AAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIAAgAUAAIAAgACAA0AAgACAAIAEAAUAAIACgACAAIAAgAFAAQAAgACAAUABAACAAIABQAEAAIAAgAEAAUABwAKAAoAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABwACAAIAAgAHAAgAAgACAAcAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAAgAUAAIAAgACAA0AAgACAAIAFAACAAIAAwACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgACABQAAgACAAMAAgACAAIAAgAQABQAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABQAAgACAAIAEAAUAAIAAgAUAAIAAgAVABQAAgACAAIAFAACAAIABwACAAIAAgAIAAcAAgACAAcACAACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwAOAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIAAwACAAIAAgAHAAQAAgACAAMAFAACAAIAAgAUAAIAAgACAA0AAgACAAIAFAACAAIABAAFAAcACgAHAAIAAgACAAcABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAFAAQAAgACAAcAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAAgAUAAIAAgACABQAFQACAAMAAgACAAIABAAFAAcACgAHAAQAAgACAAQACgAHAAIAAgANAAIAAgACAA0AAgACAAIAFAACAAIAAwACAAIAAgACABQAAgACAAMAAgACAAIAAgAUABUAAgACABQAAgACAAIAAgACAAIABwACAAIAAgAHAAIAAgACAAcABAACAAIADwACAAIAAgAPAAIAAgACAA8ADgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIADwACAAIAAgAPAAIAAgACAA8AAgACAAIABwACAAIAAgAEAAUABwAKAAUABAACAAIABQAEAAIAAgAFAAQAAgACAAcAAgACAAIACgACAAIAAgAKAAIAAgACAAoAAgACAAIACgACAAIAAgAKAAQAAgACAAoAAgACAAIACgACAAIAAgALAAoAAgACAAoACwACAAIACgALAAIAAgAKAAIAAgACAAoAAgACAAIABwACAAIAAgAHAAQAAgACAAcAAgACAAIABwACAAIAAgAHAAIAAgACAAcAAgACAAIACgALAAIAAgAKAAIAAgACAAoABAACAAIACgAEAAIAAgAEAAoABwACAAoACwACAAIABwAIAAIAAgAEAAoABwACAAcABAACAAIABwAEAAIAAgAHAAIAAgACAAcACAACAAIABwACAAIAAgAHAAIAAgACAAcACAACAAIABwAIAAIAAgAIAAcAAgACAAcAAgACAAIAAwAUAAIAAgACABQAAgACAAIAFAACAAIAAgAUAAIAAgADAAIAAgACAAMAFAACAAIABAAKAAcAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgAEAAoABwACAAcABAACAAIABwAEAAIAAgADAAIAAgACAAMAAgACAAIAAwAQAAIAAgADAAIAAgACAAIAEAACAAIAAgAQAAIAAgACABAAAgACAAMAEAACAAIABAAKAAcAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgADAAIAAgACAAoABAACAAIACgAEAAIAAgAEAAoABwACAAMAAgACAAIAAwACAAIAAgACAAIAAgACAAIAAgACAAIAAwACAAIAAgACAAIAAgACAAIAAgACAAIAAwACAAIAAgACABQAFQACAAIAAgACAAIAAgAQAAIAAgACABAAEQACAAIAAgACAAIABQAEAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAUABAACAAIABQAEAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAUABAACAAIABQAEAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAFAAQAAgACAAUABAACAAIABQAEAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAFAAQAAgACAAUABAACAAIAAgANAAIAAgACAA0AAgACAA0ADgACAAIADQAOAAIAAgACAA0AAgACAA0ADgACAAIACgAEAAIAAgADABAAAgACAAMAEAACAAIAAwAQAAIAAgAKAAQAAgACAAoABAACAAIAAwACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgACAAIAAgACAAMAAgACAAIAAgANAAIAAgACABAAAgACAAIADQACAAIAAgACAAIAAgACABAAAgACAAIAEAACAAIAAgAQAAIAAgACABAAAgACAAIADQACAAIACgAEAAIAAgAKAAQAAgACAAoACwACAAIABAACAAIAAgAEAAIAAgACAAUABAACAAIABAACAAIAAgAEAAIAAgACAAUABAACAAIABgACAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAAgANAAIAAgACAA0AAgACAA0ADgACAAIAAgAQAAIAAgACABAAAgACABEAEAACAAIADQAOAAIAAgANAA4AAgACAA8ADgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgACAAIAAgACAAIAAgACAAIADQACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgAQAAIAAgACABAAAgACABAAEQACAAIAAgAQAAIAAgACABAAAgACABEAEAACAAIAAgAQAAIAAgACABAAAgACABEAEAACAAIAAgAQAAIAAgACABAAAgACABEAEAACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQAQAAIAAgACABAAEQACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQAQAAIAAgARABAAAgACABEAAgACAAIAEAARAAIAAgARABAAAgACABEAAgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIACgALAAIAAgAKAAsAAgACAAsAAgACAAIACwAKAAIAAgAKAAsAAgACAAsAAgACAAIABwACAAIAAgAHAAIAAgACAAcAAgACAAIABwACAAIAAgAHAAIAAgACAAcAAgACAAIABAAKAAcAAgAKAAQAAgACAAoACwACAAIACgALAAIAAgAKAAsAAgACAAsAAgACAAIADQAOAAIAAgACAA0AAgACAA0ADgACAAIADQAOAAIAAgAPAA4AAgACAA0ADgACAAIAAgANAAIAAgACAA0AAgACAA0ADgACAAIADQAOAAIAAgANAA4AAgACAAIADQACAAIADwAOAAIAAgAPAA4AAgACAA8AAgACAAIADwAOAAIAAgAPAA4AAgACAA8AAgACAAIADwAOAAIAAgAPAA4AAgACAA8AAgACAAIADwAOAAIAAgAPAA4AAgACAA8AAgACAAIADwAOAAIAAgAPAA4AAgACAA8AAgACAAIAEQAQAAIAAgACABAAAgACAAIAEAARAAIAAwACAAIAAgACAAIAAgACAAIAAgACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgANAAIAAgACAAIAAgACAAIAEAACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgANAAIAAgACABAAAgACAAIADQACAAIABQAEAAIAAgAEAAIAAgACAAUABAACAAIABQAEAAIAAgAEAAIAAgACAAUABAACAAIACgALAAIAAgAKAAQAAgACAAoACwACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIACgALAAIAAgAKAAQAAgACAAoACwACAAIACgACAAIAAgAKAAIAAgACAAoAAgACAAIAAwAQAAIAAgADAAIAAgACAAoABAACAAIADQAOAAIAAgACAA0AAgACAAIADQACAAIAEAARAAIAAgACABAAAgACABEAEAACAAIADwAOAAIAAgANAA4AAgACAA8ADgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgANAAIAAgACAAIAAgACAAIADQACAAIAEQAQAAIAAgACABAAAgACABAAEQACAAIAAwACAAIAAgADAAIAAgACAAIAAgACAAIAEQAQAAIAAgACABAAAgACABEAEAACAAIAEQAQAAIAAgACABAAAgACABEAEAACAAIAEQAQAAIAAgACABAAAgACABEAEAACAAIAEQASAAIAAgACABAAEQACABEAEgACAAIACgALAAIAAgAEAAoABwACAAoACwACAAIACwACAAIAAgAKAAsAAgACAAsACgACAAIADwAOAAIAAgANAA4AAgACAA8ADgACAAIADwAOAAIAAgANAA4AAgACAA8ADgACAAIADwAOAAIAAgANAA4AAgACAA8ADgACAAIADwAOAAIAAgANAA4AAgACAA0ADgACAAIADwACAAIAAgAPAA4AAgACAA8AAgACAAIADwACAAIAAgAPAA4AAgACAA8AAgACAAIADwACAAIAAgAPAA4AAgACAA8AAgACAAIAAgANAAIAAgANAA4AAgACAAIADQACAAIADQAOAAIAAgANAA4AAgACAAIADQACAAIABwAEAAIAAgADABQAAgACAAMAFAACAAIAAwAUAAIAAgAHAAQAAgACAAcABAACAAIAAgACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgADAAIAAgACAAIAAgACAAIABAACAAIAAgAHAAIAAgACAAcAAgACAAIABwACAAIAAgAEAAIAAgACAAQAAgACAAIAAgANAAIAAgACAA0AAgACAAIAFAACAAIAAgACAAIAAgACABQAAgACAAIAFAACAAIAAgAUAAIAAgACAA0AAgACAAIAFAACAAIABwAEAAIAAgAHAAgAAgACAAcABAACAAIABAACAAIAAgAFAAQAAgACAAQAAgACAAIABAACAAIAAgAFAAQAAgACAAQAAgACAAIABgACAAIAAgAGAAIAAgACAAUABAACAAIABAACAAIAAgAFAAQAAgACAAUABAACAAIABQAEAAIAAgAKAAIAAgACAAQAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAGAAIAAgACAAUABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABQAEAAIAAgAGAAIAAgACAAUABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAAgANAAIAAgANAA4AAgACAAIADQACAAIAAgAUAAIAAgAVABQAAgACAAIAFAACAAIADQAOAAIAAgAPAA4AAgACAA0ADgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgACAAIAAgACAA0AAgACAAIAAgACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgAUAAIAAgAUABUAAgACAAIAFAACAAIAAgAUAAIAAgAVABQAAgACAAIAFAACAAIAAgAUAAIAAgAVABQAAgACAAIAFAACAAIAAgAUAAIAAgAVABQAAgACAAIAFAACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAUAAIAAgAVABYAAgACAAIAFAAVAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAUAAIAAgAVAAIAAgACABUAFAACAAIAFAAVAAIAAgAVAAIAAgACABUAFAACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIABwAIAAIAAgAIAAIAAgACAAcACAACAAIACAAHAAIAAgAIAAIAAgACAAcACAACAAIABAAKAAcAAgAHAAgAAgACAAcABAACAAIABwAIAAIAAgAIAAIAAgACAAcACAACAAIADQAOAAIAAgAPAA4AAgACAA0ADgACAAIADQAOAAIAAgAPAA4AAgACAA0ADgACAAIADQAOAAIAAgAPAA4AAgACAA8ADgACAAIADwAOAAIAAgANAA4AAgACAA0ADgACAAIADwAOAAIAAgAPAAIAAgACAA8ADgACAAIADwAOAAIAAgAPAAIAAgACAA8ADgACAAIADwAOAAIAAgAPAAIAAgACAA8ADgACAAIADwAOAAIAAgAPAAIAAgACAA8ADgACAAIADwAOAAIAAgAPAAIAAgACAA8ADgACAAIAFQAUAAIAAgACABQAFQACAAIAFAACAAIAAwACAAIAAgACAAIAAgACAAIAAgACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgANAAIAAgACAA0AAgACAAIADQACAAIAAgANAAIAAgACABQAAgACAAIAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgANAAIAAgACAA0AAgACAAIAFAACAAIABQAEAAIAAgAFAAQAAgACAAQAAgACAAIABQAEAAIAAgAEAAIAAgACAAUABAACAAIABwAIAAIAAgAHAAgAAgACAAcABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAUABAACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABwAIAAIAAgAHAAgAAgACAAcABAACAAIABwACAAIAAgAHAAIAAgACAAcAAgACAAIAAwAUAAIAAgAHAAQAAgACAAMAAgACAAIADQAOAAIAAgACAA0AAgACAAIADQACAAIAFAAVAAIAAgAVABQAAgACAAIAFAACAAIADwAOAAIAAgAPAA4AAgACAA0ADgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIAAgANAAIAAgACAA0AAgACAAIAAgACAAIAFQAUAAIAAgAUABUAAgACAAIAFAACAAIAAwACAAIAAgACAAIAAgACAAMAAgACAAIAFQAUAAIAAgAVABQAAgACAAIAFAACAAIAFQAUAAIAAgAVABQAAgACAAIAFAACAAIAFQAUAAIAAgAVABQAAgACAAIAFAACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIABwAIAAIAAgAEAAoABwACAAcACAACAAIACAACAAIAAgAIAAcAAgACAAcACAACAAIADwAOAAIAAgAPAA4AAgACAA0ADgACAAIADwAOAAIAAgAPAA4AAgACAA0ADgACAAIADwAOAAIAAgAPAA4AAgACAA0ADgACAAIADQAOAAIAAgANAA4AAgACAA8ADgACAAIADwAOAAIAAgAPAA4AAgACAA0ADgACAAIADwACAAIAAgAPAAIAAgACAA8ADgACAAIADwACAAIAAgAPAAIAAgACAA8ADgACAAIADwACAAIAAgAPAAIAAgACAA8ADgACAAIAEQASAAIAAgARABIAAgACAAIAEAARAAIAAgAQABEAAgACABAAAgACABEAEgACAAIABAACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgAEAAIAAgACAAQAAgACAAIACgAEAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgAEAAIAAgACAAoABAACAAIABwAEAAIAAgAHAAgAAgACAAcAAgACAAIABAACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgAHAAQAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAMAAgACAAIAAwACAAIAAgADAAIAAgACAAQAAgACAAIACgACAAIAAgAKAAIAAgACAAoAAgACAAIACgACAAIAAgAKAAIAAgACAAoAAgACAAIABwAIAAIAAgAIAAcAAgACAAcAAgACAAIABwACAAIAAgAHAAIAAgACAAcACAACAAIABwAIAAIAAgAHAAgAAgACAAcAAgACAAIACgACAAIAAgAKAAsAAgACAAoACwACAAIACgALAAIAAgAKAAIAAgACAAoAAgACAAIACgACAAIAAgAKAAsAAgACAAsACgACAAIACwAKAAIAAgAKAAIAAgACAAoAAgACAAIABwACAAIAAgAHAAIAAgACAAgABwACAAIACAAHAAIAAgAHAAgAAgACAAcAAgACAAIACwAKAAIAAgAKAAsAAgACAAoACwACAAIACAAHAAIAAgAHAAgAAgACAAcACAACAAIACgALAAIAAgAKAAIAAgACAAsACgACAAIACgACAAIAAgAKAAsAAgACAAoAAgACAAIACgACAAIAAgAKAAIAAgACAAoAAgACAAIABAACAAIAAgAEAAIAAgACAAoAAgACAAIACgACAAIAAgAKAAIAAgACAAQAAgACAAIACgACAAIAAgAKAAQAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAoAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABwACAAIAAgAHAAIAAgACAAcACAACAAIABwAIAAIAAgAHAAIAAgACAAcAAgACAAIACgAEAAIAAgAKAAIAAgACAAoACwACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAcABAACAAIABwAEAAIAAgAHAAIAAgACAAQAAgACAAIAEQASAAIAAgARABIAAgACABEAEAACAAIAEQAQAAIAAgARABAAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACAAIAEAACAAIAAgAQAAIAAgARABAAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEAACAAIAEQAQAAIAAgARABAAAgACABEAEgACAAIAFQAWAAIAAgAVABQAAgACABUAFAACAAIAFQAUAAIAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABQAAgACABUAFAACAAIAFQAUAAIAAgAVABYAAgACABUAFgACAAIAFQAUAAIAAgAVABYAAgACABQAFQACAAIAEQAQAAIAAgAQABEAAgACABEAEgACAAIAFQAWAAIAAgACABQAAgACAAIAFAAVAAIAAgAUABUAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABQAAgACAAIAFAACAAIAAgAUAAIAAgAVABYAAgACABUAFgACAAIAAgAUABUAAgAVABYAAgACABUAFgACAAIAAgANAAIAAgANAA4AAgACAA0ADgACAAIADQAOAAIAAgACAA0AAgACAAIADQACAAIAAgANAAIAAgANAA4AAgACAA0ADgACAAIAAgANAAIAAgANAA4AAgACAA0ADgACAAIAAgANAAIAAgANAA4AAgACAA0ADgACAAIABAACAAIAAgADAAIAAgACAAMAAgACAAIABAACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgADAAIAAgACAAQAAgACAAIABAACAAIAAgAEAAIAAgACAAMAAgACAAIAAwACAAIAAgADAAIAAgACAAIAEAACAAIAAgAQAAIAAgACAAIAAgACAAMAAgACAAIAAwACAAIAAgADABAAAgACAAIAEAACAAIAAgAQAAIAAgACABAAAgACAAMAAgACAAIAAgAQAAIAAgADAAIAAgACAAMAAgACAAIAAgAQAAIAAgADABAAAgACAAMAEAACAAIAAgAUAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgAEAAIAAgACAAQAAgACAAIABAACAAIAAgADAAIAAgACAAMAAgACAAIAAwACAAIAAgACAAIAAgACAAIAFAACAAIAAgAUAAIAAgADAAIAAgACAAMAAgACAAIAAgAUAAIAAgADABQAAgACAAMAFAACAAIAAwACAAIAAgACABQAAgACAAIAFAACAAIAAgAUAAIAAgADABQAAgACAAMAAgACAAIABAACAAIAAgAHAAIAAgACAAUABAACAAIABQAEAAIAAgAFAAQAAgACAAQAAgACAAIABQAEAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAFAAQAAgACAAUABAACAAIABQAEAAIAAgAFAAQAAgACAAoAAgACAAIACgACAAIAAgAKAAIAAgACAAUABAACAAIABQAEAAIAAgAHAAIAAgACAAcAAgACAAIABwACAAIAAgAFAAQAAgACAAUABAACAAIABQAEAAIAAgAFAAQAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAUABAACAAIABgACAAIAAgAFAAQAAgACAAUABAACAAIABgACAAIAAgAFAAQAAgACAAUABAACAAIAEQASAAIAAgARAAIAAgACABIAEQACAAIAEQASAAIAAgARABIAAgACABMAEgACAAIAEQASAAIAAgASABEAAgACABIAEwACAAIAEwASAAIAAgASABMAAgACABMAAgACAAIAEQASAAIAAgARABIAAgACABMAEgACAAIAEgARAAIAAgARABIAAgACABIAEwACAAIAEQASAAIAAgARABIAAgACABIAEwACAAIAEQASAAIAAgARABIAAgACABIAEwACAAIAEwACAAIAAgATABIAAgACABMAAgACAAIAEwACAAIAAgATAAIAAgACABMAAgACAAIAEwASAAIAAgATAAIAAgACABMAAgACAAIAEwACAAIAAgASABMAAgACABMAAgACAAIAEgATAAIAAgASABMAAgACABMAAgACAAIAEgATAAIAAgASABMAAgACABMAAgACAAIACwACAAIAAgALAAIAAgACAAwACwACAAIACwACAAIAAgAMAAsAAgACAAsAAgACAAIACwACAAIAAgALAAIAAgACAAwACwACAAIACwACAAIAAgALAAIAAgACAAwACwACAAIACwACAAIAAgALAAIAAgACAAwACwACAAIACwACAAIAAgALAAoAAgACAAsAAgACAAIADAACAAIAAgAMAAsAAgACAAwAAgACAAIADAACAAIAAgAMAAIAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwAAgACAAIAEQASAAIAAgARABAAAgACABEAEgACAAIAEQACAAIAAgARABAAAgACABEAEgACAAIAEQASAAIAAgARABAAAgACABEAEgACAAIAEgARAAIAAgARAAIAAgACABEAEgACAAIAEQASAAIAAgAQABEAAgACABEAAgACAAIAEgATAAIAAgARABIAAgACABMAEgACAAIAEgATAAIAAgASABEAAgACABIAEwACAAIAEwASAAIAAgARABIAAgACABMAEgACAAIAEgATAAIAAgASABEAAgACABIAEwACAAIAEwASAAIAAgARABIAAgACABIAEwACAAIAEwACAAIAAgATABIAAgACABMAEgACAAIAEwACAAIAAgATAAIAAgACABMAAgACAAIAEwASAAIAAgATAAIAAgACABMAAgACAAIAEwACAAIAAgATAAIAAgACABMAAgACAAIAEwACAAIAAgASABMAAgACABMAEgACAAIAEwACAAIAAgASABMAAgACABMAAgACAAIACwACAAIAAgAKAAsAAgACAAsAAgACAAIADAALAAIAAgALAAIAAgACAAwACwACAAIACwACAAIAAgALAAoAAgACAAsAAgACAAIACwACAAIAAgALAAoAAgACAAsAAgACAAIACwACAAIAAgAKAAsAAgACAAsAAgACAAIADAALAAIAAgALAAIAAgACAAwACwACAAIADAALAAIAAgALAAIAAgACAAwACwACAAIADAACAAIAAgAMAAsAAgACAAwAAgACAAIADAALAAIAAgAMAAsAAgACAAwACwACAAIADAACAAIAAgAMAAIAAgACAAwAAgACAAIADAACAAIAAgAMAAIAAgACAAwAAgACAAIADAACAAIAAgAMAAsAAgACAAwAAgACAAIADAACAAIAAgAMAAsAAgACAAwAAgACAAIADAACAAIAAgAMAAsAAgACAAwAAgACAAIAFQAWAAIAAgAWABUAAgACABUAAgACAAIAFQAWAAIAAgAXABYAAgACABUAFgACAAIAFQAWAAIAAgAWABcAAgACABYAFQACAAIAFwAWAAIAAgAXAAIAAgACABYAFwACAAIAFQAWAAIAAgAXABYAAgACABUAFgACAAIAFgAVAAIAAgAWABcAAgACABUAFgACAAIAFQAWAAIAAgAWABcAAgACABUAFgACAAIAFQAWAAIAAgAWABcAAgACABUAFgACAAIAFwACAAIAAgAXAAIAAgACABcAFgACAAIAFwACAAIAAgAXAAIAAgACABcAAgACAAIAFwAWAAIAAgAXAAIAAgACABcAAgACAAIAFwACAAIAAgAXAAIAAgACABYAFwACAAIAFgAXAAIAAgAXAAIAAgACABYAFwACAAIAFgAXAAIAAgAXAAIAAgACABYAFwACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAJAAgAAgACAAgAAgACAAIACQACAAIAAgAJAAIAAgACAAkACAACAAIACQACAAIAAgAJAAIAAgACAAkAAgACAAIACQAIAAIAAgAJAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAIAAgACAAkACAACAAIAFQAWAAIAAgAVABYAAgACABUAFAACAAIAFQACAAIAAgAVABYAAgACABUAFAACAAIAFQAWAAIAAgAVABYAAgACABUAFAACAAIAFgAVAAIAAgAVABYAAgACABUAAgACAAIAFQAWAAIAAgAVAAIAAgACABQAFQACAAIAFgAXAAIAAgAXABYAAgACABUAFgACAAIAFgAXAAIAAgAWABcAAgACABYAFQACAAIAFwAWAAIAAgAXABYAAgACABUAFgACAAIAFgAXAAIAAgAWABcAAgACABYAFQACAAIAFwAWAAIAAgAWABcAAgACABUAFgACAAIAFwACAAIAAgAXABYAAgACABcAFgACAAIAFwACAAIAAgAXAAIAAgACABcAAgACAAIAFwAWAAIAAgAXAAIAAgACABcAAgACAAIAFwACAAIAAgAXAAIAAgACABcAAgACAAIAFwACAAIAAgAXABYAAgACABYAFwACAAIAFwACAAIAAgAXAAIAAgACABYAFwACAAIACAACAAIAAgAIAAIAAgACAAcACAACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAIAAIAAgACAAgABwACAAIACAACAAIAAgAIAAIAAgACAAgABwACAAIACAACAAIAAgAIAAIAAgACAAcACAACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIACQACAAIAAgAJAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAgAAgACAAkACAACAAIACQACAAIAAgAJAAIAAgACAAkAAgACAAIACQACAAIAAgAJAAIAAgACAAkAAgACAAIACQACAAIAAgAJAAIAAgACAAkACAACAAIACQACAAIAAgAJAAIAAgACAAkACAACAAIACQACAAIAAgAJAAIAAgACAAkACAACAAIACwACAAIAAgAMAAsAAgACAAwACwACAAIADAALAAIAAgALAAIAAgACAAsAAgACAAIACAACAAIAAgAIAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIACAACAAIAAgAIAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIACwACAAIAAgALAAIAAgACAAsACgACAAIACwAKAAIAAgAKAAsAAgACAAsAAgACAAIACwACAAIAAgAMAAsAAgACAAwACwACAAIADAALAAIAAgALAAIAAgACAAsAAgACAAIACwACAAIAAgAMAAsAAgACAAwACwACAAIADAALAAIAAgALAAIAAgACAAsAAgACAAIACAACAAIAAgAHAAgAAgACAAcACAACAAIABwAIAAIAAgAIAAIAAgACAAgAAgACAAIACAACAAIAAgAIAAcAAgACAAcACAACAAIABwAIAAIAAgAIAAIAAgACAAgAAgACAAIACwACAAIAAgALAAIAAgACAAoACwACAAIACgALAAIAAgAKAAsAAgACAAsAAgACAAIACwACAAIAAgALAAIAAgACAAoACwACAAIACgALAAIAAgALAAoAAgACAAsAAgACAAIACAACAAIAAgAHAAgAAgACAAgABwACAAIACAAHAAIAAgAIAAIAAgACAAgAAgACAAIACAACAAIAAgAIAAIAAgACAAkACAACAAIACQAIAAIAAgAJAAgAAgACAAgAAgACAAIADAALAAIAAgALAAIAAgACAAsAAgACAAIACwAKAAIAAgALAAIAAgACAAsAAgACAAIACAAHAAIAAgAIAAIAAgACAAgAAgACAAIACAAHAAIAAgAIAAIAAgACAAgAAgACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAFQAWAAIAAgAVABYAAgACABUAFAACAAIAFQAWAAIAAgAVABYAAgACABUAFgACAAIAEQASAAIAAgARABAAAgACABEAEgACAAIAEQASAAIAAgARABIAAgACABEAEgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIABgACAAIAAgAGAAIAAgACAAYAAgACAAIAmpkZP83MzD4AAAAAAAAAANo/Mz+amRk+AmcZPgAAAAAK12M/rkfhPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA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uB6FPgAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAMzNzP83MTD0AAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAMzNzP83MTD0AAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAACtdjP65H4T0AAAAAAAAAAArXYz+uR+E9AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAAD8AAAA/AAAAAAAAAACZmRk/zszMPgAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAAD8AAAA/AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA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AAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAGZmZj/NzMw9AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAwvUoP3sUrj4AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAFyPQj+PwnU+AAAAAAAAAADC9Sg/exSuPgAAAAAAAAAAwvUoP3sUrj4AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAEA/AACAPgAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAADC9Sg/exSuPgAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAGZmZj/NzMw9AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAGZmZj/NzMw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAMzNzP83MTD0AAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAMzNzP83MTD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAMzNzP83MTD0AAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAMzNzP83MTD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAzM3M/zcxMPQAAAAAAAAAAMzNzP83MTD0AAAAAAAAAADMzcz/NzEw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAA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AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAGZmZj/NzMw9AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAGZmZj/NzMw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAGZmZj/NzMw9AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAUrkc/sEdhPgAAAAAAAAAAFK5HP7BHYT4AAAAAAAAAAM3MTD/NzEw+AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAGZmZj/NzMw9AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAGZmZj/NzMw9AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAM3MTD/NzEw+AAAAAAAAAADNzEw/zcxMPgAAAAAAAAAAzcxMP83MTD4AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAA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HAsyvz3BAr4ZCzI/Z8ECPhwLMr87wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9mwQI+HAsyvzrBAr4ZCzI/ZsECPhwLMr86wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/Z8ECPhwLMr87wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/aMECPhwLMr88wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9owQI+HAsyvzzBAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/Z8ECPhwLMr87wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9mwQI+HAsyvzrBAr4ZCzI/acECPhwLMr89wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9nwQI+HAsyvzvBAr4ZCzI/ZsECPhwLMr86wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9owQI+HAsyvzzBAr4ZCzI/ZsECPhwLMr86wQK+GQsyP2bBAj4cCzK/OsECvhkLMj9mwQI+HAsyvzrBAr4ZCzI/ZsECPhwLMr86wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9pwQI+HAsyvz3BAr4ZCzI/acECPhwLMr89wQK+GQsyP2nBAj4cCzK/PcECvhkLMj9nwQI+HAsyvzvBAr4ZCzI/Z8ECPhwLMr87wQK+GQsyP2nBAj4cCzK/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",
+ "byteLength": 119904
+ }
+ ],
+ "images": [
+ {
+ "uri": "data:image/png;base64,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",
+ "mimeType": "image/png"
+ }
+ ],
+ "materials": [
+ {
+ "name": "fox_material",
+ "pbrMetallicRoughness": {
+ "baseColorTexture": {
+ "index": 0
+ },
+ "metallicFactor": 0,
+ "roughnessFactor": 0.58
+ }
+ }
+ ],
+ "meshes": [
+ {
+ "name": "fox1",
+ "primitives": [
+ {
+ "attributes": {
+ "POSITION": 0,
+ "TEXCOORD_0": 1,
+ "JOINTS_0": 2,
+ "WEIGHTS_0": 3
+ },
+ "material": 0
+ }
+ ]
+ }
+ ],
+ "nodes": [
+ {
+ "children": [
+ 1,
+ 2
+ ],
+ "name": "root"
+ },
+ {
+ "name": "fox",
+ "mesh": 0,
+ "skin": 0
+ },
+ {
+ "children": [
+ 3
+ ],
+ "name": "_rootJoint"
+ },
+ {
+ "children": [
+ 4
+ ],
+ "name": "b_Root_00",
+ "rotation": [
+ -0.7071080924875391,
+ 0.0,
+ 0.0,
+ 0.7071054698831242
+ ]
+ },
+ {
+ "children": [
+ 5,
+ 15,
+ 18,
+ 22
+ ],
+ "name": "b_Hip_01",
+ "rotation": [
+ 0.12769094176175547,
+ -0.6954820192393762,
+ -0.12769022650601444,
+ 0.695481840425441
+ ],
+ "translation": [
+ 0,
+ 26.748403549194336,
+ 42.93817138671875
+ ]
+ },
+ {
+ "children": [
+ 6
+ ],
+ "name": "b_Spine01_02",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.5904157638238317,
+ 0.8070992664030376
+ ],
+ "translation": [
+ 12.850601196289062,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 7,
+ 9,
+ 12
+ ],
+ "name": "b_Spine02_03",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.017411952404281082,
+ 0.9998484004655261
+ ],
+ "translation": [
+ 21.65575408935547,
+ -0.000118255615234375,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 8
+ ],
+ "name": "b_Neck_04",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.30337914028264346,
+ 0.9528699267168443
+ ],
+ "translation": [
+ 25.64914321899414,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_Head_05",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.4002854151487349,
+ 0.9163905206947555
+ ],
+ "translation": [
+ 13.376960754394531,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 10
+ ],
+ "name": "b_RightUpperArm_06",
+ "rotation": [
+ 0.0004673273262011562,
+ -0.0004461484692255928,
+ -0.7121792881110691,
+ 0.7019973248825985
+ ],
+ "translation": [
+ 18.677913665771484,
+ -4.297340393066406,
+ 6.9675750732421875
+ ]
+ },
+ {
+ "children": [
+ 11
+ ],
+ "name": "b_RightForeArm_07",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.03712589977348744,
+ 0.9993105961441663
+ ],
+ "translation": [
+ 23.04512596130371,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_RightHand_08",
+ "rotation": [
+ -0.012037406914797018,
+ -0.00782221012465276,
+ 0.4605623277185148,
+ 0.8875112709988741
+ ],
+ "translation": [
+ 19.350055694580078,
+ -0.14598655700683594,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 13
+ ],
+ "name": "b_LeftUpperArm_09",
+ "rotation": [
+ 0.0004972619220940174,
+ -0.0008821923166442875,
+ -0.7120874929914663,
+ 0.7020900061903927
+ ],
+ "translation": [
+ 18.67791748046875,
+ -4.297344207763672,
+ -6.967987060546875
+ ]
+ },
+ {
+ "children": [
+ 14
+ ],
+ "name": "b_LeftForeArm_010",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.03712589977348744,
+ 0.9993105961441663
+ ],
+ "translation": [
+ 23.045124053955078,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_LeftHand_011",
+ "rotation": [
+ 0.01651791440721507,
+ 0.014013739873997781,
+ 0.46007557521271,
+ 0.8876154790736099
+ ],
+ "translation": [
+ 19.350051879882812,
+ -0.14599037170410156,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 16
+ ],
+ "name": "b_Tail01_012",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.9818928940656295,
+ 0.1894369145214904
+ ],
+ "translation": [
+ 4.2603759765625,
+ 15.958770751953125,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 17
+ ],
+ "name": "b_Tail02_013",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.0696171663387466,
+ 0.9975737818081244
+ ],
+ "translation": [
+ 12.411918640136719,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_Tail03_014",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.05383274484207684,
+ 0.9985499664927979
+ ],
+ "translation": [
+ 24.24032211303711,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 19
+ ],
+ "name": "b_LeftLeg01_015",
+ "rotation": [
+ 0.0,
+ -0.0001717522536559936,
+ 0.9700158834020681,
+ -0.2430414706359161
+ ],
+ "translation": [
+ 4.813770294189453,
+ 5.154018402099609,
+ -6.968006134033203
+ ]
+ },
+ {
+ "children": [
+ 20
+ ],
+ "name": "b_LeftLeg02_016",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.36804378855511655,
+ 0.9298084586117706
+ ],
+ "translation": [
+ 18.944175720214844,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 21
+ ],
+ "name": "b_LeftFoot01_017",
+ "rotation": [
+ 0.0002484105929664666,
+ 0.0,
+ 0.4584841122585099,
+ 0.888702569535333
+ ],
+ "translation": [
+ 17.942811965942383,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_LeftFoot02_018",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.5472882949090243,
+ 0.8369441571906533
+ ],
+ "translation": [
+ 15.779938697814941,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 23
+ ],
+ "name": "b_RightLeg01_019",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.9699585942054535,
+ -0.24327006705918533
+ ],
+ "translation": [
+ 4.813777923583984,
+ 5.154026031494141,
+ 6.967563629150391
+ ]
+ },
+ {
+ "children": [
+ 24
+ ],
+ "name": "b_RightLeg02_020",
+ "rotation": [
+ 0.0,
+ 0.0,
+ -0.36804381432052885,
+ 0.9298084484131106
+ ],
+ "translation": [
+ 18.944183349609375,
+ 0,
+ 0
+ ]
+ },
+ {
+ "children": [
+ 25
+ ],
+ "name": "b_RightFoot01_021",
+ "rotation": [
+ -0.00015345455876803163,
+ 0.0,
+ 0.4579093746168346,
+ 0.888998864504178
+ ],
+ "translation": [
+ 17.94281005859375,
+ 0,
+ 0
+ ]
+ },
+ {
+ "name": "b_RightFoot02_022",
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.5472882949090243,
+ 0.8369441571906533
+ ],
+ "translation": [
+ 15.779935836791992,
+ 0,
+ 0
+ ]
+ }
+ ],
+ "samplers": [
+ {
+ "magFilter": 9729,
+ "minFilter": 9987
+ }
+ ],
+ "scene": 0,
+ "scenes": [
+ {
+ "nodes": [
+ 0
+ ]
+ }
+ ],
+ "skins": [
+ {
+ "inverseBindMatrices": 4,
+ "joints": [
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25
+ ],
+ "skeleton": 2
+ }
+ ],
+ "textures": [
+ {
+ "sampler": 0,
+ "source": 0
+ }
+ ]
+}
diff --git a/demo/model3D/files/face.obj b/demo/model3D/files/face.obj
new file mode 100644
index 0000000000000000000000000000000000000000..a2e82ee9cb6dd5a9fc6cb612dfea0bd5e7eab162
--- /dev/null
+++ b/demo/model3D/files/face.obj
@@ -0,0 +1,2471 @@
+####
+#
+# OBJ File Generated by Meshlab
+#
+####
+# Object face.obj
+#
+# Vertices: 845
+# Faces: 1610
+#
+####
+v 54.126293 -49.502399 71.230705 0.384314 0.254902 0.200000
+v 51.424591 -54.578999 75.431709 0.337255 0.227451 0.172549
+v 44.556496 -61.237099 65.307907 0.384314 0.254902 0.192157
+v 18.416197 -75.205498 35.343601 0.529412 0.376471 0.298039
+v 13.523697 -77.731102 34.633598 0.513725 0.364706 0.290196
+v 11.454597 -74.201599 29.775103 0.639216 0.454902 0.372549
+v 5.855427 -77.386299 30.315100 0.603922 0.435294 0.356863
+v -0.378855 -77.287903 29.743700 0.611765 0.443137 0.360784
+v 6.812867 -79.041397 33.545300 0.505882 0.368627 0.298039
+v 21.881296 -70.810898 34.982002 0.588235 0.415686 0.329412
+v 17.653797 -69.034798 30.263802 0.674510 0.478431 0.388235
+v 39.436996 -66.435501 64.968597 0.164706 0.109804 0.082353
+v 33.808598 -70.338699 57.717205 0.364706 0.247059 0.184314
+v 31.909595 -68.409302 47.974705 0.439216 0.301961 0.227451
+v 38.451797 -64.744904 55.703503 0.427451 0.294118 0.219608
+v 28.802397 -72.939499 50.408905 0.372549 0.254902 0.192157
+v 22.955397 -75.486603 43.228905 0.400000 0.274510 0.215686
+v 26.511995 -70.622101 41.049904 0.494118 0.341176 0.262745
+v 24.465696 -76.217796 49.972805 0.345098 0.239216 0.184314
+v 15.571197 -78.986099 40.602001 0.396078 0.278431 0.219608
+v 17.437696 -79.466103 47.124001 0.352941 0.247059 0.196078
+v 28.846695 -74.018898 56.477203 0.164706 0.113725 0.086275
+v 9.321696 -81.938202 48.001999 0.172549 0.129412 0.105882
+v -0.898453 -82.647102 47.089699 0.172549 0.129412 0.105882
+v -0.725759 -82.110100 43.572498 0.400000 0.301961 0.254902
+v 18.763496 -79.316498 51.133400 0.172549 0.117647 0.094118
+v 8.731546 -81.557503 44.441002 0.392157 0.286275 0.235294
+v 27.614496 -65.079002 38.432205 0.596078 0.419608 0.321569
+v 33.274998 -61.490501 43.398605 0.568627 0.400000 0.301961
+v 38.784996 -60.440899 50.047802 0.513725 0.356863 0.266667
+v 42.862595 -58.651798 55.019802 0.490196 0.337255 0.250980
+v 7.726847 -80.575996 38.638500 0.415686 0.301961 0.247059
+v -0.490965 -80.930901 37.912300 0.427451 0.317647 0.262745
+v -0.419731 -79.354401 33.152100 0.513725 0.376471 0.305882
+v -0.332592 -73.782600 27.050400 0.705882 0.505882 0.415686
+v -0.212143 -66.515099 24.546000 0.815686 0.584314 0.501961
+v 11.557498 -67.907898 26.621702 0.749020 0.529412 0.443137
+v 23.830296 -66.563599 34.771904 0.631373 0.447059 0.352941
+v 35.915897 105.133003 38.176804 0.219608 0.152941 0.117647
+v 36.548496 101.879997 36.786003 0.454902 0.309804 0.235294
+v 27.391598 102.010002 31.503502 0.278431 0.188235 0.141176
+v 59.787598 -0.163902 47.832703 0.611765 0.403922 0.321569
+v 50.721996 -9.559180 38.382904 0.721569 0.490196 0.403922
+v 52.439697 -0.358719 38.911705 0.741176 0.501961 0.419608
+v 29.889196 -56.737301 37.395603 0.662745 0.470588 0.360784
+v 26.097795 -54.826500 33.666504 0.694118 0.486275 0.372549
+v 26.293499 -49.727501 32.217205 0.717647 0.501961 0.388235
+v 25.434498 -44.035900 30.291403 0.729412 0.509804 0.400000
+v 31.436096 -44.876701 34.064003 0.737255 0.533333 0.411765
+v 32.500095 -51.078300 37.202503 0.690196 0.490196 0.376471
+v 21.003098 -62.278099 31.444601 0.705882 0.501961 0.400000
+v 26.550097 -59.714100 35.467205 0.666667 0.474510 0.364706
+v 44.267796 -52.222500 50.556103 0.552941 0.384314 0.290196
+v 44.155598 -45.754700 45.234005 0.607843 0.423529 0.325490
+v 39.424698 -54.441200 45.685303 0.588235 0.411765 0.309804
+v 42.849094 -40.630600 40.559803 0.662745 0.462745 0.364706
+v 38.941998 -42.900600 37.800304 0.713725 0.505882 0.400000
+v 52.563396 -19.698900 43.829704 0.650980 0.443137 0.356863
+v 46.654697 -16.837099 36.168205 0.749020 0.517647 0.427451
+v 33.321995 -35.720200 31.409004 0.745098 0.541176 0.427451
+v 32.657997 -40.731899 33.174603 0.752941 0.549020 0.427451
+v 35.472797 -44.317001 36.017105 0.737255 0.533333 0.415686
+v 27.102999 -39.309502 30.560902 0.713725 0.494118 0.388235
+v 21.412498 -21.051500 22.568802 0.733333 0.509804 0.415686
+v 23.988897 -17.175900 24.872402 0.803922 0.549020 0.447059
+v 27.558098 -24.650700 25.424603 0.745098 0.533333 0.443137
+v 27.926598 -35.123001 29.129301 0.701961 0.494118 0.384314
+v 24.306997 -32.355598 25.602802 0.674510 0.478431 0.384314
+v 26.352098 -28.906099 25.178001 0.725490 0.537255 0.439216
+v 22.071098 -41.536701 27.588202 0.670588 0.447059 0.368627
+v 20.085999 -45.811401 26.494501 0.701961 0.486275 0.384314
+v 19.001799 -42.619900 24.806602 0.662745 0.431373 0.364706
+v 28.976398 -21.374100 26.378202 0.788235 0.556863 0.454902
+v 26.341497 -16.211300 25.941402 0.839216 0.584314 0.474510
+v 30.814697 -16.946400 27.290703 0.866667 0.611765 0.501961
+v 15.764998 -20.247000 19.382002 0.698039 0.478431 0.392157
+v 16.598598 -15.898800 21.267502 0.737255 0.486275 0.400000
+v 22.444199 -3.466390 25.169203 0.752941 0.505882 0.415686
+v 21.588697 -7.433040 25.304302 0.760784 0.513725 0.423529
+v 18.939598 -4.099130 23.521101 0.556863 0.321569 0.270588
+v 26.227198 -11.129200 26.175901 0.894118 0.639216 0.533333
+v 23.958097 -13.787900 25.571701 0.843137 0.584314 0.474510
+v 3.233079 -28.114599 12.996900 0.807843 0.517647 0.474510
+v 3.691189 -24.150000 13.560400 0.788235 0.545098 0.450980
+v 7.239779 -23.905701 14.043200 0.760784 0.533333 0.439216
+v 3.876879 -20.045601 14.070800 0.803922 0.580392 0.490196
+v 9.195189 -19.025499 15.793001 0.705882 0.498039 0.411765
+v 3.141149 -17.198000 13.771500 0.807843 0.584314 0.498039
+v 4.931409 -13.967200 13.240000 0.737255 0.509804 0.435294
+v 30.555098 -31.658199 28.330402 0.737255 0.537255 0.439216
+v 36.921795 -39.106701 34.709404 0.749020 0.541176 0.427451
+v 37.097694 -31.720600 32.396603 0.737255 0.521569 0.415686
+v 32.560898 -26.616501 28.413202 0.749020 0.533333 0.435294
+v 10.314199 -9.869830 13.888401 0.564706 0.352941 0.301961
+v 3.716749 -10.896600 9.270600 0.549020 0.333333 0.278431
+v 6.998729 -8.745080 9.093191 0.458824 0.274510 0.247059
+v 11.017399 -7.650950 11.325301 0.407843 0.235294 0.196078
+v 13.094099 -8.179750 13.619401 0.596078 0.372549 0.305882
+v 14.387198 -9.345590 16.544502 0.682353 0.423529 0.349020
+v 14.674398 -10.957500 19.197702 0.619608 0.352941 0.286275
+v 12.273198 -13.638600 18.082401 0.670588 0.415686 0.349020
+v 15.706099 -12.324600 21.310001 0.654902 0.400000 0.341176
+v 0.160743 -11.927500 9.164860 0.631373 0.415686 0.345098
+v 16.748499 -0.088195 17.466702 0.486275 0.262745 0.211765
+v 14.135499 2.999720 13.703901 0.498039 0.278431 0.223529
+v 15.227698 3.521270 17.552402 0.509804 0.286275 0.227451
+v 11.515499 5.295930 9.697881 0.517647 0.298039 0.235294
+v 12.664099 6.361880 14.138000 0.529412 0.305882 0.243137
+v 17.526098 -1.031370 20.210901 0.478431 0.250980 0.203922
+v 18.114098 -7.909870 23.033703 0.556863 0.313725 0.266667
+v 10.384699 8.630760 10.439901 0.541176 0.321569 0.250980
+v 17.828499 0.413114 21.808401 0.541176 0.305882 0.250980
+v 17.929298 -3.542410 20.437902 0.482353 0.247059 0.203922
+v 17.031097 -10.684200 22.274002 0.619608 0.368627 0.313725
+v 0.287526 -2.020300 -3.337250 0.925490 0.694118 0.627451
+v 3.060050 -2.048090 -2.924980 0.894118 0.650980 0.584314
+v 3.007730 -4.729930 -2.346410 0.870588 0.611765 0.537255
+v 5.864850 -1.934710 -1.552539 0.835294 0.592157 0.525490
+v 5.417400 -4.893230 -0.945915 0.788235 0.533333 0.458824
+v 8.198860 -5.353820 2.653151 0.627451 0.403922 0.329412
+v 5.432270 -7.772490 2.088590 0.639216 0.411765 0.337255
+v 6.036009 -8.309330 5.213161 0.458824 0.270588 0.223529
+v 8.222100 -6.896640 5.293671 0.498039 0.305882 0.247059
+v 5.315060 7.954630 2.505800 0.662745 0.400000 0.321569
+v 5.391600 3.642640 -0.798212 0.729412 0.454902 0.372549
+v 3.235490 4.316670 -1.382350 0.764706 0.482353 0.396078
+v 5.431940 1.019950 -1.779530 0.788235 0.521569 0.443137
+v 3.012540 0.964488 -2.729010 0.847059 0.572549 0.494118
+v 3.567950 -7.050370 -0.455861 0.772549 0.517647 0.439216
+v 0.254061 -9.470920 1.815530 0.694118 0.466667 0.388235
+v 3.185970 -9.021570 1.994320 0.686275 0.458824 0.380392
+v 3.347260 -9.952950 5.307401 0.568627 0.360784 0.294118
+v 11.644599 -4.814710 6.525851 0.666667 0.439216 0.360784
+v 10.245199 -6.916610 8.546041 0.431373 0.254902 0.207843
+v 14.322199 -5.140650 10.096601 0.682353 0.439216 0.360784
+v 13.032799 -7.158690 11.593801 0.564706 0.352941 0.286275
+v 16.428497 -5.656990 13.658102 0.650980 0.396078 0.321569
+v 15.041399 -7.855270 14.466301 0.674510 0.423529 0.345098
+v 17.493698 -6.043210 17.118502 0.572549 0.313725 0.254902
+v 16.415197 -8.234700 17.133102 0.619608 0.356863 0.290196
+v 0.234891 4.747230 -1.584250 0.788235 0.498039 0.407843
+v 7.301090 1.952910 -0.069825 0.709804 0.443137 0.364706
+v 9.047320 -0.970925 1.557191 0.690196 0.443137 0.368627
+v 9.465290 3.177850 3.547511 0.596078 0.352941 0.282353
+v 17.660997 -6.569220 20.282202 0.505882 0.258824 0.215686
+v 16.557198 -9.033780 19.871101 0.552941 0.290196 0.235294
+v 20.394499 -10.617700 24.778902 0.776471 0.517647 0.427451
+v 19.250498 -13.611500 23.636002 0.780392 0.513725 0.423529
+v 11.990899 1.078080 6.089581 0.576471 0.337255 0.266667
+v 12.157999 -1.685630 5.705281 0.647059 0.403922 0.329412
+v 8.839929 9.251840 7.807421 0.568627 0.341176 0.262745
+v 8.096309 14.803000 11.047301 0.600000 0.368627 0.290196
+v 11.552299 11.023700 14.935801 0.584314 0.360784 0.278431
+v 8.089608 23.007601 17.162300 0.607843 0.376471 0.290196
+v 12.042598 18.267500 20.407701 0.627451 0.396078 0.305882
+v 21.344799 3.444300 24.364801 0.760784 0.525490 0.435294
+v 10.378798 43.596600 19.092800 0.760784 0.545098 0.439216
+v 11.674199 50.650799 15.859901 0.796078 0.596078 0.509804
+v 54.439495 58.174599 40.267605 0.525490 0.352941 0.262745
+v 56.231796 64.326599 44.901005 0.525490 0.349020 0.258824
+v 20.091297 46.555901 20.626602 0.615686 0.435294 0.352941
+v 12.458998 40.488800 23.149502 0.682353 0.470588 0.364706
+v 11.517699 58.712601 14.732701 0.894118 0.666667 0.576471
+v 20.941198 69.476898 17.756903 0.811765 0.568627 0.458824
+v 28.594099 70.756203 20.988201 0.768627 0.537255 0.427451
+v 36.831398 72.183800 26.344303 0.705882 0.490196 0.380392
+v 44.649097 71.571800 32.518906 0.650980 0.447059 0.337255
+v 44.312595 65.052498 30.244703 0.650980 0.450980 0.349020
+v 51.160194 68.888397 38.786102 0.580392 0.392157 0.290196
+v 50.121696 63.216999 35.800903 0.592157 0.400000 0.301961
+v 29.676498 38.193501 27.577202 0.278431 0.203922 0.172549
+v 32.242195 35.520000 28.930403 0.176471 0.149020 0.133333
+v 36.059795 38.007198 28.101904 0.337255 0.254902 0.223529
+v 29.195498 28.762300 30.062502 0.537255 0.407843 0.376471
+v 35.387295 30.454100 30.872303 0.494118 0.427451 0.419608
+v 40.619995 36.623299 30.930103 0.376471 0.290196 0.262745
+v 40.689995 30.856199 33.447403 0.560784 0.435294 0.415686
+v 46.166798 34.721901 35.938004 0.427451 0.274510 0.219608
+v 24.791199 28.750900 30.347101 0.631373 0.439216 0.380392
+v 23.558298 30.911301 30.865202 0.654902 0.525490 0.490196
+v 23.990099 35.138500 30.007702 0.588235 0.525490 0.505882
+v 18.925999 31.543200 29.964102 0.607843 0.411765 0.345098
+v 22.978798 22.609301 29.898302 0.698039 0.478431 0.415686
+v 44.176495 24.024099 36.367702 0.666667 0.462745 0.368627
+v 48.844097 28.759600 40.696102 0.568627 0.372549 0.290196
+v 29.935898 20.776899 30.510502 0.764706 0.541176 0.462745
+v 37.725395 21.069901 32.600403 0.768627 0.552941 0.450980
+v 43.673397 41.639000 29.921003 0.639216 0.447059 0.364706
+v 30.249598 43.423698 24.863802 0.698039 0.498039 0.396078
+v 21.971298 38.089298 28.511002 0.552941 0.376471 0.305882
+v 18.851599 37.250599 29.058102 0.600000 0.403922 0.317647
+v 26.141699 38.694302 27.701101 0.415686 0.305882 0.258824
+v 24.366098 42.716400 25.250301 0.670588 0.470588 0.364706
+v 33.047497 40.919201 25.876904 0.588235 0.415686 0.341176
+v 38.202995 45.220299 25.513803 0.741176 0.541176 0.447059
+v 37.181396 41.326099 26.587204 0.592157 0.415686 0.341176
+v 40.767696 39.773300 28.946104 0.533333 0.368627 0.305882
+v 17.566698 40.536701 25.680403 0.682353 0.478431 0.372549
+v 12.599898 34.387402 26.919203 0.635294 0.439216 0.356863
+v 9.244298 36.241699 22.858601 0.670588 0.454902 0.349020
+v 42.106094 27.525101 34.601604 0.588235 0.396078 0.337255
+v 9.833448 28.316700 23.639999 0.592157 0.392157 0.298039
+v 18.639698 24.671700 29.695803 0.650980 0.447059 0.376471
+v 17.292599 20.688499 27.482101 0.654902 0.439216 0.341176
+v 13.333098 24.688499 26.033302 0.607843 0.407843 0.305882
+v 22.784698 17.533800 28.735502 0.721569 0.498039 0.407843
+v 30.601099 15.688600 30.290201 0.780392 0.560784 0.466667
+v 41.169495 16.181299 33.723103 0.792157 0.564706 0.458824
+v 47.120296 20.681999 37.970406 0.709804 0.501961 0.400000
+v 51.931698 25.841200 43.142902 0.639216 0.443137 0.341176
+v 52.340096 32.697899 43.622303 0.576471 0.384314 0.298039
+v 55.356895 32.597599 46.411205 0.619608 0.439216 0.341176
+v 53.222797 37.287899 42.089905 0.568627 0.392157 0.301961
+v 29.678698 24.733801 30.073902 0.717647 0.501961 0.431373
+v 36.489197 25.085699 31.599504 0.698039 0.498039 0.427451
+v 7.209608 -47.131500 19.961300 0.694118 0.474510 0.392157
+v 14.446698 -46.892300 22.922901 0.701961 0.486275 0.392157
+v 14.611198 -50.406300 25.080801 0.741176 0.521569 0.407843
+v 59.776695 32.152901 51.172405 0.615686 0.435294 0.333333
+v 55.757698 22.840000 45.449802 0.650980 0.447059 0.341176
+v 50.009796 17.205099 38.838005 0.725490 0.501961 0.396078
+v 41.713795 8.508140 32.452805 0.839216 0.580392 0.486275
+v 57.126797 40.041698 45.909004 0.552941 0.380392 0.294118
+v 60.104397 43.092098 50.342705 0.509804 0.345098 0.262745
+v 54.672398 42.407398 40.515404 0.556863 0.380392 0.305882
+v 56.906197 46.631001 42.925304 0.462745 0.305882 0.239216
+v 51.822495 43.786900 36.258904 0.596078 0.415686 0.337255
+v 54.271397 50.864399 37.835804 0.419608 0.282353 0.223529
+v 47.592297 46.765598 30.486204 0.627451 0.454902 0.384314
+v 49.821495 53.293598 31.830803 0.427451 0.298039 0.243137
+v 42.391796 49.445400 25.742804 0.607843 0.454902 0.388235
+v 44.034695 54.943100 26.506004 0.443137 0.317647 0.266667
+v 36.751995 50.112900 22.968603 0.545098 0.407843 0.349020
+v 37.753296 55.541100 22.525805 0.490196 0.364706 0.313725
+v 28.692497 48.042801 21.970001 0.600000 0.435294 0.356863
+v 31.105598 56.180599 19.828001 0.596078 0.450980 0.392157
+v 36.435097 81.925400 28.781404 0.682353 0.470588 0.364706
+v 45.338295 80.322098 35.563904 0.603922 0.411765 0.305882
+v 24.592999 80.095299 21.969002 0.772549 0.541176 0.427451
+v 11.213599 69.043297 15.977401 0.835294 0.588235 0.474510
+v 11.825998 81.413200 18.962801 0.803922 0.564706 0.447059
+v 21.538898 53.003700 17.177603 0.588235 0.439216 0.380392
+v -0.179365 43.542702 17.002100 0.898039 0.666667 0.564706
+v 5.625159 37.419102 18.996799 0.803922 0.576471 0.466667
+v 4.198629 23.955999 12.407200 0.686275 0.435294 0.345098
+v 14.535299 -2.114900 9.443011 0.631373 0.380392 0.309804
+v 15.685598 8.142320 20.454601 0.658824 0.427451 0.337255
+v 30.598497 1.488610 27.147802 0.839216 0.576471 0.490196
+v 29.978397 -6.397050 26.571701 0.894118 0.635294 0.545098
+v 41.297398 -1.405200 31.022003 0.854902 0.596078 0.509804
+v 36.111397 -6.540340 28.005903 0.882353 0.623529 0.537255
+v 44.276794 -9.991890 32.788902 0.811765 0.568627 0.478431
+v 36.580196 -12.147500 28.853804 0.874510 0.623529 0.525490
+v 23.545498 26.550501 30.193302 0.670588 0.454902 0.392157
+v 7.536978 -50.700600 22.940800 0.737255 0.513725 0.407843
+v 0.049966 -50.745201 22.357901 0.713725 0.490196 0.403922
+v -0.059187 -47.707500 19.745001 0.662745 0.450980 0.376471
+v 13.614799 -61.189201 26.770203 0.772549 0.549020 0.447059
+v 7.402448 -54.763500 24.320801 0.792157 0.549020 0.443137
+v 5.676798 -60.044102 24.120001 0.815686 0.568627 0.478431
+v 0.007680 -58.305000 23.528999 0.823529 0.568627 0.478431
+v 14.550098 -55.003899 26.621601 0.780392 0.549020 0.431373
+v 20.750698 -49.841400 28.390602 0.729412 0.505882 0.396078
+v 14.341599 -43.669201 21.142101 0.690196 0.443137 0.392157
+v 9.106318 -44.220402 18.280300 0.749020 0.454902 0.427451
+v 4.624769 -44.514198 17.213200 0.768627 0.458824 0.439216
+v 13.494699 1.203290 9.375581 0.541176 0.305882 0.247059
+v 17.587399 -3.090150 17.170603 0.521569 0.282353 0.231373
+v 15.390899 0.616895 13.529201 0.525490 0.290196 0.239216
+v 16.498499 -2.610490 13.351402 0.580392 0.333333 0.270588
+v 0.114789 -17.205601 13.556900 0.803922 0.576471 0.490196
+v 0.213039 -10.739900 5.333460 0.631373 0.419608 0.345098
+v 0.155695 9.698840 1.605760 0.737255 0.458824 0.372549
+v 63.699497 35.875702 57.276005 0.541176 0.364706 0.274510
+v 62.952995 26.737499 54.915302 0.588235 0.400000 0.301961
+v 62.913197 46.593300 56.027405 0.486275 0.321569 0.239216
+v 66.067696 49.149700 63.298607 0.435294 0.282353 0.207843
+v 67.025894 36.883900 64.329010 0.478431 0.313725 0.235294
+v 66.947090 22.464199 62.047707 0.505882 0.325490 0.243137
+v 62.186794 10.766600 50.973103 0.576471 0.376471 0.290196
+v 68.964989 11.545400 68.556404 0.415686 0.266667 0.200000
+v 64.644791 3.438430 56.958504 0.498039 0.317647 0.243137
+v 7.315678 30.263700 20.278500 0.635294 0.407843 0.309804
+v 16.478199 14.480500 23.730602 0.674510 0.435294 0.341176
+v 22.498598 11.176800 26.488401 0.752941 0.505882 0.411765
+v 30.975899 9.046680 28.818901 0.800000 0.545098 0.447059
+v 59.705097 18.493999 48.250504 0.619608 0.415686 0.317647
+v 53.774796 10.607700 40.580803 0.741176 0.505882 0.411765
+v 4.194539 31.168200 16.627800 0.733333 0.498039 0.388235
+v -0.049233 31.606899 15.159500 0.800000 0.552941 0.435294
+v 60.551994 58.758701 51.876305 0.482353 0.313725 0.231373
+v 64.570694 60.979000 60.018402 0.403922 0.266667 0.196078
+v 58.582897 51.884102 46.769802 0.482353 0.317647 0.239216
+v 58.461395 70.455803 49.594505 0.466667 0.313725 0.231373
+v 52.436497 76.538399 42.343403 0.533333 0.356863 0.262745
+v -0.208444 49.913601 15.256100 0.917647 0.698039 0.611765
+v -0.124523 58.086498 14.326200 0.905882 0.674510 0.584314
+v 0.274219 81.382401 18.191799 0.819608 0.576471 0.458824
+v 0.481933 93.290398 21.740499 0.725490 0.498039 0.384314
+v 12.405998 93.661400 22.874903 0.713725 0.486275 0.376471
+v 24.880598 93.906502 26.578302 0.658824 0.447059 0.341176
+v 36.480595 93.078102 32.634003 0.576471 0.388235 0.294118
+v 46.004696 90.203003 39.649605 0.505882 0.345098 0.258824
+v 53.584496 85.144096 46.494904 0.450980 0.305882 0.223529
+v 62.545998 71.367798 56.403603 0.364706 0.250980 0.188235
+v 59.255596 78.845100 52.443905 0.400000 0.274510 0.203922
+v 61.191795 85.050301 57.241005 0.333333 0.235294 0.180392
+v 65.452393 75.230003 61.807304 0.286275 0.207843 0.160784
+v 68.381790 63.713902 67.643311 0.266667 0.188235 0.149020
+v 69.324196 50.443100 71.447411 0.341176 0.227451 0.172549
+v 70.128990 37.903400 72.923409 0.360784 0.239216 0.180392
+v 70.487595 24.768299 72.393105 0.396078 0.250980 0.192157
+v 10.803699 -24.072800 15.435301 0.713725 0.501961 0.407843
+v 15.684198 -24.840200 18.155502 0.698039 0.494118 0.403922
+v 14.923498 -28.631399 17.459002 0.729412 0.498039 0.431373
+v 19.121199 -30.573601 20.995502 0.694118 0.478431 0.403922
+v 21.119598 -26.506599 21.583101 0.701961 0.509804 0.423529
+v 36.499996 -22.712601 30.213703 0.811765 0.572549 0.466667
+v 40.448395 -36.176701 36.400604 0.725490 0.509804 0.407843
+v 44.144596 -32.603699 38.731205 0.705882 0.490196 0.392157
+v 38.536495 -47.817600 40.317505 0.666667 0.474510 0.364706
+v 46.546295 -37.311100 43.387104 0.635294 0.439216 0.349020
+v 50.373398 -34.235699 47.127705 0.611765 0.423529 0.333333
+v 49.724796 -40.818298 50.185303 0.588235 0.403922 0.317647
+v 49.255295 -27.889099 42.907104 0.658824 0.454902 0.360784
+v 44.257797 -23.479799 35.807602 0.752941 0.525490 0.427451
+v 40.645798 -27.765900 34.063705 0.764706 0.537255 0.431373
+v 40.754898 -19.093399 32.012905 0.815686 0.576471 0.478431
+v 10.416199 -27.973200 14.961201 0.756863 0.498039 0.443137
+v 0.075350 -28.306400 12.898400 0.803922 0.521569 0.466667
+v 0.092755 -24.430799 13.505000 0.772549 0.529412 0.443137
+v 0.110785 -20.513000 13.908800 0.807843 0.588235 0.501961
+v 0.085609 -54.512001 23.610901 0.784314 0.537255 0.443137
+v 20.909399 -54.946800 30.047201 0.729412 0.509804 0.392157
+v 35.645298 -55.715099 42.223003 0.623529 0.439216 0.337255
+v 49.814896 -48.565498 56.933704 0.517647 0.356863 0.274510
+v 47.977795 -55.414200 62.039703 0.443137 0.301961 0.231373
+v 55.688496 -28.994600 53.447903 0.560784 0.380392 0.301961
+v 55.983391 -43.000198 65.692207 0.450980 0.305882 0.239216
+v 56.362797 -36.061699 59.322903 0.517647 0.349020 0.274510
+v 57.892796 -19.573200 52.540302 0.560784 0.376471 0.294118
+v 70.365593 -2.993800 89.379608 0.321569 0.211765 0.164706
+v 71.177193 8.937180 81.271606 0.321569 0.211765 0.164706
+v 72.558990 10.622100 91.867805 0.298039 0.200000 0.156863
+v 66.125992 -21.471800 81.920410 0.341176 0.223529 0.168627
+v 67.528091 -10.306600 77.117210 0.364706 0.239216 0.180392
+v 61.701691 -27.660801 67.740509 0.443137 0.294118 0.227451
+v 68.337189 -0.022244 71.967606 0.380392 0.243137 0.188235
+v 63.424397 -15.896200 64.452606 0.443137 0.290196 0.219608
+v 68.125694 -16.648800 92.619408 0.301961 0.200000 0.156863
+v 63.768192 -32.212200 86.796310 0.305882 0.203922 0.156863
+v 61.167294 -36.372501 75.628105 0.376471 0.250980 0.192157
+v 59.626293 -41.868698 80.668411 0.333333 0.223529 0.172549
+v 64.162796 -6.066620 60.428703 0.454902 0.294118 0.223529
+v 57.393696 -11.239100 47.991703 0.611765 0.411765 0.329412
+v 72.524994 24.387699 82.025009 0.282353 0.188235 0.145098
+v 73.856789 35.723499 88.540108 0.105882 0.074510 0.062745
+v 73.683792 23.761801 91.300209 0.243137 0.164706 0.129412
+v 74.501190 30.125500 94.839706 0.094118 0.062745 0.050980
+v 74.034592 22.480499 96.303810 0.141176 0.098039 0.078431
+v 72.831192 7.859240 98.770004 0.149020 0.101961 0.082353
+v 69.296593 -13.425300 99.241905 0.305882 0.200000 0.160784
+v 71.395790 -3.606020 100.302010 0.325490 0.215686 0.172549
+v 71.129791 -7.143250 103.242004 0.188235 0.125490 0.101961
+v 68.107590 -18.211399 101.004005 0.133333 0.086275 0.070588
+v 72.363594 -0.137348 102.838005 0.176471 0.117647 0.094118
+v 46.213596 99.739601 44.501404 0.388235 0.266667 0.200000
+v 54.685898 92.834099 51.120205 0.376471 0.258824 0.192157
+v 55.596695 97.970802 54.777103 0.294118 0.207843 0.160784
+v 59.781796 92.442200 58.018204 0.125490 0.090196 0.066667
+v 50.586895 101.808998 50.572002 0.172549 0.121569 0.094118
+v 43.422997 104.478996 44.205505 0.184314 0.125490 0.098039
+v 72.007690 49.799099 78.898109 0.250980 0.176471 0.137255
+v 73.057594 49.127201 82.269409 0.094118 0.066667 0.054902
+v 49.949097 58.855202 33.782906 0.564706 0.388235 0.301961
+v 44.336697 60.042801 28.311203 0.603922 0.419608 0.337255
+v 37.959198 59.937000 23.450504 0.674510 0.482353 0.400000
+v 4.464459 16.161301 7.486950 0.682353 0.423529 0.341176
+v 0.094371 16.649401 6.087460 0.745098 0.466667 0.376471
+v 0.014745 24.425800 10.934700 0.745098 0.482353 0.384314
+v 71.478493 58.516998 75.568504 0.105882 0.074510 0.058824
+v 68.260490 72.263603 66.620407 0.137255 0.101961 0.082353
+v 70.731094 66.735497 71.686806 0.109804 0.082353 0.066667
+v 72.507889 38.181301 81.341507 0.254902 0.176471 0.137255
+v 64.500496 82.174896 61.573006 0.149020 0.109804 0.082353
+v 55.767296 99.280998 55.781605 0.145098 0.101961 0.078431
+v 12.876298 100.102997 25.744701 0.317647 0.215686 0.164706
+v 0.286601 -4.793040 -2.721520 0.894118 0.643137 0.568627
+v 64.638489 -29.722000 98.167007 0.121569 0.082353 0.062745
+v 58.149193 -45.228298 86.664307 0.290196 0.196078 0.152941
+v 62.356594 -36.605999 93.365707 0.274510 0.184314 0.141176
+v 60.716892 -40.186600 93.595604 0.113725 0.078431 0.058824
+v 56.109493 -48.650299 86.931511 0.141176 0.098039 0.074510
+v 49.385094 -57.278099 77.067108 0.160784 0.109804 0.082353
+v 66.355392 -24.387800 96.374504 0.270588 0.184314 0.141176
+v 37.257298 34.215500 30.609003 0.415686 0.392157 0.388235
+v 39.520298 33.790501 31.976805 0.529412 0.494118 0.490196
+v 27.428999 33.649700 29.901602 0.372549 0.333333 0.309804
+v 23.755198 -35.746101 28.257301 0.482353 0.278431 0.235294
+v 3.793149 -35.116299 16.927900 0.600000 0.278431 0.294118
+v 3.855958 -38.129200 17.080799 0.756863 0.376471 0.407843
+v -0.023884 -38.223301 16.909401 0.749020 0.368627 0.400000
+v 8.071998 -35.035198 18.102501 0.588235 0.266667 0.286275
+v 8.431998 -37.966801 18.149799 0.717647 0.352941 0.384314
+v 13.239598 -35.231899 20.689901 0.545098 0.262745 0.274510
+v 13.372499 -37.816101 20.728703 0.631373 0.317647 0.337255
+v 17.666399 -35.273201 23.658503 0.447059 0.227451 0.227451
+v 17.640099 -37.751598 24.088802 0.556863 0.282353 0.286275
+v 21.365198 -34.941399 26.083202 0.478431 0.266667 0.231373
+v 21.738897 -38.277302 27.387302 0.564706 0.325490 0.298039
+v 21.377197 -34.903000 26.050001 0.490196 0.278431 0.239216
+v -0.125513 -44.742699 17.141100 0.749020 0.454902 0.419608
+v 14.317698 -31.063400 17.972801 0.662745 0.403922 0.364706
+v 6.533319 -27.864201 13.520501 0.788235 0.505882 0.458824
+v 17.674997 -35.227402 23.629501 0.427451 0.219608 0.211765
+v 18.364597 -33.324001 22.496202 0.580392 0.341176 0.301961
+v 13.245798 -35.168499 20.655602 0.537255 0.258824 0.270588
+v 13.862498 -33.057598 19.452902 0.596078 0.333333 0.313725
+v 8.065038 -34.963299 18.048201 0.580392 0.270588 0.282353
+v 9.277578 -32.971199 17.116100 0.631373 0.349020 0.337255
+v 3.799159 -35.048901 16.841700 0.600000 0.278431 0.294118
+v 5.629269 -33.251099 16.003500 0.643137 0.349020 0.341176
+v 2.758119 -33.165501 15.103900 0.650980 0.345098 0.341176
+v 0.038323 -35.330101 16.649599 0.396078 0.176471 0.192157
+v 0.067189 -33.274799 14.942100 0.662745 0.345098 0.352941
+v 2.880549 -31.155199 13.597900 0.701961 0.388235 0.380392
+v 5.936328 -30.985800 14.264301 0.694118 0.396078 0.380392
+v 4.098669 -41.269699 16.459999 0.811765 0.458824 0.486275
+v 8.892108 -41.014599 17.645000 0.760784 0.427451 0.450980
+v 9.781240 -30.931801 15.664701 0.682353 0.400000 0.376471
+v 13.905798 -40.587799 20.457802 0.658824 0.360784 0.364706
+v 18.077698 -39.992001 24.048601 0.603922 0.341176 0.325490
+v 0.069898 -31.269300 13.405600 0.725490 0.411765 0.407843
+v 37.322296 65.013603 24.625504 0.709804 0.498039 0.396078
+v 29.652199 63.115200 19.714302 0.780392 0.560784 0.466667
+v 21.287199 60.616798 16.368002 0.847059 0.623529 0.533333
+v 0.127883 -14.200400 12.254200 0.741176 0.509804 0.435294
+v 0.278404 1.040420 -3.071150 0.870588 0.596078 0.513725
+v -0.116712 37.803699 17.313200 0.882353 0.650980 0.533333
+v 0.279360 -7.378550 -0.992634 0.819608 0.560784 0.478431
+v 0.046502 68.758400 15.460200 0.854902 0.607843 0.494118
+v 0.599951 99.454498 24.243299 0.349020 0.235294 0.180392
+v 0.031221 -35.395699 16.746401 0.458824 0.203922 0.219608
+v -0.106864 -41.376099 16.290199 0.800000 0.447059 0.474510
+v -53.841106 -48.983299 71.426689 0.407843 0.274510 0.215686
+v -51.275307 -53.996498 75.538391 0.368627 0.247059 0.192157
+v -44.535206 -60.645199 65.560791 0.411765 0.274510 0.211765
+v -18.750103 -74.796997 35.786999 0.529412 0.372549 0.298039
+v -14.085703 -77.391403 34.978100 0.509804 0.364706 0.290196
+v -11.957403 -73.963402 30.096098 0.635294 0.450980 0.368627
+v -6.566503 -77.262100 30.449800 0.596078 0.431373 0.349020
+v -7.564453 -78.871101 33.695099 0.501961 0.360784 0.290196
+v -22.016403 -70.478699 35.529198 0.588235 0.415686 0.329412
+v -17.863401 -68.837303 30.791098 0.674510 0.478431 0.388235
+v -39.540703 -65.852203 65.266602 0.180392 0.121569 0.090196
+v -33.939205 -69.790604 58.118694 0.388235 0.262745 0.200000
+v -31.925804 -67.925903 48.449497 0.458824 0.317647 0.239216
+v -38.444904 -64.204102 56.125298 0.450980 0.305882 0.231373
+v -28.939505 -72.407097 50.816597 0.392157 0.270588 0.203922
+v -23.188004 -74.982597 43.634598 0.415686 0.290196 0.223529
+v -26.559404 -70.188103 41.544697 0.505882 0.352941 0.270588
+v -24.695004 -75.705597 50.416195 0.364706 0.250980 0.192157
+v -16.072004 -78.604698 40.981701 0.403922 0.282353 0.223529
+v -17.844904 -79.063103 47.658199 0.360784 0.250980 0.196078
+v -29.056807 -73.493698 56.917194 0.176471 0.117647 0.090196
+v -10.376904 -81.684601 48.519402 0.168627 0.121569 0.101961
+v -19.158804 -78.889801 51.744801 0.176471 0.121569 0.094118
+v -9.669264 -81.344200 44.934101 0.376471 0.274510 0.223529
+v -27.571703 -64.815102 39.005997 0.603922 0.423529 0.329412
+v -33.198803 -61.133202 43.968197 0.576471 0.403922 0.305882
+v -38.691704 -59.988998 50.588497 0.525490 0.364706 0.274510
+v -42.734406 -58.145699 55.489697 0.501961 0.341176 0.258824
+v -8.533234 -80.387604 38.906601 0.407843 0.294118 0.239216
+v -11.915502 -67.795502 26.995598 0.745098 0.529412 0.443137
+v -23.853804 -66.357597 35.367195 0.635294 0.447059 0.352941
+v -34.301003 104.745003 38.021896 0.207843 0.141176 0.109804
+v -35.090004 101.537003 36.596096 0.427451 0.282353 0.215686
+v -26.006802 101.713997 31.525198 0.270588 0.176471 0.133333
+v -59.540703 -0.172551 48.112595 0.619608 0.403922 0.325490
+v -50.470104 -9.587020 38.842495 0.729412 0.490196 0.411765
+v -52.236305 -0.444375 39.310497 0.745098 0.501961 0.419608
+v -29.805405 -56.547798 37.997498 0.666667 0.474510 0.364706
+v -26.022703 -54.744801 34.242695 0.694118 0.490196 0.376471
+v -26.218403 -49.663700 32.767998 0.717647 0.498039 0.388235
+v -25.394102 -44.041801 30.750198 0.729412 0.505882 0.396078
+v -31.448503 -44.790001 34.639797 0.737255 0.525490 0.403922
+v -32.419804 -50.899601 37.823597 0.690196 0.490196 0.376471
+v -21.044302 -62.170700 31.980398 0.705882 0.498039 0.400000
+v -26.501503 -59.568001 36.049995 0.670588 0.474510 0.368627
+v -44.034306 -51.844898 51.117294 0.560784 0.384314 0.294118
+v -43.882004 -45.489799 45.821396 0.611765 0.419608 0.329412
+v -39.261204 -54.099098 46.284496 0.592157 0.411765 0.309804
+v -42.625404 -40.450100 41.156296 0.662745 0.458824 0.360784
+v -38.801704 -42.761002 38.411594 0.713725 0.501961 0.396078
+v -52.231606 -19.653799 44.279896 0.658824 0.443137 0.356863
+v -46.410305 -16.803400 36.662895 0.756863 0.517647 0.427451
+v -33.261505 -35.711102 31.876297 0.741176 0.537255 0.423529
+v -32.671204 -40.674500 33.693596 0.749020 0.545098 0.423529
+v -35.453705 -44.188400 36.643997 0.733333 0.529412 0.411765
+v -27.096502 -39.330601 30.955198 0.713725 0.498039 0.384314
+v -21.293402 -21.040701 22.753899 0.729412 0.498039 0.407843
+v -23.889301 -17.153200 25.090498 0.796078 0.537255 0.431373
+v -27.442001 -24.677700 25.678598 0.741176 0.529412 0.435294
+v -27.894802 -35.143299 29.500797 0.698039 0.494118 0.384314
+v -24.245901 -32.390999 25.918598 0.666667 0.470588 0.380392
+v -26.250002 -28.942699 25.473698 0.721569 0.529412 0.431373
+v -22.010002 -41.590900 27.971397 0.670588 0.450980 0.364706
+v -20.023802 -45.808498 26.881199 0.705882 0.486275 0.384314
+v -18.923801 -42.662899 25.164799 0.666667 0.435294 0.364706
+v -28.864202 -21.376200 26.642797 0.784314 0.545098 0.443137
+v -26.229301 -16.210501 26.192198 0.827451 0.568627 0.454902
+v -30.681902 -16.933201 27.620897 0.858824 0.603922 0.490196
+v -15.621302 -20.221901 19.470098 0.690196 0.470588 0.380392
+v -16.465702 -15.840100 21.345999 0.729412 0.474510 0.384314
+v -22.337402 -3.399040 25.406399 0.741176 0.494118 0.396078
+v -21.458002 -7.348170 25.506098 0.721569 0.474510 0.380392
+v -18.854101 -4.005630 23.601898 0.533333 0.301961 0.250980
+v -26.091501 -11.087000 26.476297 0.878431 0.623529 0.513725
+v -23.841803 -13.780800 25.798899 0.831373 0.572549 0.458824
+v -3.088731 -28.148701 13.002100 0.811765 0.521569 0.478431
+v -3.510681 -24.156099 13.543200 0.788235 0.541176 0.450980
+v -7.061972 -23.912500 14.032299 0.764706 0.529412 0.435294
+v -3.687661 -20.046000 14.031400 0.807843 0.584314 0.494118
+v -9.043321 -19.022600 15.774699 0.705882 0.494118 0.403922
+v -2.931611 -17.201000 13.721800 0.807843 0.584314 0.494118
+v -4.743171 -14.022100 13.188100 0.737255 0.505882 0.431373
+v -30.459501 -31.690300 28.703999 0.729412 0.537255 0.435294
+v -36.833103 -39.026501 35.269897 0.749020 0.537255 0.423529
+v -36.962105 -31.691099 32.883995 0.741176 0.517647 0.411765
+v -32.433002 -26.637400 28.764599 0.749020 0.529412 0.427451
+v -10.186301 -10.045900 13.821699 0.560784 0.341176 0.290196
+v -3.445531 -10.998200 9.252610 0.556863 0.337255 0.278431
+v -6.762481 -8.908630 9.055569 0.494118 0.294118 0.258824
+v -10.854001 -7.895510 11.215299 0.427451 0.250980 0.211765
+v -12.950301 -8.438200 13.560799 0.588235 0.368627 0.305882
+v -14.310402 -9.532510 16.465097 0.674510 0.411765 0.333333
+v -14.624502 -11.047600 19.142298 0.615686 0.345098 0.282353
+v -12.154902 -13.660100 18.041199 0.662745 0.403922 0.337255
+v -15.637602 -12.306800 21.315199 0.635294 0.376471 0.313725
+v -16.678001 0.018672 17.475899 0.454902 0.239216 0.188235
+v -14.077101 3.077540 13.715799 0.470588 0.254902 0.203922
+v -15.178302 3.616140 17.563799 0.490196 0.270588 0.215686
+v -11.450801 5.402890 9.661229 0.498039 0.278431 0.219608
+v -12.646701 6.457730 14.109399 0.513725 0.294118 0.231373
+v -17.444702 -0.924688 20.193298 0.450980 0.227451 0.184314
+v -18.059002 -7.877630 23.064198 0.529412 0.286275 0.243137
+v -10.368801 8.722010 10.384299 0.521569 0.301961 0.235294
+v -17.744202 0.517129 21.854698 0.521569 0.294118 0.239216
+v -17.907402 -3.455530 20.442198 0.458824 0.231373 0.188235
+v -16.974201 -10.677600 22.292898 0.596078 0.341176 0.286275
+v -2.506120 -2.028510 -3.080180 0.913725 0.674510 0.607843
+v -2.469770 -4.768590 -2.486050 0.886275 0.623529 0.552941
+v -5.439900 -1.886710 -1.785390 0.847059 0.584314 0.517647
+v -4.991440 -4.960640 -1.139691 0.803922 0.541176 0.462745
+v -7.917010 -5.451350 2.487329 0.647059 0.415686 0.341176
+v -5.044560 -7.893640 1.983989 0.650980 0.415686 0.349020
+v -5.685171 -8.434240 5.155859 0.486275 0.290196 0.243137
+v -7.915720 -7.024910 5.173709 0.537255 0.337255 0.282353
+v -5.069190 8.041960 2.428190 0.662745 0.396078 0.317647
+v -5.017550 3.745630 -0.921486 0.737255 0.454902 0.372549
+v -2.789870 4.372350 -1.462200 0.772549 0.486275 0.396078
+v -4.999330 1.117930 -1.968431 0.792157 0.509804 0.427451
+v -2.481880 1.025610 -2.840810 0.854902 0.576471 0.494118
+v -3.088550 -7.134860 -0.568535 0.784314 0.529412 0.447059
+v -2.741080 -9.109190 1.948480 0.694118 0.462745 0.384314
+v -2.959080 -10.054000 5.285800 0.576471 0.360784 0.298039
+v -11.491201 -4.921930 6.367449 0.674510 0.447059 0.372549
+v -10.020901 -7.086960 8.412829 0.474510 0.290196 0.243137
+v -14.259301 -5.239610 9.939149 0.690196 0.443137 0.368627
+v -12.878401 -7.387150 11.456599 0.564706 0.352941 0.290196
+v -16.464901 -5.716880 13.556098 0.647059 0.388235 0.317647
+v -14.983801 -8.065290 14.371499 0.670588 0.415686 0.337255
+v -17.583902 -6.038910 17.100498 0.560784 0.305882 0.247059
+v -16.457602 -8.372230 17.068798 0.623529 0.352941 0.286275
+v -6.973730 2.091660 -0.242824 0.705882 0.435294 0.356863
+v -8.818600 -0.891477 1.383239 0.690196 0.439216 0.364706
+v -9.290710 3.329020 3.458919 0.580392 0.337255 0.266667
+v -17.710503 -6.541460 20.280298 0.498039 0.250980 0.207843
+v -16.597502 -9.103660 19.840698 0.560784 0.290196 0.239216
+v -20.254002 -10.584600 24.919098 0.725490 0.466667 0.380392
+v -19.110601 -13.563800 23.751698 0.756863 0.490196 0.400000
+v -11.853701 1.210450 5.993569 0.552941 0.313725 0.247059
+v -12.033501 -1.648010 5.569239 0.631373 0.388235 0.313725
+v -8.771261 9.366440 7.745239 0.549020 0.317647 0.247059
+v -8.091181 14.909600 10.967199 0.588235 0.352941 0.278431
+v -11.574701 11.120500 14.904899 0.564706 0.341176 0.262745
+v -8.252582 23.095100 17.156300 0.592157 0.356863 0.274510
+v -12.164402 18.366899 20.500298 0.607843 0.372549 0.286275
+v -21.284002 3.497090 24.570698 0.768627 0.525490 0.431373
+v -10.742502 43.732601 19.227800 0.772549 0.552941 0.447059
+v -12.018201 50.872398 15.973799 0.796078 0.596078 0.513725
+v -53.977802 58.171299 39.694695 0.501961 0.325490 0.250980
+v -55.620903 64.281502 44.285595 0.509804 0.329412 0.247059
+v -20.308903 46.723099 20.792599 0.607843 0.427451 0.345098
+v -12.843102 40.605900 23.333698 0.694118 0.474510 0.368627
+v -11.662601 58.885700 14.851099 0.890196 0.662745 0.576471
+v -20.507902 69.580101 17.878298 0.800000 0.549020 0.435294
+v -27.933802 70.843803 20.968597 0.749020 0.509804 0.400000
+v -36.014503 72.235001 26.102497 0.690196 0.466667 0.356863
+v -43.836502 71.610802 32.086895 0.631373 0.423529 0.317647
+v -43.620102 65.109001 29.763796 0.635294 0.427451 0.329412
+v -50.451702 68.894699 38.239597 0.564706 0.372549 0.278431
+v -49.542004 63.241699 35.253395 0.576471 0.380392 0.290196
+v -29.960102 38.037498 27.851099 0.282353 0.203922 0.168627
+v -32.476303 35.348900 29.197298 0.176471 0.149020 0.133333
+v -36.246204 37.764400 28.355696 0.329412 0.254902 0.223529
+v -29.328802 28.733900 30.342098 0.529412 0.392157 0.360784
+v -35.523403 30.304701 31.130497 0.482353 0.411765 0.400000
+v -40.727005 36.324501 31.155497 0.392157 0.313725 0.294118
+v -40.839203 30.600300 33.689297 0.568627 0.435294 0.411765
+v -46.191402 34.452000 36.131695 0.427451 0.274510 0.223529
+v -24.977001 28.765301 30.636297 0.627451 0.431373 0.372549
+v -23.804102 30.909100 31.155798 0.686275 0.556863 0.521569
+v -24.319902 35.130699 30.242397 0.592157 0.521569 0.505882
+v -19.257402 31.576700 30.228998 0.611765 0.411765 0.341176
+v -23.152302 22.654400 30.191898 0.721569 0.498039 0.431373
+v -44.272903 23.796400 36.654297 0.666667 0.454902 0.360784
+v -48.903404 28.476500 40.922897 0.552941 0.352941 0.274510
+v -30.033503 20.755199 30.809198 0.784314 0.556863 0.474510
+v -37.799706 20.942499 32.892296 0.772549 0.545098 0.443137
+v -43.489803 41.473999 30.150797 0.639216 0.439216 0.360784
+v -30.361101 43.423199 25.189299 0.698039 0.494118 0.392157
+v -22.342802 38.114101 28.789198 0.560784 0.376471 0.301961
+v -19.248802 37.309799 29.324799 0.603922 0.396078 0.309804
+v -26.459501 38.629799 27.978798 0.427451 0.305882 0.258824
+v -24.593601 42.781898 25.542498 0.670588 0.466667 0.360784
+v -33.258904 40.763699 26.193096 0.592157 0.419608 0.345098
+v -37.950806 45.187599 25.795197 0.741176 0.533333 0.435294
+v -37.224903 41.155800 26.895596 0.592157 0.411765 0.337255
+v -40.750904 39.547798 29.199097 0.537255 0.368627 0.305882
+v -17.907701 40.627102 25.913097 0.686275 0.478431 0.372549
+v -12.980102 34.449100 27.123398 0.639216 0.439216 0.352941
+v -9.614821 36.339699 23.000999 0.678431 0.458824 0.352941
+v -42.234406 27.275101 34.868195 0.588235 0.388235 0.329412
+v -10.124502 28.367300 23.751200 0.580392 0.372549 0.282353
+v -18.888203 24.715599 29.982798 0.658824 0.454902 0.380392
+v -17.454302 20.764400 27.755598 0.639216 0.419608 0.321569
+v -13.572302 24.756201 26.250998 0.592157 0.388235 0.286275
+v -22.865002 17.581499 29.052998 0.733333 0.505882 0.411765
+v -30.623402 15.645700 30.650799 0.803922 0.576471 0.482353
+v -41.184105 16.006500 34.079998 0.796078 0.560784 0.450980
+v -47.160904 20.448400 38.277298 0.705882 0.490196 0.388235
+v -51.919205 25.598900 43.368195 0.623529 0.423529 0.321569
+v -52.268005 32.498501 43.699497 0.568627 0.372549 0.290196
+v -55.200302 32.461800 46.434196 0.611765 0.419608 0.329412
+v -53.071705 37.138699 42.057297 0.576471 0.388235 0.301961
+v -29.791203 24.710300 30.338198 0.729412 0.513725 0.439216
+v -36.564205 24.958700 31.851896 0.698039 0.490196 0.415686
+v -7.289592 -47.139000 20.103399 0.694118 0.474510 0.392157
+v -14.413102 -46.868698 23.217598 0.705882 0.486275 0.392157
+v -14.603202 -50.371601 25.371597 0.741176 0.517647 0.407843
+v -59.491802 32.046799 51.147495 0.603922 0.415686 0.321569
+v -55.639103 22.632401 45.670296 0.639216 0.431373 0.325490
+v -49.984604 16.973101 39.163597 0.725490 0.494118 0.388235
+v -41.621704 8.346640 32.884995 0.843137 0.576471 0.478431
+v -56.876003 39.973801 45.675396 0.556863 0.372549 0.298039
+v -59.767105 43.045399 49.976097 0.501961 0.329412 0.258824
+v -54.420605 42.338902 40.295395 0.568627 0.384314 0.313725
+v -56.593704 46.599098 42.486496 0.454902 0.294118 0.239216
+v -51.546104 43.681000 36.144497 0.615686 0.423529 0.349020
+v -53.910103 50.838902 37.405296 0.403922 0.266667 0.215686
+v -47.176605 46.687801 30.461897 0.658824 0.470588 0.400000
+v -49.335606 53.263500 31.465897 0.419608 0.286275 0.239216
+v -41.835705 49.451500 25.770996 0.623529 0.458824 0.388235
+v -43.368805 54.963402 26.223997 0.435294 0.305882 0.258824
+v -36.252106 50.171902 23.068497 0.549020 0.400000 0.341176
+v -37.054005 55.634499 22.359797 0.482353 0.352941 0.301961
+v -28.583101 48.147099 22.169699 0.588235 0.423529 0.345098
+v -30.643501 56.322201 19.778698 0.596078 0.443137 0.384314
+v -35.441105 81.907204 28.633097 0.662745 0.443137 0.337255
+v -44.335304 80.277100 35.155895 0.584314 0.388235 0.286275
+v -23.805302 80.078201 22.057999 0.756863 0.517647 0.403922
+v -11.024801 69.106598 16.104898 0.835294 0.584314 0.470588
+v -11.198602 81.384598 19.098099 0.800000 0.556863 0.435294
+v -21.602503 53.225300 17.283098 0.596078 0.443137 0.384314
+v -5.917871 37.487801 19.084600 0.811765 0.580392 0.466667
+v -4.247971 24.037399 12.356400 0.686275 0.435294 0.345098
+v -14.467901 -2.056030 9.347089 0.611765 0.356863 0.290196
+v -15.684502 8.225480 20.506998 0.647059 0.411765 0.325490
+v -30.492302 1.468230 27.575397 0.847059 0.576471 0.486275
+v -29.855103 -6.375450 26.988998 0.890196 0.627451 0.537255
+v -41.125404 -1.490210 31.515596 0.854902 0.580392 0.494118
+v -35.953903 -6.553680 28.526196 0.882353 0.615686 0.525490
+v -44.049503 -10.001100 33.293495 0.819608 0.564706 0.478431
+v -36.408905 -12.117100 29.324495 0.878431 0.615686 0.517647
+v -23.772902 26.589300 30.467398 0.690196 0.466667 0.400000
+v -7.501412 -50.686699 23.065300 0.737255 0.509804 0.403922
+v -13.754702 -61.147598 27.150497 0.772549 0.545098 0.443137
+v -7.330832 -54.754902 24.476400 0.796078 0.552941 0.447059
+v -5.799892 -60.043400 24.272900 0.815686 0.568627 0.478431
+v -14.562901 -54.969002 26.952198 0.784314 0.549020 0.431373
+v -20.703901 -49.802700 28.816797 0.729412 0.501961 0.392157
+v -14.287502 -43.688099 21.461899 0.698039 0.447059 0.392157
+v -9.185982 -44.236801 18.529900 0.749020 0.454902 0.427451
+v -4.844681 -44.535198 17.332600 0.772549 0.458824 0.443137
+v -13.385301 1.321240 9.319969 0.517647 0.282353 0.223529
+v -17.594803 -2.992360 17.184399 0.494118 0.258824 0.207843
+v -15.316101 0.718187 13.531699 0.490196 0.262745 0.211765
+v -16.484503 -2.517690 13.317098 0.556863 0.305882 0.247059
+v -63.277405 35.791199 57.119396 0.525490 0.345098 0.266667
+v -62.593704 26.610701 54.955097 0.576471 0.380392 0.290196
+v -62.468002 46.489700 55.637897 0.466667 0.301961 0.227451
+v -65.474205 48.985901 62.915993 0.419608 0.262745 0.196078
+v -66.472511 36.767601 64.102196 0.454902 0.290196 0.219608
+v -66.524406 22.424500 62.011292 0.490196 0.309804 0.235294
+v -61.938904 10.699000 51.148296 0.568627 0.364706 0.286275
+v -68.543007 11.577000 68.501892 0.411765 0.258824 0.200000
+v -64.340508 3.476640 57.093597 0.498039 0.313725 0.247059
+v -7.594552 30.348700 20.315800 0.627451 0.396078 0.298039
+v -16.549402 14.557100 23.902597 0.662745 0.419608 0.325490
+v -22.511202 11.211700 26.775698 0.764706 0.505882 0.407843
+v -30.923302 8.988230 29.229298 0.815686 0.549020 0.447059
+v -59.490303 18.310400 48.448795 0.607843 0.396078 0.301961
+v -53.647404 10.434700 40.909695 0.737255 0.494118 0.403922
+v -4.381762 31.257401 16.638100 0.737255 0.494118 0.388235
+v -60.029804 58.640598 51.293797 0.462745 0.294118 0.219608
+v -64.019104 60.767300 59.519794 0.392157 0.250980 0.188235
+v -58.184303 51.842499 46.189598 0.458824 0.298039 0.227451
+v -57.762302 70.295197 48.925396 0.447059 0.290196 0.215686
+v -51.554703 76.438698 41.738796 0.513725 0.337255 0.247059
+v -11.345502 93.571404 23.007797 0.709804 0.482353 0.372549
+v -23.729801 93.736099 26.669699 0.647059 0.435294 0.329412
+v -35.271004 92.898697 32.481598 0.556863 0.364706 0.274510
+v -44.764503 89.974899 39.158897 0.482353 0.313725 0.235294
+v -52.434803 84.860397 45.720497 0.427451 0.278431 0.207843
+v -61.925304 71.077103 55.743397 0.360784 0.239216 0.180392
+v -58.381702 78.523102 51.614697 0.380392 0.250980 0.188235
+v -60.005302 84.621002 56.387897 0.313725 0.215686 0.168627
+v -64.720604 74.840401 61.180397 0.278431 0.196078 0.152941
+v -67.735107 63.471001 67.175995 0.274510 0.188235 0.149020
+v -68.669807 50.221901 71.097496 0.333333 0.215686 0.168627
+v -69.477310 37.736198 72.644493 0.352941 0.227451 0.176471
+v -69.931206 24.711700 72.207596 0.388235 0.239216 0.188235
+v -10.646601 -24.065701 15.460499 0.713725 0.498039 0.403922
+v -15.570902 -24.833599 18.256699 0.694118 0.490196 0.400000
+v -14.838702 -28.652700 17.550598 0.725490 0.498039 0.427451
+v -19.051203 -30.614100 21.181898 0.694118 0.478431 0.403922
+v -21.021603 -26.519899 21.785698 0.698039 0.501961 0.415686
+v -36.361103 -22.694599 30.639095 0.811765 0.568627 0.462745
+v -40.278202 -36.076199 36.963898 0.725490 0.509804 0.403922
+v -43.906403 -32.487301 39.282295 0.705882 0.486275 0.392157
+v -38.385506 -47.603401 40.941395 0.666667 0.470588 0.364706
+v -46.264404 -37.117699 43.960796 0.643137 0.439216 0.349020
+v -50.024704 -34.044201 47.640896 0.619608 0.419608 0.337255
+v -49.385105 -40.522999 50.694595 0.596078 0.403922 0.321569
+v -48.941204 -27.787399 43.411995 0.662745 0.450980 0.364706
+v -44.039505 -23.420401 36.323795 0.756863 0.529412 0.431373
+v -40.469105 -27.708000 34.571297 0.768627 0.537255 0.435294
+v -40.584103 -19.038799 32.502396 0.819608 0.576471 0.474510
+v -10.270801 -27.988501 14.987799 0.760784 0.501961 0.447059
+v -20.882402 -54.889301 30.517797 0.729412 0.509804 0.392157
+v -35.545204 -55.400200 42.849697 0.627451 0.439216 0.337255
+v -49.520702 -48.135101 57.375698 0.533333 0.360784 0.282353
+v -47.788506 -54.890400 62.359497 0.466667 0.313725 0.243137
+v -55.262604 -28.814100 53.853397 0.572549 0.380392 0.305882
+v -55.605106 -42.532398 65.974190 0.466667 0.313725 0.247059
+v -55.941505 -35.714100 59.684597 0.529412 0.349020 0.282353
+v -57.457302 -19.495899 52.872997 0.568627 0.376471 0.301961
+v -69.852905 -2.797300 89.256996 0.333333 0.215686 0.168627
+v -70.631210 9.026070 81.100189 0.333333 0.211765 0.164706
+v -72.047607 10.667300 91.656296 0.305882 0.200000 0.160784
+v -65.526306 -21.184401 81.961395 0.352941 0.227451 0.176471
+v -66.953011 -10.110300 77.137192 0.368627 0.235294 0.180392
+v -61.182209 -27.386299 67.969193 0.447059 0.290196 0.227451
+v -67.878204 0.099053 71.940689 0.384314 0.243137 0.188235
+v -62.927803 -15.756000 64.638695 0.447059 0.286275 0.223529
+v -67.671104 -16.365200 92.531090 0.329412 0.215686 0.168627
+v -63.259407 -31.738800 86.818794 0.321569 0.211765 0.164706
+v -60.684906 -35.904400 75.737091 0.392157 0.258824 0.203922
+v -59.222309 -41.333500 80.770195 0.352941 0.235294 0.184314
+v -63.768204 -5.981940 60.569996 0.462745 0.294118 0.231373
+v -57.061104 -11.211700 48.339996 0.615686 0.407843 0.329412
+v -71.885208 24.282400 81.760689 0.294118 0.184314 0.149020
+v -73.277611 35.372601 88.210091 0.105882 0.070588 0.058824
+v -73.102806 23.570700 90.919289 0.247059 0.160784 0.129412
+v -74.068710 29.841700 94.291794 0.094118 0.062745 0.050980
+v -73.606911 22.268999 95.906693 0.137255 0.090196 0.074510
+v -72.477509 7.978640 98.615295 0.152941 0.101961 0.082353
+v -69.024506 -13.136300 99.036591 0.333333 0.215686 0.172549
+v -71.098709 -3.316490 100.109993 0.341176 0.223529 0.180392
+v -70.885109 -6.826520 103.005989 0.192157 0.125490 0.101961
+v -67.819908 -17.923401 100.792992 0.145098 0.094118 0.074510
+v -72.112007 0.218792 102.677994 0.180392 0.117647 0.094118
+v -44.566803 99.373398 43.969296 0.364706 0.243137 0.184314
+v -53.142704 92.472603 50.275696 0.345098 0.231373 0.176471
+v -53.622902 97.571404 53.947998 0.262745 0.176471 0.137255
+v -58.044403 92.007202 57.123795 0.121569 0.086275 0.066667
+v -48.604305 101.376999 49.915794 0.156863 0.105882 0.082353
+v -41.549603 104.077003 43.819798 0.172549 0.113725 0.086275
+v -71.393410 49.452900 78.631592 0.247059 0.168627 0.137255
+v -72.491310 48.692600 82.087189 0.094118 0.066667 0.054902
+v -49.436703 58.866501 33.259895 0.545098 0.364706 0.290196
+v -43.665604 60.113602 27.862896 0.592157 0.403922 0.325490
+v -37.226006 60.068802 23.153795 0.670588 0.474510 0.392157
+v -4.352591 16.224400 7.395720 0.682353 0.419608 0.337255
+v -70.843208 58.216900 75.191589 0.101961 0.074510 0.058824
+v -67.510704 71.916199 66.095291 0.133333 0.098039 0.078431
+v -69.946907 66.516602 71.206192 0.109804 0.078431 0.066667
+v -71.842804 37.894199 81.078789 0.254902 0.168627 0.137255
+v -63.468903 81.661102 60.812897 0.137255 0.094118 0.074510
+v -53.695305 98.844704 54.975895 0.129412 0.086275 0.066667
+v -11.574702 100.000999 25.843098 0.317647 0.211765 0.160784
+v -64.204407 -29.280001 98.039894 0.129412 0.086275 0.066667
+v -57.808506 -44.627602 86.710495 0.313725 0.207843 0.164706
+v -61.904308 -36.036499 93.323090 0.290196 0.192157 0.152941
+v -60.306007 -39.574100 93.578392 0.125490 0.082353 0.066667
+v -55.835407 -48.028099 86.987991 0.156863 0.105882 0.082353
+v -49.323906 -56.665699 77.172592 0.176471 0.117647 0.090196
+v -65.933609 -24.037500 96.256691 0.290196 0.188235 0.149020
+v -37.446705 33.968201 30.858696 0.407843 0.384314 0.380392
+v -39.703102 33.516899 32.215996 0.572549 0.533333 0.541176
+v -27.674603 33.585201 30.179197 0.356863 0.309804 0.290196
+v -23.713802 -35.788601 28.594898 0.482353 0.282353 0.235294
+v -3.734711 -35.148399 16.966900 0.596078 0.274510 0.290196
+v -3.894611 -38.155800 17.165199 0.756863 0.372549 0.407843
+v -8.034562 -35.082500 18.211599 0.584314 0.262745 0.282353
+v -8.452592 -38.003201 18.352200 0.713725 0.349020 0.380392
+v -13.179702 -35.288399 20.849298 0.541176 0.258824 0.270588
+v -13.330002 -37.864399 20.994598 0.635294 0.317647 0.337255
+v -17.577602 -35.332802 23.885798 0.447059 0.223529 0.223529
+v -17.583403 -37.785702 24.382399 0.549020 0.274510 0.278431
+v -21.285702 -34.999901 26.378998 0.474510 0.262745 0.231373
+v -21.699402 -38.312199 27.727598 0.564706 0.325490 0.294118
+v -21.295403 -34.956501 26.346899 0.486275 0.270588 0.239216
+v -14.235902 -31.116699 18.050999 0.666667 0.407843 0.368627
+v -6.377821 -27.889299 13.529899 0.796078 0.509804 0.466667
+v -17.588001 -35.285000 23.855999 0.427451 0.215686 0.211765
+v -18.272202 -33.384800 22.694597 0.576471 0.337255 0.298039
+v -13.185702 -35.228500 20.810898 0.533333 0.254902 0.266667
+v -13.791502 -33.117401 19.544298 0.596078 0.329412 0.313725
+v -8.025412 -35.018002 18.154800 0.576471 0.266667 0.282353
+v -9.206802 -33.017300 17.168400 0.631373 0.345098 0.337255
+v -3.731441 -35.080601 16.883200 0.596078 0.274510 0.290196
+v -5.548481 -33.276402 16.041901 0.643137 0.341176 0.337255
+v -2.653011 -33.159401 15.113800 0.650980 0.341176 0.341176
+v -2.764671 -31.169201 13.618300 0.705882 0.388235 0.384314
+v -5.831661 -30.993200 14.292099 0.698039 0.388235 0.380392
+v -4.266491 -41.302898 16.592800 0.807843 0.458824 0.490196
+v -8.956841 -41.049999 17.898399 0.749020 0.415686 0.439216
+v -9.671581 -30.964100 15.692699 0.686275 0.400000 0.376471
+v -13.864402 -40.635300 20.778898 0.654902 0.360784 0.364706
+v -18.022501 -40.030899 24.391897 0.603922 0.345098 0.325490
+v -36.597202 65.101097 24.312796 0.701961 0.478431 0.380392
+v -29.114101 63.241402 19.640799 0.772549 0.541176 0.447059
+v -21.118702 60.808300 16.469297 0.843137 0.607843 0.517647
+# 845 vertices, 0 vertices normals
+
+f 1 2 3
+f 4 5 6
+f 7 6 5
+f 8 7 9
+f 10 4 6
+f 3 12 13
+f 14 15 13
+f 14 16 17
+f 4 10 18
+f 17 16 19
+f 19 16 13
+f 5 4 17
+f 20 17 19
+f 21 19 22
+f 22 13 12
+f 23 24 25
+f 26 23 27
+f 10 6 11
+f 18 28 29
+f 14 29 30
+f 3 15 31
+f 32 20 21
+f 32 33 34
+f 27 25 33
+f 9 5 20
+f 35 36 37
+f 7 8 35
+f 31 15 30
+f 18 10 38
+f 39 40 41
+f 42 43 44
+f 45 46 47
+f 47 48 49
+f 45 47 50
+f 28 38 51
+f 46 45 52
+f 29 28 52
+f 53 31 30
+f 54 53 55
+f 56 54 57
+f 61 62 49
+f 61 48 63
+f 64 65 66
+f 67 68 69
+f 48 70 63
+f 71 72 70
+f 73 74 75
+f 64 76 77
+f 78 79 80
+f 79 81 82
+f 83 84 85
+f 84 86 87
+f 86 88 89
+f 91 60 92
+f 60 90 93
+f 94 89 95
+f 94 95 96
+f 94 96 97
+f 94 97 98
+f 94 98 99
+f 94 99 100
+f 94 100 101
+f 94 101 89
+f 101 100 102
+f 103 95 89
+f 104 105 106
+f 107 108 105
+f 112 109 106
+f 113 109 80
+f 115 116 117
+f 116 118 119
+f 119 120 121
+f 122 121 120
+f 124 125 126
+f 125 127 128
+f 127 118 116
+f 129 117 119
+f 130 131 132
+f 131 121 122
+f 120 133 134
+f 133 135 136
+f 135 137 138
+f 137 139 140
+f 141 126 128
+f 125 142 127
+f 144 142 125
+f 96 95 132
+f 139 145 146
+f 145 110 114
+f 110 147 114
+f 147 148 114
+f 147 82 148
+f 104 109 113
+f 144 107 149
+f 96 123 134
+f 120 143 150
+f 143 144 149
+f 151 152 153
+f 152 154 155
+f 100 146 114
+f 145 113 80
+f 78 112 156
+f 161 162 157
+f 166 167 168
+f 167 169 170
+f 169 160 159
+f 172 171 173
+f 190 192 182
+f 193 189 190
+f 189 194 192
+f 195 196 194
+f 188 197 196
+f 162 198 199
+f 198 191 182
+f 178 185 184
+f 202 199 182
+f 203 204 205
+f 203 183 206
+f 183 186 207
+f 186 187 208
+f 187 184 209
+f 184 185 210
+f 185 211 212
+f 213 211 178
+f 179 174 214
+f 174 175 215
+f 201 215 175
+f 216 217 218
+f 210 212 219
+f 209 210 220
+f 221 222 208
+f 223 224 219
+f 225 226 223
+f 227 228 226
+f 229 230 228
+f 229 231 232
+f 231 233 234
+f 233 235 236
+f 166 237 238
+f 165 239 237
+f 164 239 165
+f 240 241 239
+f 161 242 236
+f 243 157 244
+f 245 154 152
+f 246 135 133
+f 153 247 106
+f 106 247 156
+f 156 248 249
+f 248 250 251
+f 250 252 251
+f 250 44 43
+f 253 251 252
+f 82 74 65
+f 202 205 155
+f 214 215 187
+f 183 254 214
+f 182 180 179
+f 193 190 191
+f 189 193 235
+f 195 189 233
+f 188 195 231
+f 178 188 229
+f 178 225 213
+f 196 197 176
+f 194 196 173
+f 192 194 171
+f 182 192 181
+f 255 256 257
+f 258 37 36
+f 259 260 261
+f 262 259 255
+f 71 263 218
+f 264 72 71
+f 265 264 217
+f 266 265 216
+f 266 216 257
+f 150 149 267
+f 143 118 127
+f 144 125 124
+f 80 79 147
+f 109 104 106
+f 104 113 268
+f 105 104 269
+f 107 105 269
+f 106 105 108
+f 151 111 107
+f 267 149 107
+f 151 107 144
+f 268 113 145
+f 109 112 80
+f 270 246 267
+f 268 270 269
+f 270 268 139
+f 246 270 137
+f 119 118 143
+f 131 129 121
+f 136 98 97
+f 138 140 99
+f 100 99 140
+f 102 114 148
+f 101 102 77
+f 87 89 101
+f 89 88 271
+f 103 272 132
+f 129 131 130
+f 128 116 115
+f 126 141 273
+f 153 108 111
+f 211 213 223
+f 219 274 275
+f 220 219 275
+f 274 276 277
+f 275 274 278
+f 275 279 280
+f 281 282 280
+f 154 283 202
+f 155 205 204
+f 284 204 206
+f 285 206 207
+f 286 207 208
+f 221 220 287
+f 288 287 280
+f 286 222 250
+f 285 286 248
+f 284 285 156
+f 155 284 247
+f 182 203 205
+f 289 244 200
+f 244 289 290
+f 202 283 200
+f 276 274 219
+f 291 292 277
+f 293 291 276
+f 291 293 159
+f 294 291 160
+f 169 295 294
+f 158 157 243
+f 163 158 296
+f 240 163 297
+f 298 241 240
+f 241 298 299
+f 239 241 300
+f 237 239 301
+f 238 237 302
+f 295 238 303
+f 295 169 167
+f 294 295 304
+f 305 292 291
+f 305 294 306
+f 305 306 307
+f 292 305 308
+f 277 292 309
+f 278 277 310
+f 279 278 311
+f 312 281 279
+f 42 44 280
+f 313 314 315
+f 313 87 76
+f 87 313 85
+f 69 68 316
+f 66 69 317
+f 64 317 314
+f 77 148 65
+f 92 93 318
+f 319 56 57
+f 56 319 320
+f 57 321 62
+f 57 54 321
+f 54 56 322
+f 323 324 322
+f 325 323 322
+f 326 327 318
+f 253 328 318
+f 66 73 93
+f 93 73 75
+f 82 81 75
+f 82 147 79
+f 249 81 79
+f 253 249 251
+f 249 253 75
+f 85 313 329
+f 314 317 316
+f 76 87 77
+f 84 83 330
+f 86 84 331
+f 88 86 332
+f 36 261 260
+f 259 262 258
+f 259 333 256
+f 47 46 334
+f 55 335 50
+f 262 334 51
+f 334 262 218
+f 46 52 51
+f 11 37 258
+f 38 11 51
+f 335 29 45
+f 55 30 29
+f 53 54 324
+f 336 337 31
+f 91 61 60
+f 327 320 319
+f 326 325 320
+f 59 328 252
+f 325 338 323
+f 1 337 336
+f 339 336 324
+f 340 324 323
+f 338 325 58
+f 342 343 344
+f 345 346 342
+f 346 345 347
+f 348 346 349
+f 350 351 345
+f 345 351 352
+f 352 353 1
+f 347 352 339
+f 349 347 338
+f 354 349 341
+f 43 58 59
+f 355 58 43
+f 282 354 355
+f 281 348 354
+f 344 343 356
+f 343 342 346
+f 343 348 281
+f 356 343 312
+f 356 312 311
+f 357 358 356
+f 358 357 359
+f 344 358 360
+f 342 344 361
+f 362 350 342
+f 48 47 263
+f 49 62 321
+f 61 91 57
+f 61 49 48
+f 363 364 365
+f 366 364 363
+f 326 58 325
+f 326 59 58
+f 326 328 59
+f 183 182 254
+f 184 187 215
+f 303 367 368
+f 302 40 367
+f 369 370 307
+f 371 369 368
+f 372 371 367
+f 373 374 357
+f 301 41 40
+f 226 293 224
+f 228 159 293
+f 230 375 159
+f 232 376 375
+f 234 377 376
+f 234 236 377
+f 161 235 193
+f 162 200 244
+f 162 161 198
+f 242 161 158
+f 378 379 380
+f 245 289 283
+f 380 290 289
+f 378 124 273
+f 152 151 124
+f 381 382 383
+f 384 311 310
+f 381 374 373
+f 385 307 370
+f 308 307 385
+f 309 308 382
+f 373 310 309
+f 306 304 368
+f 352 351 353
+f 65 74 73
+f 82 65 148
+f 44 250 222
+f 288 222 221
+f 371 386 369
+f 387 300 299
+f 301 300 387
+f 386 370 369
+f 39 372 40
+f 388 117 129
+f 390 391 392
+f 390 393 394
+f 2 394 12
+f 391 395 389
+f 390 2 1
+f 390 353 351
+f 391 351 395
+f 395 351 350
+f 395 362 365
+f 397 175 396
+f 173 176 397
+f 397 178 177
+f 175 397 177
+f 180 398 174
+f 398 180 181
+f 178 397 176
+f 172 398 171
+f 172 173 396
+f 172 396 175
+f 399 68 67
+f 400 401 402
+f 403 404 401
+f 405 406 404
+f 407 408 406
+f 409 410 408
+f 399 410 409
+f 410 399 63
+f 413 315 316
+f 411 415 416
+f 415 417 418
+f 417 419 420
+f 419 421 422
+f 421 423 422
+f 421 424 425
+f 426 427 422
+f 426 83 414
+f 399 67 63
+f 266 428 429
+f 427 430 420
+f 70 410 63
+f 264 265 429
+f 72 264 431
+f 410 70 72
+f 406 408 432
+f 404 406 431
+f 401 404 429
+f 428 266 412
+f 402 401 428
+f 413 316 416
+f 430 413 418
+f 329 315 413
+f 414 329 430
+f 433 426 423
+f 330 83 426
+f 159 375 170
+f 375 376 168
+f 376 377 434
+f 435 434 377
+f 165 166 434
+f 164 165 435
+f 436 163 164
+f 436 435 236
+f 436 242 158
+f 1 3 337
+f 7 5 9
+f 8 9 34
+f 11 6 37
+f 3 13 15
+f 14 13 16
+f 14 17 18
+f 4 18 17
+f 19 13 22
+f 5 17 20
+f 20 19 21
+f 21 22 26
+f 23 25 27
+f 26 27 21
+f 10 11 38
+f 18 29 14
+f 14 30 15
+f 3 31 337
+f 32 21 27
+f 32 34 9
+f 27 33 32
+f 9 20 32
+f 35 37 6
+f 35 6 7
+f 18 38 28
+f 47 49 50
+f 45 50 335
+f 28 51 52
+f 29 52 45
+f 53 30 55
+f 54 55 321
+f 60 61 67
+f 61 63 67
+f 67 69 90
+f 71 70 48
+f 64 77 65
+f 78 80 112
+f 83 85 414
+f 84 87 85
+f 86 89 87
+f 67 90 60
+f 91 92 319
+f 60 93 92
+f 103 89 437
+f 115 117 388
+f 116 119 117
+f 119 121 129
+f 122 120 123
+f 123 96 122
+f 124 126 273
+f 125 128 126
+f 127 116 128
+f 130 132 272
+f 131 122 132
+f 120 134 123
+f 133 136 134
+f 135 138 136
+f 137 140 138
+f 141 128 438
+f 143 142 144
+f 96 132 122
+f 139 146 140
+f 145 114 146
+f 96 134 97
+f 120 150 133
+f 143 149 150
+f 151 153 111
+f 152 155 153
+f 108 107 111
+f 100 114 102
+f 145 80 110
+f 157 158 161
+f 164 163 240
+f 167 170 168
+f 169 159 170
+f 182 183 203
+f 188 178 197
+f 190 182 191
+f 189 192 190
+f 195 194 189
+f 188 196 195
+f 162 199 200
+f 198 182 199
+f 178 201 177
+f 178 184 201
+f 202 182 205
+f 203 206 204
+f 183 207 206
+f 186 208 207
+f 187 209 208
+f 184 210 209
+f 185 212 210
+f 179 214 254
+f 174 215 214
+f 201 175 177
+f 216 218 255
+f 210 219 220
+f 209 220 221
+f 221 208 209
+f 178 211 185
+f 223 219 212
+f 225 223 213
+f 227 226 225
+f 229 228 227
+f 229 232 230
+f 231 234 232
+f 233 236 234
+f 166 238 167
+f 165 237 166
+f 240 239 164
+f 161 236 235
+f 243 244 439
+f 245 152 378
+f 246 133 150
+f 153 106 108
+f 106 156 112
+f 156 249 78
+f 248 251 249
+f 250 43 252
+f 253 252 328
+f 214 187 186
+f 183 214 186
+f 182 179 254
+f 193 191 198
+f 189 235 233
+f 195 233 231
+f 188 231 229
+f 178 229 227
+f 178 227 225
+f 197 178 176
+f 196 176 173
+f 194 173 171
+f 192 171 181
+f 182 181 180
+f 255 257 216
+f 258 36 260
+f 259 261 333
+f 262 255 218
+f 71 218 217
+f 264 71 217
+f 265 217 216
+f 266 257 412
+f 150 267 246
+f 143 127 142
+f 144 124 151
+f 80 147 110
+f 107 269 267
+f 268 145 139
+f 270 267 269
+f 268 269 104
+f 270 139 137
+f 246 137 135
+f 119 143 120
+f 136 97 134
+f 98 136 138
+f 138 99 98
+f 100 140 146
+f 102 148 77
+f 101 77 87
+f 89 271 437
+f 103 132 95
+f 129 130 440
+f 128 115 438
+f 211 223 212
+f 220 275 287
+f 274 277 278
+f 275 278 279
+f 275 280 287
+f 281 280 279
+f 154 202 155
+f 155 204 284
+f 284 206 285
+f 285 207 286
+f 286 208 222
+f 221 287 288
+f 288 280 44
+f 286 250 248
+f 285 248 156
+f 284 156 247
+f 155 247 153
+f 289 200 283
+f 244 290 439
+f 202 200 199
+f 276 219 224
+f 291 277 276
+f 293 276 224
+f 291 159 160
+f 169 294 160
+f 158 243 296
+f 163 296 297
+f 240 297 441
+f 298 240 441
+f 241 299 300
+f 239 300 301
+f 237 301 302
+f 238 302 303
+f 295 303 304
+f 295 167 238
+f 294 304 306
+f 305 291 294
+f 305 307 308
+f 292 308 309
+f 277 309 310
+f 278 310 311
+f 279 311 312
+f 42 280 282
+f 313 315 329
+f 313 76 314
+f 69 316 317
+f 66 317 64
+f 64 314 76
+f 92 318 327
+f 319 57 91
+f 56 320 322
+f 54 322 324
+f 325 322 320
+f 326 318 328
+f 253 318 75
+f 90 69 66
+f 66 93 90
+f 93 75 318
+f 82 75 74
+f 249 79 78
+f 249 75 81
+f 85 329 414
+f 314 316 315
+f 84 330 331
+f 86 331 332
+f 88 332 271
+f 259 258 260
+f 259 256 255
+f 47 334 263
+f 55 50 321
+f 262 51 258
+f 334 218 263
+f 46 51 334
+f 11 258 51
+f 55 29 335
+f 53 324 336
+f 336 31 53
+f 327 319 92
+f 326 320 327
+f 1 336 339
+f 339 324 340
+f 340 323 338
+f 338 58 341
+f 341 58 355
+f 345 342 350
+f 346 347 349
+f 348 349 354
+f 345 352 347
+f 352 1 339
+f 347 339 340
+f 347 340 338
+f 349 338 341
+f 354 341 355
+f 43 59 252
+f 355 43 42
+f 282 355 42
+f 281 354 282
+f 344 356 358
+f 343 346 348
+f 343 281 312
+f 356 311 384
+f 357 356 384
+f 358 359 360
+f 344 360 361
+f 342 361 363
+f 362 342 363
+f 48 263 71
+f 49 321 50
+f 61 57 62
+f 363 365 362
+f 184 215 201
+f 303 368 304
+f 302 367 303
+f 369 307 368
+f 371 368 367
+f 372 367 40
+f 373 357 384
+f 301 40 302
+f 226 224 223
+f 228 293 226
+f 230 159 228
+f 232 375 230
+f 234 376 232
+f 161 193 198
+f 162 244 157
+f 378 380 245
+f 245 283 154
+f 380 289 245
+f 378 273 379
+f 152 124 378
+f 384 310 373
+f 308 385 382
+f 309 382 381
+f 373 309 381
+f 306 368 307
+f 65 73 66
+f 44 222 288
+f 387 299 442
+f 301 387 41
+f 388 129 440
+f 390 392 393
+f 390 394 2
+f 2 12 3
+f 391 389 392
+f 390 1 353
+f 390 351 391
+f 395 350 362
+f 395 365 389
+f 173 397 396
+f 180 174 179
+f 398 181 171
+f 172 175 174
+f 172 174 398
+f 400 402 443
+f 403 401 400
+f 405 404 403
+f 407 406 405
+f 409 408 407
+f 411 68 399
+f 411 416 68
+f 415 418 416
+f 417 420 418
+f 419 422 420
+f 421 425 423
+f 426 422 423
+f 426 414 427
+f 266 429 265
+f 427 420 422
+f 264 429 431
+f 72 431 432
+f 410 72 432
+f 408 410 432
+f 406 432 431
+f 404 431 429
+f 401 429 428
+f 428 412 444
+f 402 428 444
+f 413 416 418
+f 430 418 420
+f 316 68 416
+f 329 413 430
+f 414 430 427
+f 433 423 425
+f 330 426 433
+f 375 168 170
+f 376 434 168
+f 435 377 236
+f 166 168 434
+f 165 434 435
+f 164 435 436
+f 436 236 242
+f 436 158 163
+f 363 361 366
+f 445 447 446
+f 448 450 449
+f 451 449 450
+f 8 452 451
+f 453 450 448
+f 447 456 455
+f 457 456 458
+f 457 460 459
+f 448 461 453
+f 460 462 459
+f 462 456 459
+f 449 460 448
+f 463 462 460
+f 464 465 462
+f 465 455 456
+f 466 25 24
+f 467 468 466
+f 453 454 450
+f 461 470 469
+f 457 471 470
+f 447 472 458
+f 473 464 463
+f 473 34 33
+f 468 33 25
+f 452 463 449
+f 35 474 36
+f 451 35 8
+f 472 471 458
+f 461 475 453
+f 476 478 477
+f 479 481 480
+f 482 484 483
+f 484 486 485
+f 482 487 484
+f 469 488 475
+f 483 489 482
+f 470 489 469
+f 490 471 472
+f 491 492 490
+f 493 494 491
+f 498 486 499
+f 498 500 485
+f 501 503 502
+f 504 506 505
+f 485 500 507
+f 508 507 509
+f 510 512 511
+f 501 514 513
+f 515 517 516
+f 516 519 518
+f 520 522 521
+f 521 524 523
+f 523 526 525
+f 528 529 497
+f 497 530 527
+f 531 532 526
+f 531 533 532
+f 531 534 533
+f 531 535 534
+f 531 536 535
+f 531 537 536
+f 531 538 537
+f 531 526 538
+f 538 539 537
+f 103 526 532
+f 540 542 541
+f 543 541 544
+f 548 542 545
+f 549 517 545
+f 115 552 551
+f 551 554 553
+f 554 556 555
+f 557 555 556
+f 559 561 560
+f 560 563 562
+f 562 551 553
+f 564 554 552
+f 130 566 565
+f 565 557 556
+f 555 568 567
+f 567 570 569
+f 569 572 571
+f 571 574 573
+f 141 563 561
+f 560 562 575
+f 577 560 575
+f 533 566 532
+f 573 579 578
+f 578 550 546
+f 546 550 580
+f 580 550 581
+f 580 581 519
+f 540 549 545
+f 577 582 543
+f 533 568 558
+f 555 583 576
+f 576 582 577
+f 584 586 585
+f 585 588 587
+f 537 550 579
+f 578 517 549
+f 515 589 548
+f 594 590 595
+f 599 601 600
+f 600 603 602
+f 602 592 593
+f 605 606 604
+f 623 615 625
+f 626 623 622
+f 622 625 627
+f 628 627 629
+f 621 629 630
+f 595 632 631
+f 631 615 624
+f 611 617 618
+f 635 615 632
+f 636 638 637
+f 636 639 616
+f 616 640 619
+f 619 641 620
+f 620 642 617
+f 617 643 618
+f 618 645 644
+f 646 611 644
+f 612 647 607
+f 607 648 608
+f 634 608 648
+f 649 651 650
+f 643 652 645
+f 642 653 643
+f 654 641 655
+f 656 652 657
+f 658 656 659
+f 660 659 661
+f 662 661 663
+f 662 665 664
+f 664 667 666
+f 666 669 668
+f 599 671 670
+f 598 670 672
+f 597 598 672
+f 673 672 674
+f 594 669 675
+f 243 676 590
+f 677 585 587
+f 678 567 569
+f 586 542 679
+f 542 589 679
+f 589 681 680
+f 680 683 682
+f 682 683 684
+f 682 480 481
+f 685 684 683
+f 519 502 511
+f 635 588 638
+f 647 620 648
+f 616 647 686
+f 615 612 613
+f 626 624 623
+f 622 668 626
+f 628 666 622
+f 621 664 628
+f 611 662 621
+f 611 646 658
+f 629 609 630
+f 627 606 629
+f 625 604 627
+f 615 614 625
+f 687 257 256
+f 688 36 474
+f 689 261 690
+f 691 687 689
+f 508 651 692
+f 693 508 509
+f 694 650 693
+f 695 649 694
+f 695 257 649
+f 583 696 582
+f 576 562 553
+f 577 559 560
+f 517 580 516
+f 545 542 540
+f 540 697 549
+f 541 698 540
+f 543 698 541
+f 542 544 541
+f 584 543 547
+f 696 543 582
+f 584 577 543
+f 697 578 549
+f 545 517 548
+f 699 696 678
+f 697 698 699
+f 699 573 697
+f 678 571 699
+f 554 576 553
+f 565 556 564
+f 570 534 535
+f 572 536 574
+f 537 574 536
+f 539 581 550
+f 538 514 539
+f 524 538 526
+f 526 271 525
+f 103 566 272
+f 564 130 565
+f 563 115 551
+f 561 273 141
+f 586 547 544
+f 644 656 646
+f 652 701 700
+f 653 701 652
+f 700 703 702
+f 701 704 700
+f 701 706 705
+f 707 706 708
+f 587 635 709
+f 588 637 638
+f 710 639 637
+f 711 640 639
+f 712 641 640
+f 654 713 653
+f 714 706 713
+f 712 682 655
+f 711 680 712
+f 710 589 711
+f 588 679 710
+f 615 638 636
+f 715 633 676
+f 676 290 715
+f 635 633 709
+f 702 652 700
+f 716 703 717
+f 718 702 716
+f 716 592 718
+f 719 593 716
+f 602 719 720
+f 591 243 590
+f 596 296 591
+f 673 297 596
+f 298 673 674
+f 674 299 298
+f 672 721 674
+f 670 722 672
+f 671 723 670
+f 720 724 671
+f 720 600 602
+f 719 725 720
+f 726 716 717
+f 726 727 719
+f 726 728 727
+f 717 729 726
+f 703 730 717
+f 704 731 703
+f 705 732 704
+f 733 705 707
+f 479 706 481
+f 734 736 735
+f 734 513 524
+f 524 522 734
+f 506 737 505
+f 503 738 506
+f 501 735 738
+f 514 502 581
+f 529 739 530
+f 740 494 493
+f 493 741 740
+f 494 499 742
+f 494 742 491
+f 491 743 493
+f 744 743 745
+f 746 743 744
+f 747 739 748
+f 685 739 749
+f 503 530 510
+f 530 512 510
+f 519 512 518
+f 519 516 580
+f 681 516 518
+f 685 683 681
+f 681 512 685
+f 522 750 734
+f 735 737 738
+f 513 514 524
+f 521 330 520
+f 523 331 521
+f 525 332 523
+f 36 690 261
+f 689 688 691
+f 689 256 333
+f 484 751 483
+f 492 487 752
+f 691 488 751
+f 751 651 691
+f 483 488 489
+f 454 688 474
+f 475 488 454
+f 752 482 470
+f 492 470 471
+f 490 745 491
+f 753 472 754
+f 528 497 498
+f 748 740 741
+f 747 741 746
+f 496 684 749
+f 746 744 755
+f 445 753 754
+f 756 745 753
+f 757 744 745
+f 755 495 746
+f 759 761 760
+f 762 759 763
+f 763 764 762
+f 765 766 763
+f 767 762 768
+f 762 769 768
+f 769 445 770
+f 764 756 769
+f 766 755 764
+f 771 758 766
+f 480 496 495
+f 772 480 495
+f 708 772 771
+f 707 771 765
+f 761 773 760
+f 760 763 759
+f 760 707 765
+f 773 733 760
+f 773 732 733
+f 774 773 775
+f 775 776 774
+f 761 777 775
+f 759 778 761
+f 779 759 767
+f 485 692 484
+f 486 742 499
+f 498 494 528
+f 498 485 486
+f 780 782 781
+f 783 780 781
+f 747 746 495
+f 747 495 496
+f 747 496 749
+f 616 686 615
+f 617 648 620
+f 724 785 784
+f 723 784 477
+f 786 728 787
+f 788 785 786
+f 789 784 788
+f 790 774 791
+f 722 477 478
+f 659 657 718
+f 661 718 592
+f 663 592 792
+f 665 792 793
+f 667 793 794
+f 667 794 669
+f 594 626 668
+f 595 676 633
+f 595 631 594
+f 675 591 594
+f 795 380 379
+f 677 709 715
+f 380 715 290
+f 795 273 559
+f 585 559 584
+f 796 798 797
+f 799 731 732
+f 796 790 791
+f 800 787 728
+f 729 800 728
+f 730 797 729
+f 790 730 731
+f 727 785 725
+f 769 770 768
+f 502 510 511
+f 519 581 502
+f 481 655 682
+f 714 654 655
+f 788 786 801
+f 802 299 721
+f 722 802 721
+f 801 786 787
+f 476 477 789
+f 388 564 552
+f 804 806 805
+f 804 808 807
+f 446 455 808
+f 805 803 809
+f 804 445 446
+f 804 768 770
+f 805 809 768
+f 809 767 768
+f 809 782 779
+f 811 810 608
+f 606 811 609
+f 811 610 611
+f 608 610 811
+f 613 607 812
+f 812 614 613
+f 611 609 811
+f 605 604 812
+f 605 810 606
+f 605 608 810
+f 813 504 505
+f 814 402 815
+f 816 815 817
+f 818 817 819
+f 820 819 821
+f 822 821 823
+f 813 822 823
+f 823 500 813
+f 825 737 736
+f 824 828 827
+f 827 830 829
+f 829 832 831
+f 831 834 833
+f 833 834 835
+f 833 425 424
+f 836 834 837
+f 836 826 520
+f 813 500 504
+f 695 839 838
+f 837 832 840
+f 507 500 823
+f 693 839 694
+f 509 841 693
+f 823 509 507
+f 819 842 821
+f 817 841 819
+f 815 839 817
+f 838 412 695
+f 402 838 815
+f 825 828 737
+f 840 830 825
+f 750 825 736
+f 826 840 750
+f 433 835 836
+f 330 836 520
+f 592 603 792
+f 792 601 793
+f 793 843 794
+f 844 794 843
+f 598 843 599
+f 597 844 598
+f 845 597 596
+f 845 669 844
+f 845 591 675
+f 445 754 447
+f 451 452 449
+f 8 34 452
+f 454 474 450
+f 447 458 456
+f 457 459 456
+f 457 461 460
+f 448 460 461
+f 462 465 456
+f 449 463 460
+f 463 464 462
+f 464 467 465
+f 466 468 25
+f 467 464 468
+f 453 475 454
+f 461 457 470
+f 457 458 471
+f 447 754 472
+f 473 468 464
+f 473 452 34
+f 468 473 33
+f 452 473 463
+f 35 450 474
+f 35 451 450
+f 461 469 475
+f 484 487 486
+f 482 752 487
+f 469 489 488
+f 470 482 489
+f 490 492 471
+f 491 742 492
+f 497 504 498
+f 498 504 500
+f 504 527 506
+f 508 485 507
+f 501 502 514
+f 515 548 517
+f 520 826 522
+f 521 522 524
+f 523 524 526
+f 504 497 527
+f 528 740 529
+f 497 529 530
+f 103 437 526
+f 115 388 552
+f 551 552 554
+f 554 564 556
+f 557 558 555
+f 558 557 533
+f 559 273 561
+f 560 561 563
+f 562 563 551
+f 130 272 566
+f 565 566 557
+f 555 558 568
+f 567 568 570
+f 569 570 572
+f 571 572 574
+f 141 438 563
+f 576 577 575
+f 533 557 566
+f 573 574 579
+f 578 579 550
+f 533 534 568
+f 555 567 583
+f 576 583 582
+f 584 547 586
+f 585 586 588
+f 544 547 543
+f 537 539 550
+f 578 546 517
+f 590 594 591
+f 597 673 596
+f 600 601 603
+f 602 603 592
+f 615 636 616
+f 621 630 611
+f 623 624 615
+f 622 623 625
+f 628 622 627
+f 621 628 629
+f 595 633 632
+f 631 632 615
+f 611 610 634
+f 611 634 617
+f 635 638 615
+f 636 637 639
+f 616 639 640
+f 619 640 641
+f 620 641 642
+f 617 642 643
+f 618 643 645
+f 612 686 647
+f 607 647 648
+f 634 610 608
+f 649 687 651
+f 643 653 652
+f 642 654 653
+f 654 642 641
+f 611 618 644
+f 656 645 652
+f 658 646 656
+f 660 658 659
+f 662 660 661
+f 662 663 665
+f 664 665 667
+f 666 667 669
+f 599 600 671
+f 598 599 670
+f 673 597 672
+f 594 668 669
+f 243 439 676
+f 677 795 585
+f 678 583 567
+f 586 544 542
+f 542 548 589
+f 589 515 681
+f 680 681 683
+f 682 684 480
+f 685 749 684
+f 647 619 620
+f 616 619 647
+f 615 686 612
+f 626 631 624
+f 622 666 668
+f 628 664 666
+f 621 662 664
+f 611 660 662
+f 611 658 660
+f 630 609 611
+f 629 606 609
+f 627 604 606
+f 625 614 604
+f 615 613 614
+f 687 649 257
+f 688 690 36
+f 689 333 261
+f 691 651 687
+f 508 650 651
+f 693 650 508
+f 694 649 650
+f 695 412 257
+f 583 678 696
+f 576 575 562
+f 577 584 559
+f 517 546 580
+f 543 696 698
+f 697 573 578
+f 699 698 696
+f 697 540 698
+f 699 571 573
+f 678 569 571
+f 554 555 576
+f 570 568 534
+f 535 572 570
+f 572 535 536
+f 537 579 574
+f 539 514 581
+f 538 524 514
+f 526 437 271
+f 103 532 566
+f 564 440 130
+f 563 438 115
+f 644 645 656
+f 653 713 701
+f 700 704 703
+f 701 705 704
+f 701 713 706
+f 707 705 706
+f 587 588 635
+f 588 710 637
+f 710 711 639
+f 711 712 640
+f 712 655 641
+f 654 714 713
+f 714 481 706
+f 712 680 682
+f 711 589 680
+f 710 679 589
+f 588 586 679
+f 715 709 633
+f 676 439 290
+f 635 632 633
+f 702 657 652
+f 716 702 703
+f 718 657 702
+f 716 593 592
+f 602 593 719
+f 591 296 243
+f 596 297 296
+f 673 441 297
+f 298 441 673
+f 674 721 299
+f 672 722 721
+f 670 723 722
+f 671 724 723
+f 720 725 724
+f 720 671 600
+f 719 727 725
+f 726 719 716
+f 726 729 728
+f 717 730 729
+f 703 731 730
+f 704 732 731
+f 705 733 732
+f 479 708 706
+f 734 750 736
+f 734 735 513
+f 506 738 737
+f 503 501 738
+f 501 513 735
+f 529 748 739
+f 740 528 494
+f 493 743 741
+f 491 745 743
+f 746 741 743
+f 747 749 739
+f 685 512 739
+f 527 503 506
+f 503 527 530
+f 530 739 512
+f 519 511 512
+f 681 515 516
+f 681 518 512
+f 522 826 750
+f 735 736 737
+f 521 331 330
+f 523 332 331
+f 525 271 332
+f 689 690 688
+f 689 687 256
+f 484 692 751
+f 492 742 487
+f 691 688 488
+f 751 692 651
+f 483 751 488
+f 454 488 688
+f 492 752 470
+f 490 753 745
+f 753 490 472
+f 748 529 740
+f 747 748 741
+f 445 756 753
+f 756 757 745
+f 757 755 744
+f 755 758 495
+f 758 772 495
+f 762 767 759
+f 763 766 764
+f 765 771 766
+f 762 764 769
+f 769 756 445
+f 764 757 756
+f 764 755 757
+f 766 758 755
+f 771 772 758
+f 480 684 496
+f 772 479 480
+f 708 479 772
+f 707 708 771
+f 761 775 773
+f 760 765 763
+f 760 733 707
+f 773 799 732
+f 774 799 773
+f 775 777 776
+f 761 778 777
+f 759 780 778
+f 779 780 759
+f 485 508 692
+f 486 487 742
+f 498 499 494
+f 780 779 782
+f 617 634 648
+f 724 725 785
+f 723 724 784
+f 786 785 728
+f 788 784 785
+f 789 477 784
+f 790 799 774
+f 722 723 477
+f 659 656 657
+f 661 659 718
+f 663 661 592
+f 665 663 792
+f 667 665 793
+f 594 631 626
+f 595 590 676
+f 795 677 380
+f 677 587 709
+f 380 677 715
+f 795 379 273
+f 585 795 559
+f 799 790 731
+f 729 797 800
+f 730 796 797
+f 790 796 730
+f 727 728 785
+f 502 503 510
+f 481 714 655
+f 802 442 299
+f 722 478 802
+f 388 440 564
+f 804 807 806
+f 804 446 808
+f 446 447 455
+f 805 806 803
+f 804 770 445
+f 804 805 768
+f 809 779 767
+f 809 803 782
+f 606 810 811
+f 613 612 607
+f 812 604 614
+f 605 607 608
+f 605 812 607
+f 814 443 402
+f 816 814 815
+f 818 816 817
+f 820 818 819
+f 822 820 821
+f 824 813 505
+f 824 505 828
+f 827 828 830
+f 829 830 832
+f 831 832 834
+f 833 835 425
+f 836 835 834
+f 836 837 826
+f 695 694 839
+f 837 834 832
+f 693 841 839
+f 509 842 841
+f 823 842 509
+f 821 842 823
+f 819 841 842
+f 817 839 841
+f 815 838 839
+f 838 444 412
+f 402 444 838
+f 825 830 828
+f 840 832 830
+f 737 828 505
+f 750 840 825
+f 826 837 840
+f 433 425 835
+f 330 433 836
+f 792 603 601
+f 793 601 843
+f 844 669 794
+f 599 843 601
+f 598 844 843
+f 597 845 844
+f 845 675 669
+f 845 596 591
+f 780 783 778
+# 1610 faces, 0 coords texture
+
+# End of File
diff --git a/demo/model3D/files/sofia.stl b/demo/model3D/files/sofia.stl
new file mode 100644
index 0000000000000000000000000000000000000000..8a811c851675350bc5f9ab0d1f0eff69651104ae
Binary files /dev/null and b/demo/model3D/files/sofia.stl differ
diff --git a/demo/model3D/files/source.txt b/demo/model3D/files/source.txt
new file mode 100644
index 0000000000000000000000000000000000000000..95f4bcc925f0bf5cf6a00913e13532fd0616f77a
--- /dev/null
+++ b/demo/model3D/files/source.txt
@@ -0,0 +1,13 @@
+Stanford Bunny:
+https://graphics.stanford.edu/data/3Dscanrep/
+https://graphics.stanford.edu/~mdfisher/Data/Meshes/bunny.obj
+
+Duck & Fox:
+https://github.com/KhronosGroup/glTF-Sample-Models
+
+Face:
+https://github.com/mikedh/trimesh/tree/main/models
+
+NASA SOFIA:
+https://nasa3d.arc.nasa.gov/detail/sofia
+https://github.com/nasa/NASA-3D-Resources/blob/master/3D%20Models/SOFIA/Fuselage_top.stl
\ No newline at end of file
diff --git a/demo/model3D/run.ipynb b/demo/model3D/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e44bd515ac7f5d5f2be164c72c7e2c64fdb4d653
--- /dev/null
+++ b/demo/model3D/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: model3D"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/Bunny.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Bunny.obj\n", "!wget -q -O files/Duck.glb https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Duck.glb\n", "!wget -q -O files/Fox.gltf https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Fox.gltf\n", "!wget -q -O files/face.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/face.obj\n", "!wget -q -O files/sofia.stl https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/sofia.stl\n", "!wget -q -O files/source.txt https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/source.txt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def load_mesh(mesh_file_name):\n", " return mesh_file_name\n", "\n", "\n", "demo = gr.Interface(\n", " fn=load_mesh,\n", " inputs=gr.Model3D(),\n", " outputs=gr.Model3D(\n", " clear_color=[0.0, 0.0, 0.0, 0.0], label=\"3D Model\"),\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"files/Bunny.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/Duck.glb\")],\n", " [os.path.join(os.path.abspath(''), \"files/Fox.gltf\")],\n", " [os.path.join(os.path.abspath(''), \"files/face.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/sofia.stl\")],\n", " ],\n", " cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/model3D/run.py b/demo/model3D/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..232d7aac53f3a438fac427f9b15d45e59f4981df
--- /dev/null
+++ b/demo/model3D/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+import os
+
+
+def load_mesh(mesh_file_name):
+ return mesh_file_name
+
+
+demo = gr.Interface(
+ fn=load_mesh,
+ inputs=gr.Model3D(),
+ outputs=gr.Model3D(
+ clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model"),
+ examples=[
+ [os.path.join(os.path.dirname(__file__), "files/Bunny.obj")],
+ [os.path.join(os.path.dirname(__file__), "files/Duck.glb")],
+ [os.path.join(os.path.dirname(__file__), "files/Fox.gltf")],
+ [os.path.join(os.path.dirname(__file__), "files/face.obj")],
+ [os.path.join(os.path.dirname(__file__), "files/sofia.stl")],
+ ],
+ cache_examples=True
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/model3D_demo.zip b/demo/model3D_demo.zip
new file mode 100644
index 0000000000000000000000000000000000000000..12309e3ae972e56e7fb0d37c73f2912d4f6ef495
--- /dev/null
+++ b/demo/model3D_demo.zip
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:49112eed80b58d99b205ac76b7e2cb2e55ef1195fad4dd4ccacfebe2320e2d3d
+size 287848
diff --git a/demo/model3d_component/run.ipynb b/demo/model3d_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dafccd6cd838618a372ebd72ea9705fad4b12a44
--- /dev/null
+++ b/demo/model3d_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: model3d_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Model3D()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/model3d_component/run.py b/demo/model3d_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc773fe511ab9397939bf899965c425a9c09c8b4
--- /dev/null
+++ b/demo/model3d_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Model3D()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/model3d_component_events/run.ipynb b/demo/model3d_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..448f1cd9122db9da8f0fc4982f8bf83c2d241642
--- /dev/null
+++ b/demo/model3d_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: model3d_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_3d = gr.Model3D(label=\"Input Model3D\")\n", " with gr.Column():\n", " output_3d = gr.Model3D(label=\"Output Model3D\")\n", " with gr.Column():\n", " num_change = gr.Number(label=\"# Change Events\", value=0)\n", " num_load = gr.Number(label=\"# Upload Events\", value=0)\n", " num_clear = gr.Number(label=\"# Clear Events\", value=0)\n", " clear_value = gr.Textbox(label=\"Clear Value\", value=\"\")\n", " input_3d.upload(lambda s, n: (s, n + 1), [input_3d, num_load], [output_3d, num_load])\n", " input_3d.change(lambda n: n + 1, num_change, num_change)\n", " input_3d.clear(lambda s, n: (s, n + 1), [input_3d, num_clear], [clear_value, num_clear])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/model3d_component_events/run.py b/demo/model3d_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4eb8002557a41f7965e62a6b45b7478b1a7f220b
--- /dev/null
+++ b/demo/model3d_component_events/run.py
@@ -0,0 +1,20 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ input_3d = gr.Model3D(label="Input Model3D")
+ with gr.Column():
+ output_3d = gr.Model3D(label="Output Model3D")
+ with gr.Column():
+ num_change = gr.Number(label="# Change Events", value=0)
+ num_load = gr.Number(label="# Upload Events", value=0)
+ num_clear = gr.Number(label="# Clear Events", value=0)
+ clear_value = gr.Textbox(label="Clear Value", value="")
+ input_3d.upload(lambda s, n: (s, n + 1), [input_3d, num_load], [output_3d, num_load])
+ input_3d.change(lambda n: n + 1, num_change, num_change)
+ input_3d.clear(lambda s, n: (s, n + 1), [input_3d, num_clear], [clear_value, num_clear])
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/musical_instrument_identification/DESCRIPTION.md b/demo/musical_instrument_identification/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..99b199f205c9bb17086e5093ef98cbbc744920cc
--- /dev/null
+++ b/demo/musical_instrument_identification/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo identifies musical instruments from an audio file. It uses Gradio's Audio and Label components.
\ No newline at end of file
diff --git a/demo/musical_instrument_identification/data_setups.py b/demo/musical_instrument_identification/data_setups.py
new file mode 100644
index 0000000000000000000000000000000000000000..2488ac6684d6f3ea3b1b2121f725f297bf8b1d3c
--- /dev/null
+++ b/demo/musical_instrument_identification/data_setups.py
@@ -0,0 +1,80 @@
+# Make function to find classes in target directory
+import os
+import librosa
+import torch
+import numpy as np
+from torchaudio.transforms import Resample
+
+SAMPLE_RATE = 44100
+AUDIO_LEN = 2.90
+
+# Parameters to control the MelSpec generation
+N_MELS = 128
+F_MIN = 20
+F_MAX = 16000
+N_FFT = 1024
+HOP_LEN = 512
+
+# Make function to find classes in target directory
+def find_classes(directory: str):
+ # 1. Get the class names by scanning the target directory
+ classes = sorted(entry.name for entry in os.scandir(directory) if entry.is_dir())
+ # 2. Raise an error if class names not found
+ if not classes:
+ raise FileNotFoundError(f"Couldn't find any classes in {directory}.")
+ # 3. Crearte a dictionary of index labels (computers prefer numerical rather than string labels)
+ class_to_idx = {cls_name: i for i, cls_name in enumerate(classes)}
+ return classes, class_to_idx
+
+def resample(wav, sample_rate, new_sample_rate):
+ if wav.shape[0] >= 2:
+ wav = torch.mean(wav, dim=0)
+ else:
+ wav = wav.squeeze(0)
+ if sample_rate > new_sample_rate:
+ resampler = Resample(sample_rate, new_sample_rate)
+ wav = resampler(wav)
+ return wav
+
+def mono_to_color(X, eps=1e-6, mean=None, std=None):
+ X = np.stack([X, X, X], axis=-1)
+ # Standardize
+ mean = mean or X.mean()
+ std = std or X.std()
+ X = (X - mean) / (std + eps)
+ # Normalize to [0, 255]
+ _min, _max = X.min(), X.max()
+ if (_max - _min) > eps:
+ V = np.clip(X, _min, _max)
+ V = 255 * (V - _min) / (_max - _min)
+ V = V.astype(np.uint8)
+ else:
+ V = np.zeros_like(X, dtype=np.uint8)
+ return V
+
+def normalize(image, mean=None, std=None):
+ image = image / 255.0
+ if mean is not None and std is not None:
+ image = (image - mean) / std
+ return np.moveaxis(image, 2, 0).astype(np.float32)
+
+def compute_melspec(wav, sample_rate=SAMPLE_RATE):
+ melspec = librosa.feature.melspectrogram(
+ y=wav,
+ sr=sample_rate,
+ n_fft=N_FFT,
+ fmin=F_MIN,
+ fmax=F_MAX,
+ n_mels=N_MELS,
+ hop_length=HOP_LEN
+ )
+ melspec = librosa.power_to_db(melspec).astype(np.float32)
+ return melspec
+
+def audio_preprocess(wav, sample_rate):
+ wav = wav.numpy()
+ melspec = compute_melspec(wav, sample_rate)
+ image = mono_to_color(melspec)
+ image = normalize(image, mean=None, std=None)
+ image = torch.from_numpy(image)
+ return image
\ No newline at end of file
diff --git a/demo/musical_instrument_identification/requirements.txt b/demo/musical_instrument_identification/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6d940e5956421ec02cdbb385f6c9b87153d22ba1
--- /dev/null
+++ b/demo/musical_instrument_identification/requirements.txt
@@ -0,0 +1,5 @@
+torch==1.12.0
+torchvision==0.13.0
+torchaudio==0.12.0
+librosa==0.9.2
+gdown
\ No newline at end of file
diff --git a/demo/musical_instrument_identification/run.ipynb b/demo/musical_instrument_identification/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..cd757ae18234f639318f856ce78037dad687709a
--- /dev/null
+++ b/demo/musical_instrument_identification/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: musical_instrument_identification\n", "### This demo identifies musical instruments from an audio file. It uses Gradio's Audio and Label components.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch==1.12.0 torchvision==0.13.0 torchaudio==0.12.0 librosa==0.9.2 gdown"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/musical_instrument_identification/data_setups.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "import torchaudio\n", "from timeit import default_timer as timer\n", "from data_setups import audio_preprocess, resample\n", "import gdown\n", "\n", "url = 'https://drive.google.com/uc?id=1X5CR18u0I-ZOi_8P0cNptCe5JGk9Ro0C'\n", "output = 'piano.wav'\n", "gdown.download(url, output, quiet=False)\n", "url = 'https://drive.google.com/uc?id=1W-8HwmGR5SiyDbUcGAZYYDKdCIst07__'\n", "output= 'torch_efficientnet_fold2_CNN.pth'\n", "gdown.download(url, output, quiet=False)\n", "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", "SAMPLE_RATE = 44100\n", "AUDIO_LEN = 2.90\n", "model = torch.load(\"torch_efficientnet_fold2_CNN.pth\", map_location=torch.device('cpu'))\n", "LABELS = [\n", " \"Cello\", \"Clarinet\", \"Flute\", \"Acoustic Guitar\", \"Electric Guitar\", \"Organ\", \"Piano\", \"Saxophone\", \"Trumpet\", \"Violin\", \"Voice\"\n", "]\n", "example_list = [\n", " [\"piano.wav\"]\n", "]\n", "\n", "\n", "def predict(audio_path):\n", " start_time = timer()\n", " wavform, sample_rate = torchaudio.load(audio_path)\n", " wav = resample(wavform, sample_rate, SAMPLE_RATE)\n", " if len(wav) > int(AUDIO_LEN * SAMPLE_RATE):\n", " wav = wav[:int(AUDIO_LEN * SAMPLE_RATE)]\n", " else:\n", " print(f\"input length {len(wav)} too small!, need over {int(AUDIO_LEN * SAMPLE_RATE)}\")\n", " return\n", " img = audio_preprocess(wav, SAMPLE_RATE).unsqueeze(0)\n", " model.eval()\n", " with torch.inference_mode():\n", " pred_probs = torch.softmax(model(img), dim=1)\n", " pred_labels_and_probs = {LABELS[i]: float(pred_probs[0][i]) for i in range(len(LABELS))}\n", " pred_time = round(timer() - start_time, 5)\n", " return pred_labels_and_probs, pred_time\n", "\n", "demo = gr.Interface(fn=predict,\n", " inputs=gr.Audio(type=\"filepath\"),\n", " outputs=[gr.Label(num_top_classes=11, label=\"Predictions\"), \n", " gr.Number(label=\"Prediction time (s)\")],\n", " examples=example_list,\n", " cache_examples=False\n", " )\n", "\n", "demo.launch(debug=False)\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/musical_instrument_identification/run.py b/demo/musical_instrument_identification/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..94d60c7d61ce02fa4bfb4c3bb9cd54a1bdb99e8c
--- /dev/null
+++ b/demo/musical_instrument_identification/run.py
@@ -0,0 +1,51 @@
+import gradio as gr
+import torch
+import torchaudio
+from timeit import default_timer as timer
+from data_setups import audio_preprocess, resample
+import gdown
+
+url = 'https://drive.google.com/uc?id=1X5CR18u0I-ZOi_8P0cNptCe5JGk9Ro0C'
+output = 'piano.wav'
+gdown.download(url, output, quiet=False)
+url = 'https://drive.google.com/uc?id=1W-8HwmGR5SiyDbUcGAZYYDKdCIst07__'
+output= 'torch_efficientnet_fold2_CNN.pth'
+gdown.download(url, output, quiet=False)
+device = "cuda" if torch.cuda.is_available() else "cpu"
+SAMPLE_RATE = 44100
+AUDIO_LEN = 2.90
+model = torch.load("torch_efficientnet_fold2_CNN.pth", map_location=torch.device('cpu'))
+LABELS = [
+ "Cello", "Clarinet", "Flute", "Acoustic Guitar", "Electric Guitar", "Organ", "Piano", "Saxophone", "Trumpet", "Violin", "Voice"
+]
+example_list = [
+ ["piano.wav"]
+]
+
+
+def predict(audio_path):
+ start_time = timer()
+ wavform, sample_rate = torchaudio.load(audio_path)
+ wav = resample(wavform, sample_rate, SAMPLE_RATE)
+ if len(wav) > int(AUDIO_LEN * SAMPLE_RATE):
+ wav = wav[:int(AUDIO_LEN * SAMPLE_RATE)]
+ else:
+ print(f"input length {len(wav)} too small!, need over {int(AUDIO_LEN * SAMPLE_RATE)}")
+ return
+ img = audio_preprocess(wav, SAMPLE_RATE).unsqueeze(0)
+ model.eval()
+ with torch.inference_mode():
+ pred_probs = torch.softmax(model(img), dim=1)
+ pred_labels_and_probs = {LABELS[i]: float(pred_probs[0][i]) for i in range(len(LABELS))}
+ pred_time = round(timer() - start_time, 5)
+ return pred_labels_and_probs, pred_time
+
+demo = gr.Interface(fn=predict,
+ inputs=gr.Audio(type="filepath"),
+ outputs=[gr.Label(num_top_classes=11, label="Predictions"),
+ gr.Number(label="Prediction time (s)")],
+ examples=example_list,
+ cache_examples=False
+ )
+
+demo.launch(debug=False)
diff --git a/demo/native_plots/bar_plot_demo.py b/demo/native_plots/bar_plot_demo.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4432e121bcbc844df6b4a5590d51e958be3be7e
--- /dev/null
+++ b/demo/native_plots/bar_plot_demo.py
@@ -0,0 +1,111 @@
+import gradio as gr
+import pandas as pd
+
+from vega_datasets import data
+
+barley = data.barley()
+simple = pd.DataFrame({
+ 'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
+ 'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
+})
+
+def bar_plot_fn(display):
+ if display == "simple":
+ return gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ color=None,
+ group=None,
+ title="Simple Bar Plot with made up data",
+ tooltip=['a', 'b'],
+ y_lim=[20, 100],
+ x_title=None,
+ y_title=None,
+ vertical=True,
+ )
+ elif display == "stacked":
+ return gr.BarPlot(
+ barley,
+ x="variety",
+ y="yield",
+ color="site",
+ group=None,
+ title="Barley Yield Data",
+ tooltip=['variety', 'site'],
+ y_lim=None,
+ x_title=None,
+ y_title=None,
+ vertical=True,
+ )
+ elif display == "grouped":
+ return gr.BarPlot(
+ barley.astype({"year": str}),
+ x="year",
+ y="yield",
+ color="year",
+ group="site",
+ title="Barley Yield by Year and Site",
+ tooltip=["yield", "site", "year"],
+ y_lim=None,
+ x_title=None,
+ y_title=None,
+ vertical=True,
+ )
+ elif display == "simple-horizontal":
+ return gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ color=None,
+ group=None,
+ title="Simple Bar Plot with made up data",
+ tooltip=['a', 'b'],
+ y_lim=[20, 100],
+ x_title="Variable A",
+ y_title="Variable B",
+ vertical=False,
+ )
+ elif display == "stacked-horizontal":
+ return gr.BarPlot(
+ barley,
+ x="variety",
+ y="yield",
+ color="site",
+ group=None,
+ title="Barley Yield Data",
+ tooltip=['variety', 'site'],
+ y_lim=None,
+ x_title=None,
+ y_title=None,
+ vertical=False,
+ )
+ elif display == "grouped-horizontal":
+ return gr.BarPlot(
+ barley.astype({"year": str}),
+ x="year",
+ y="yield",
+ color="year",
+ group="site",
+ title="Barley Yield by Year and Site",
+ group_title="",
+ tooltip=["yield", "site", "year"],
+ y_lim=None,
+ x_title=None,
+ y_title=None,
+ vertical=False
+ )
+
+
+with gr.Blocks() as bar_plot:
+ with gr.Row():
+ with gr.Column():
+ display = gr.Dropdown(
+ choices=["simple", "stacked", "grouped", "simple-horizontal", "stacked-horizontal", "grouped-horizontal"],
+ value="simple",
+ label="Type of Bar Plot"
+ )
+ with gr.Column():
+ plot = gr.BarPlot(show_label=False, show_actions_button=True)
+ display.change(bar_plot_fn, inputs=display, outputs=plot)
+ bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot)
diff --git a/demo/native_plots/line_plot_demo.py b/demo/native_plots/line_plot_demo.py
new file mode 100644
index 0000000000000000000000000000000000000000..49b87d8db2f4a3303f616ccb29ff34a722c770b1
--- /dev/null
+++ b/demo/native_plots/line_plot_demo.py
@@ -0,0 +1,94 @@
+import gradio as gr
+from vega_datasets import data
+
+stocks = data.stocks()
+gapminder = data.gapminder()
+gapminder = gapminder.loc[
+ gapminder.country.isin(["Argentina", "Australia", "Afghanistan"])
+]
+climate = data.climate()
+seattle_weather = data.seattle_weather()
+
+
+def line_plot_fn(dataset):
+ if dataset == "stocks":
+ return gr.LinePlot(
+ stocks,
+ x="date",
+ y="price",
+ color="symbol",
+ x_lim=None,
+ y_lim=None,
+ stroke_dash=None,
+ tooltip=['date', 'price', 'symbol'],
+ overlay_point=False,
+ title="Stock Prices",
+ stroke_dash_legend_title=None,
+ height=300,
+ width=500
+ )
+ elif dataset == "climate":
+ return gr.LinePlot(
+ climate,
+ x="DATE",
+ y="HLY-TEMP-NORMAL",
+ color=None,
+ x_lim=None,
+ y_lim=[250, 500],
+ stroke_dash=None,
+ tooltip=['DATE', 'HLY-TEMP-NORMAL'],
+ overlay_point=False,
+ title="Climate",
+ stroke_dash_legend_title=None,
+ height=300,
+ width=500
+ )
+ elif dataset == "seattle_weather":
+ return gr.LinePlot(
+ seattle_weather,
+ x="date",
+ y="temp_min",
+ color=None,
+ x_lim=None,
+ y_lim=None,
+ stroke_dash=None,
+ tooltip=["weather", "date"],
+ overlay_point=True,
+ title="Seattle Weather",
+ stroke_dash_legend_title=None,
+ height=300,
+ width=500
+ )
+ elif dataset == "gapminder":
+ return gr.LinePlot(
+ gapminder,
+ x="year",
+ y="life_expect",
+ color="country",
+ x_lim=[1950, 2010],
+ y_lim=None,
+ stroke_dash="cluster",
+ tooltip=['country', 'life_expect'],
+ overlay_point=False,
+ title="Life expectancy for countries",
+ stroke_dash_legend_title="Country Cluster",
+ height=300,
+ width=500
+ )
+
+
+with gr.Blocks() as line_plot:
+ with gr.Row():
+ with gr.Column():
+ dataset = gr.Dropdown(
+ choices=["stocks", "climate", "seattle_weather", "gapminder"],
+ value="stocks",
+ )
+ with gr.Column():
+ plot = gr.LinePlot()
+ dataset.change(line_plot_fn, inputs=dataset, outputs=plot)
+ line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot)
+
+
+if __name__ == "__main__":
+ line_plot.launch()
diff --git a/demo/native_plots/requirements.txt b/demo/native_plots/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d1c8a7ae0396d12417907feb8ef43fb4bcc8e89c
--- /dev/null
+++ b/demo/native_plots/requirements.txt
@@ -0,0 +1 @@
+vega_datasets
\ No newline at end of file
diff --git a/demo/native_plots/run.ipynb b/demo/native_plots/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f79c3ad9856bd51e1174f555d319ac8c68fccf57
--- /dev/null
+++ b/demo/native_plots/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: native_plots"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/native_plots/bar_plot_demo.py\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/native_plots/line_plot_demo.py\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/native_plots/scatter_plot_demo.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "from scatter_plot_demo import scatter_plot\n", "from line_plot_demo import line_plot\n", "from bar_plot_demo import bar_plot\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tabs():\n", " with gr.TabItem(\"Scatter Plot\"):\n", " scatter_plot.render()\n", " with gr.TabItem(\"Line Plot\"):\n", " line_plot.render()\n", " with gr.TabItem(\"Bar Plot\"):\n", " bar_plot.render()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/native_plots/run.py b/demo/native_plots/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ed9ed8309fdb01401ef7c234884ea36ba9dd004
--- /dev/null
+++ b/demo/native_plots/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+
+from scatter_plot_demo import scatter_plot
+from line_plot_demo import line_plot
+from bar_plot_demo import bar_plot
+
+
+with gr.Blocks() as demo:
+ with gr.Tabs():
+ with gr.TabItem("Scatter Plot"):
+ scatter_plot.render()
+ with gr.TabItem("Line Plot"):
+ line_plot.render()
+ with gr.TabItem("Bar Plot"):
+ bar_plot.render()
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ae129ea9d3a71717ce6bcd34b94069e3cece2a7
--- /dev/null
+++ b/demo/native_plots/scatter_plot_demo.py
@@ -0,0 +1,47 @@
+import gradio as gr
+
+from vega_datasets import data
+
+cars = data.cars()
+iris = data.iris()
+
+
+def scatter_plot_fn(dataset):
+ if dataset == "iris":
+ return gr.ScatterPlot(
+ value=iris,
+ x="petalWidth",
+ y="petalLength",
+ color="species",
+ title="Iris Dataset",
+ color_legend_title="Species",
+ x_title="Petal Width",
+ y_title="Petal Length",
+ tooltip=["petalWidth", "petalLength", "species"],
+ caption="",
+ )
+ else:
+ return gr.ScatterPlot(
+ value=cars,
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ tooltip="Name",
+ title="Car Data",
+ y_title="Miles per Gallon",
+ color_legend_title="Origin of Car",
+ caption="MPG vs Horsepower of various cars",
+ )
+
+
+with gr.Blocks() as scatter_plot:
+ with gr.Row():
+ with gr.Column():
+ dataset = gr.Dropdown(choices=["cars", "iris"], value="cars")
+ with gr.Column():
+ plot = gr.ScatterPlot(show_label=False)
+ dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)
+ scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)
+
+if __name__ == "__main__":
+ scatter_plot.launch()
diff --git a/demo/neon-tts-plugin-coqui/DESCRIPTION.md b/demo/neon-tts-plugin-coqui/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..d9e5f1cc47c696247c5e3bc6ed193f3992dff75a
--- /dev/null
+++ b/demo/neon-tts-plugin-coqui/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo converts text to speech in 14 languages.
\ No newline at end of file
diff --git a/demo/neon-tts-plugin-coqui/packages.txt b/demo/neon-tts-plugin-coqui/packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5585ec894ee24dbcc5f876cebf2ca7f20f9fcf8
--- /dev/null
+++ b/demo/neon-tts-plugin-coqui/packages.txt
@@ -0,0 +1,2 @@
+libsndfile1
+espeak-ng
\ No newline at end of file
diff --git a/demo/neon-tts-plugin-coqui/requirements.txt b/demo/neon-tts-plugin-coqui/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..96d8dd6616d4262cab5c144709e3e5cd9fe2c369
--- /dev/null
+++ b/demo/neon-tts-plugin-coqui/requirements.txt
@@ -0,0 +1 @@
+neon-tts-plugin-coqui==0.4.1a9
\ No newline at end of file
diff --git a/demo/neon-tts-plugin-coqui/run.ipynb b/demo/neon-tts-plugin-coqui/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a154dec65da4109c6cf69d402f130ac07c5a204e
--- /dev/null
+++ b/demo/neon-tts-plugin-coqui/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: neon-tts-plugin-coqui\n", "### This demo converts text to speech in 14 languages.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio neon-tts-plugin-coqui==0.4.1a9"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/neon-tts-plugin-coqui/packages.txt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import tempfile\n", "import gradio as gr\n", "from neon_tts_plugin_coqui import CoquiTTS\n", "\n", "LANGUAGES = list(CoquiTTS.langs.keys())\n", "coquiTTS = CoquiTTS()\n", "\n", "def tts(text: str, language: str):\n", " with tempfile.NamedTemporaryFile(suffix=\".wav\", delete=False) as fp:\n", " coquiTTS.get_tts(text, fp, speaker = {\"language\" : language})\n", " return fp.name\n", "\n", "inputs = [gr.Textbox(label=\"Input\", value=CoquiTTS.langs[\"en\"][\"sentence\"], max_lines=3), \n", " gr.Radio(label=\"Language\", choices=LANGUAGES, value=\"en\")]\n", "outputs = gr.Audio(label=\"Output\")\n", "\n", "demo = gr.Interface(fn=tts, inputs=inputs, outputs=outputs)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/neon-tts-plugin-coqui/run.py b/demo/neon-tts-plugin-coqui/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5a78d625ffde42934edbbb31bbffe70081218c0
--- /dev/null
+++ b/demo/neon-tts-plugin-coqui/run.py
@@ -0,0 +1,19 @@
+import tempfile
+import gradio as gr
+from neon_tts_plugin_coqui import CoquiTTS
+
+LANGUAGES = list(CoquiTTS.langs.keys())
+coquiTTS = CoquiTTS()
+
+def tts(text: str, language: str):
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as fp:
+ coquiTTS.get_tts(text, fp, speaker = {"language" : language})
+ return fp.name
+
+inputs = [gr.Textbox(label="Input", value=CoquiTTS.langs["en"]["sentence"], max_lines=3),
+ gr.Radio(label="Language", choices=LANGUAGES, value="en")]
+outputs = gr.Audio(label="Output")
+
+demo = gr.Interface(fn=tts, inputs=inputs, outputs=outputs)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/ner_pipeline/requirements.txt b/demo/ner_pipeline/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39dab0fdd98d55da5ce06ddf1dacbdbda14b1372
--- /dev/null
+++ b/demo/ner_pipeline/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
\ No newline at end of file
diff --git a/demo/ner_pipeline/run.ipynb b/demo/ner_pipeline/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a67da7879392b52752bf5a5cd81cedd06fbb7b50
--- /dev/null
+++ b/demo/ner_pipeline/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: ner_pipeline"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from transformers import pipeline\n", "\n", "import gradio as gr\n", "\n", "ner_pipeline = pipeline(\"ner\")\n", "\n", "examples = [\n", " \"Does Chicago have any stores and does Joe live here?\",\n", "]\n", "\n", "def ner(text):\n", " output = ner_pipeline(text)\n", " return {\"text\": text, \"entities\": output} \n", "\n", "demo = gr.Interface(ner,\n", " gr.Textbox(placeholder=\"Enter sentence here...\"), \n", " gr.HighlightedText(),\n", " examples=examples)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/ner_pipeline/run.py b/demo/ner_pipeline/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f131632aec5a38a6e8b3839ac50979d29779fe3b
--- /dev/null
+++ b/demo/ner_pipeline/run.py
@@ -0,0 +1,21 @@
+from transformers import pipeline
+
+import gradio as gr
+
+ner_pipeline = pipeline("ner")
+
+examples = [
+ "Does Chicago have any stores and does Joe live here?",
+]
+
+def ner(text):
+ output = ner_pipeline(text)
+ return {"text": text, "entities": output}
+
+demo = gr.Interface(ner,
+ gr.Textbox(placeholder="Enter sentence here..."),
+ gr.HighlightedText(),
+ examples=examples)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/no_input/run.ipynb b/demo/no_input/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b70a7f8ba0a4bc7c8566dc67c14fb7e45dae505f
--- /dev/null
+++ b/demo/no_input/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: no_input"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "\n", "sentence_list = [\n", " \"Good morning!\",\n", " \"Prayers are with you, have a safe day!\",\n", " \"I love you!\"\n", "]\n", "\n", "\n", "def random_sentence():\n", " return sentence_list[random.randint(0, 2)]\n", "\n", "\n", "demo = gr.Interface(fn=random_sentence, inputs=None, outputs=\"text\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/no_input/run.py b/demo/no_input/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1d9344d7902f7673af289d5f04ab706f924178b
--- /dev/null
+++ b/demo/no_input/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+import random
+
+sentence_list = [
+ "Good morning!",
+ "Prayers are with you, have a safe day!",
+ "I love you!"
+]
+
+
+def random_sentence():
+ return sentence_list[random.randint(0, 2)]
+
+
+demo = gr.Interface(fn=random_sentence, inputs=None, outputs="text")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/number_component/run.ipynb b/demo/number_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8a3921c0dc21764442d05527bddcac1caefe7cfb
--- /dev/null
+++ b/demo/number_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: number_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Number()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/number_component/run.py b/demo/number_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..007339534fd16aedf65dc353a67cb9d8b5fc3ddd
--- /dev/null
+++ b/demo/number_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Number()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/on_listener_basic/run.ipynb b/demo/on_listener_basic/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8b9fa173ba17af928885647d89026aba29700014
--- /dev/null
+++ b/demo/on_listener_basic/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: on_listener_basic"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(label=\"Output Box\")\n", " greet_btn = gr.Button(\"Greet\")\n", " trigger = gr.Textbox(label=\"Trigger Box\")\n", " trigger2 = gr.Textbox(label=\"Trigger Box\")\n", "\n", " def greet(name, evt_data: gr.EventData):\n", " return \"Hello \" + name + \"!\", evt_data.target.__class__.__name__\n", " \n", " def clear_name(evt_data: gr.EventData):\n", " return \"\", evt_data.target.__class__.__name__\n", " \n", " gr.on(\n", " triggers=[name.submit, greet_btn.click],\n", " fn=greet,\n", " inputs=name,\n", " outputs=[output, trigger],\n", " ).then(clear_name, outputs=[name, trigger2])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/on_listener_basic/run.py b/demo/on_listener_basic/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..214b1cc7dc72f9b1c159aebf0ffb47bc03434771
--- /dev/null
+++ b/demo/on_listener_basic/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+ trigger = gr.Textbox(label="Trigger Box")
+ trigger2 = gr.Textbox(label="Trigger Box")
+
+ def greet(name, evt_data: gr.EventData):
+ return "Hello " + name + "!", evt_data.target.__class__.__name__
+
+ def clear_name(evt_data: gr.EventData):
+ return "", evt_data.target.__class__.__name__
+
+ gr.on(
+ triggers=[name.submit, greet_btn.click],
+ fn=greet,
+ inputs=name,
+ outputs=[output, trigger],
+ ).then(clear_name, outputs=[name, trigger2])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/on_listener_decorator/run.ipynb b/demo/on_listener_decorator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1483324520b2e3de9f886edbb573910b7739795f
--- /dev/null
+++ b/demo/on_listener_decorator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: on_listener_decorator"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(label=\"Output Box\")\n", " greet_btn = gr.Button(\"Greet\")\n", "\n", " @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output)\n", " def greet(name):\n", " return \"Hello \" + name + \"!\"\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/on_listener_decorator/run.py b/demo/on_listener_decorator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4df88b9a8a5913ea346f5ad99ba93323286a9ead
--- /dev/null
+++ b/demo/on_listener_decorator/run.py
@@ -0,0 +1,14 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+
+ @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output)
+ def greet(name):
+ return "Hello " + name + "!"
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/on_listener_live/run.ipynb b/demo/on_listener_live/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e6a97f9293e9cf8f04175a27ecbc2aef43a7ef20
--- /dev/null
+++ b/demo/on_listener_live/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: on_listener_live"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " num1 = gr.Slider(1, 10)\n", " num2 = gr.Slider(1, 10)\n", " num3 = gr.Slider(1, 10)\n", " output = gr.Number(label=\"Sum\")\n", "\n", " @gr.on(inputs=[num1, num2, num3], outputs=output)\n", " def sum(a, b, c):\n", " return a + b + c\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/on_listener_live/run.py b/demo/on_listener_live/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5488e0dfcf1faf7dcee38a73557472e22c981453
--- /dev/null
+++ b/demo/on_listener_live/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ num1 = gr.Slider(1, 10)
+ num2 = gr.Slider(1, 10)
+ num3 = gr.Slider(1, 10)
+ output = gr.Number(label="Sum")
+
+ @gr.on(inputs=[num1, num2, num3], outputs=output)
+ def sum(a, b, c):
+ return a + b + c
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/on_listener_test/run.ipynb b/demo/on_listener_test/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a7258cdc437ed1bc35ae48cba7c38d5dc7841d01
--- /dev/null
+++ b/demo/on_listener_test/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: on_listener_test"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"Name\")\n", " output = gr.Textbox(label=\"Output\")\n", " greet_btn = gr.Button(\"Greet\")\n", " trigger = gr.Textbox(label=\"Trigger 1\")\n", " trigger2 = gr.Textbox(label=\"Trigger 2\")\n", "\n", " def greet(name, evt_data: gr.EventData):\n", " return \"Hello \" + name + \"!\", evt_data.target.__class__.__name__\n", " \n", " def clear_name(evt_data: gr.EventData):\n", " return \"\", evt_data.target.__class__.__name__\n", " \n", " gr.on(\n", " triggers=[name.submit, greet_btn.click],\n", " fn=greet,\n", " inputs=name,\n", " outputs=[output, trigger],\n", " ).then(clear_name, outputs=[name, trigger2])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/on_listener_test/run.py b/demo/on_listener_test/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5ae73c8de2fdd398d1533203c225a22cbac7f88
--- /dev/null
+++ b/demo/on_listener_test/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output")
+ greet_btn = gr.Button("Greet")
+ trigger = gr.Textbox(label="Trigger 1")
+ trigger2 = gr.Textbox(label="Trigger 2")
+
+ def greet(name, evt_data: gr.EventData):
+ return "Hello " + name + "!", evt_data.target.__class__.__name__
+
+ def clear_name(evt_data: gr.EventData):
+ return "", evt_data.target.__class__.__name__
+
+ gr.on(
+ triggers=[name.submit, greet_btn.click],
+ fn=greet,
+ inputs=name,
+ outputs=[output, trigger],
+ ).then(clear_name, outputs=[name, trigger2])
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/outbreak_forecast/DESCRIPTION.md b/demo/outbreak_forecast/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..dda592517b46e1ade9b3f82874011ced89f863e5
--- /dev/null
+++ b/demo/outbreak_forecast/DESCRIPTION.md
@@ -0,0 +1 @@
+Generate a plot based on 5 inputs.
\ No newline at end of file
diff --git a/demo/outbreak_forecast/requirements.txt b/demo/outbreak_forecast/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5615a533fc38661ad62a2c87679594f38b4c3952
--- /dev/null
+++ b/demo/outbreak_forecast/requirements.txt
@@ -0,0 +1,5 @@
+numpy
+matplotlib
+bokeh
+plotly
+altair
\ No newline at end of file
diff --git a/demo/outbreak_forecast/run.ipynb b/demo/outbreak_forecast/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..60c1d1a7217171e8c8b1988d34254735cfb6a721
--- /dev/null
+++ b/demo/outbreak_forecast/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: outbreak_forecast\n", "### Generate a plot based on 5 inputs.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy matplotlib bokeh plotly altair"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import altair\n", "\n", "import gradio as gr\n", "from math import sqrt\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import plotly.express as px\n", "import pandas as pd\n", "\n", "\n", "def outbreak(plot_type, r, month, countries, social_distancing):\n", " months = [\"January\", \"February\", \"March\", \"April\", \"May\"]\n", " m = months.index(month)\n", " start_day = 30 * m\n", " final_day = 30 * (m + 1)\n", " x = np.arange(start_day, final_day + 1)\n", " pop_count = {\"USA\": 350, \"Canada\": 40, \"Mexico\": 300, \"UK\": 120}\n", " if social_distancing:\n", " r = sqrt(r)\n", " df = pd.DataFrame({\"day\": x})\n", " for country in countries:\n", " df[country] = x ** (r) * (pop_count[country] + 1)\n", "\n", " if plot_type == \"Matplotlib\":\n", " fig = plt.figure()\n", " plt.plot(df[\"day\"], df[countries].to_numpy())\n", " plt.title(\"Outbreak in \" + month)\n", " plt.ylabel(\"Cases\")\n", " plt.xlabel(\"Days since Day 0\")\n", " plt.legend(countries)\n", " return fig\n", " elif plot_type == \"Plotly\":\n", " fig = px.line(df, x=\"day\", y=countries)\n", " fig.update_layout(\n", " title=\"Outbreak in \" + month,\n", " xaxis_title=\"Cases\",\n", " yaxis_title=\"Days Since Day 0\",\n", " )\n", " return fig\n", " elif plot_type == \"Altair\":\n", " df = df.melt(id_vars=\"day\").rename(columns={\"variable\": \"country\"})\n", " fig = altair.Chart(df).mark_line().encode(x=\"day\", y='value', color='country')\n", " return fig\n", " else:\n", " raise ValueError(\"A plot type must be selected\")\n", "\n", "\n", "inputs = [\n", " gr.Dropdown([\"Matplotlib\", \"Plotly\", \"Altair\"], label=\"Plot Type\"),\n", " gr.Slider(1, 4, 3.2, label=\"R\"),\n", " gr.Dropdown([\"January\", \"February\", \"March\", \"April\", \"May\"], label=\"Month\"),\n", " gr.CheckboxGroup(\n", " [\"USA\", \"Canada\", \"Mexico\", \"UK\"], label=\"Countries\", value=[\"USA\", \"Canada\"]\n", " ),\n", " gr.Checkbox(label=\"Social Distancing?\"),\n", "]\n", "outputs = gr.Plot()\n", "\n", "demo = gr.Interface(\n", " fn=outbreak,\n", " inputs=inputs,\n", " outputs=outputs,\n", " examples=[\n", " [\"Matplotlib\", 2, \"March\", [\"Mexico\", \"UK\"], True],\n", " [\"Altair\", 2, \"March\", [\"Mexico\", \"Canada\"], True],\n", " [\"Plotly\", 3.6, \"February\", [\"Canada\", \"Mexico\", \"UK\"], False],\n", " ],\n", " cache_examples=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", "\n", "\n", "\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/outbreak_forecast/run.py b/demo/outbreak_forecast/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3101c9ccf28bb5d014f7633b88f6276e57cf4c50
--- /dev/null
+++ b/demo/outbreak_forecast/run.py
@@ -0,0 +1,75 @@
+import altair
+
+import gradio as gr
+from math import sqrt
+import matplotlib.pyplot as plt
+import numpy as np
+import plotly.express as px
+import pandas as pd
+
+
+def outbreak(plot_type, r, month, countries, social_distancing):
+ months = ["January", "February", "March", "April", "May"]
+ m = months.index(month)
+ start_day = 30 * m
+ final_day = 30 * (m + 1)
+ x = np.arange(start_day, final_day + 1)
+ pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
+ if social_distancing:
+ r = sqrt(r)
+ df = pd.DataFrame({"day": x})
+ for country in countries:
+ df[country] = x ** (r) * (pop_count[country] + 1)
+
+ if plot_type == "Matplotlib":
+ fig = plt.figure()
+ plt.plot(df["day"], df[countries].to_numpy())
+ plt.title("Outbreak in " + month)
+ plt.ylabel("Cases")
+ plt.xlabel("Days since Day 0")
+ plt.legend(countries)
+ return fig
+ elif plot_type == "Plotly":
+ fig = px.line(df, x="day", y=countries)
+ fig.update_layout(
+ title="Outbreak in " + month,
+ xaxis_title="Cases",
+ yaxis_title="Days Since Day 0",
+ )
+ return fig
+ elif plot_type == "Altair":
+ df = df.melt(id_vars="day").rename(columns={"variable": "country"})
+ fig = altair.Chart(df).mark_line().encode(x="day", y='value', color='country')
+ return fig
+ else:
+ raise ValueError("A plot type must be selected")
+
+
+inputs = [
+ gr.Dropdown(["Matplotlib", "Plotly", "Altair"], label="Plot Type"),
+ gr.Slider(1, 4, 3.2, label="R"),
+ gr.Dropdown(["January", "February", "March", "April", "May"], label="Month"),
+ gr.CheckboxGroup(
+ ["USA", "Canada", "Mexico", "UK"], label="Countries", value=["USA", "Canada"]
+ ),
+ gr.Checkbox(label="Social Distancing?"),
+]
+outputs = gr.Plot()
+
+demo = gr.Interface(
+ fn=outbreak,
+ inputs=inputs,
+ outputs=outputs,
+ examples=[
+ ["Matplotlib", 2, "March", ["Mexico", "UK"], True],
+ ["Altair", 2, "March", ["Mexico", "Canada"], True],
+ ["Plotly", 3.6, "February", ["Canada", "Mexico", "UK"], False],
+ ],
+ cache_examples=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
+
+
+
diff --git a/demo/plot_component/requirements.txt b/demo/plot_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8248f97be94ef0dabec7bd3223a2d0d51a0c847c
--- /dev/null
+++ b/demo/plot_component/requirements.txt
@@ -0,0 +1,2 @@
+matplotlib
+numpy
\ No newline at end of file
diff --git a/demo/plot_component/run.ipynb b/demo/plot_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..76aa6333c75257c456df8cea8c2eae521da6f261
--- /dev/null
+++ b/demo/plot_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: plot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio matplotlib numpy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "Fs = 8000\n", "f = 5\n", "sample = 8000\n", "x = np.arange(sample)\n", "y = np.sin(2 * np.pi * f * x / Fs)\n", "plt.plot(x, y)\n", "\n", "with gr.Blocks() as demo:\n", " gr.Plot(value=plt)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/plot_component/run.py b/demo/plot_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae7ffd3ddd6fee5dde48fb0eaf1e02981beeb2b0
--- /dev/null
+++ b/demo/plot_component/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+import matplotlib.pyplot as plt
+import numpy as np
+
+Fs = 8000
+f = 5
+sample = 8000
+x = np.arange(sample)
+y = np.sin(2 * np.pi * f * x / Fs)
+plt.plot(x, y)
+
+with gr.Blocks() as demo:
+ gr.Plot(value=plt)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/progress/requirements.txt b/demo/progress/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8f2403eb7a1fd0c9c883d713f48ad6a0f7f485b0
--- /dev/null
+++ b/demo/progress/requirements.txt
@@ -0,0 +1,2 @@
+tqdm
+datasets
\ No newline at end of file
diff --git a/demo/progress/run.ipynb b/demo/progress/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..221a9d614c026dcdd94737679e3d84873aaf0306
--- /dev/null
+++ b/demo/progress/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: progress"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio tqdm datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "import time\n", "import tqdm\n", "from datasets import load_dataset\n", "import shutil\n", "from uuid import uuid4\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " text = gr.Textbox()\n", " textb = gr.Textbox()\n", " with gr.Row():\n", " load_set_btn = gr.Button(\"Load Set\")\n", " load_nested_set_btn = gr.Button(\"Load Nested Set\")\n", " load_random_btn = gr.Button(\"Load Random\")\n", " clean_imgs_btn = gr.Button(\"Clean Images\")\n", " wait_btn = gr.Button(\"Wait\")\n", " do_all_btn = gr.Button(\"Do All\")\n", " track_tqdm_btn = gr.Button(\"Bind TQDM\")\n", " bind_internal_tqdm_btn = gr.Button(\"Bind Internal TQDM\")\n", "\n", " text2 = gr.Textbox()\n", "\n", " # track list\n", " def load_set(text, text2, progress=gr.Progress()):\n", " imgs = [None] * 24\n", " for img in progress.tqdm(imgs, desc=\"Loading from list\"):\n", " time.sleep(0.1)\n", " return \"done\"\n", " load_set_btn.click(load_set, [text, textb], text2)\n", "\n", " # track nested list\n", " def load_nested_set(text, text2, progress=gr.Progress()):\n", " imgs = [[None] * 8] * 3\n", " for img_set in progress.tqdm(imgs, desc=\"Nested list\"):\n", " time.sleep(2)\n", " for img in progress.tqdm(img_set, desc=\"inner list\"):\n", " time.sleep(0.1)\n", " return \"done\"\n", " load_nested_set_btn.click(load_nested_set, [text, textb], text2)\n", "\n", " # track iterable of unknown length\n", " def load_random(data, progress=gr.Progress()):\n", " def yielder():\n", " for i in range(0, random.randint(15, 20)):\n", " time.sleep(0.1)\n", " yield None\n", " for img in progress.tqdm(yielder()):\n", " pass\n", " return \"done\"\n", " load_random_btn.click(load_random, {text, textb}, text2)\n", " \n", " # manual progress\n", " def clean_imgs(text, progress=gr.Progress()):\n", " progress(0.2, desc=\"Collecting Images\")\n", " time.sleep(1)\n", " progress(0.5, desc=\"Cleaning Images\")\n", " time.sleep(1.5)\n", " progress(0.8, desc=\"Sending Images\")\n", " time.sleep(1.5)\n", " return \"done\"\n", " clean_imgs_btn.click(clean_imgs, text, text2)\n", "\n", " # no progress\n", " def wait(text):\n", " time.sleep(4)\n", " return \"done\"\n", " wait_btn.click(wait, text, text2)\n", "\n", " # multiple progressions\n", " def do_all(data, progress=gr.Progress()):\n", " load_set(data[text], data[textb], progress)\n", " load_random(data, progress)\n", " clean_imgs(data[text], progress)\n", " progress(None)\n", " wait(text)\n", " return \"done\"\n", " do_all_btn.click(do_all, {text, textb}, text2)\n", "\n", " def track_tqdm(data, progress=gr.Progress(track_tqdm=True)):\n", " for i in tqdm.tqdm(range(5), desc=\"outer\"):\n", " for j in tqdm.tqdm(range(4), desc=\"inner\"):\n", " time.sleep(1)\n", " return \"done\"\n", " track_tqdm_btn.click(track_tqdm, {text, textb}, text2)\n", "\n", " def bind_internal_tqdm(data, progress=gr.Progress(track_tqdm=True)):\n", " outdir = \"__tmp/\" + str(uuid4())\n", " load_dataset(\"beans\", split=\"train\", cache_dir=outdir)\n", " shutil.rmtree(outdir)\n", " return \"done\"\n", " bind_internal_tqdm_btn.click(bind_internal_tqdm, {text, textb}, text2)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/progress/run.py b/demo/progress/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..29a9473d34e1163462196522101b6e22c417ee15
--- /dev/null
+++ b/demo/progress/run.py
@@ -0,0 +1,97 @@
+import gradio as gr
+import random
+import time
+import tqdm
+from datasets import load_dataset
+import shutil
+from uuid import uuid4
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ text = gr.Textbox()
+ textb = gr.Textbox()
+ with gr.Row():
+ load_set_btn = gr.Button("Load Set")
+ load_nested_set_btn = gr.Button("Load Nested Set")
+ load_random_btn = gr.Button("Load Random")
+ clean_imgs_btn = gr.Button("Clean Images")
+ wait_btn = gr.Button("Wait")
+ do_all_btn = gr.Button("Do All")
+ track_tqdm_btn = gr.Button("Bind TQDM")
+ bind_internal_tqdm_btn = gr.Button("Bind Internal TQDM")
+
+ text2 = gr.Textbox()
+
+ # track list
+ def load_set(text, text2, progress=gr.Progress()):
+ imgs = [None] * 24
+ for img in progress.tqdm(imgs, desc="Loading from list"):
+ time.sleep(0.1)
+ return "done"
+ load_set_btn.click(load_set, [text, textb], text2)
+
+ # track nested list
+ def load_nested_set(text, text2, progress=gr.Progress()):
+ imgs = [[None] * 8] * 3
+ for img_set in progress.tqdm(imgs, desc="Nested list"):
+ time.sleep(2)
+ for img in progress.tqdm(img_set, desc="inner list"):
+ time.sleep(0.1)
+ return "done"
+ load_nested_set_btn.click(load_nested_set, [text, textb], text2)
+
+ # track iterable of unknown length
+ def load_random(data, progress=gr.Progress()):
+ def yielder():
+ for i in range(0, random.randint(15, 20)):
+ time.sleep(0.1)
+ yield None
+ for img in progress.tqdm(yielder()):
+ pass
+ return "done"
+ load_random_btn.click(load_random, {text, textb}, text2)
+
+ # manual progress
+ def clean_imgs(text, progress=gr.Progress()):
+ progress(0.2, desc="Collecting Images")
+ time.sleep(1)
+ progress(0.5, desc="Cleaning Images")
+ time.sleep(1.5)
+ progress(0.8, desc="Sending Images")
+ time.sleep(1.5)
+ return "done"
+ clean_imgs_btn.click(clean_imgs, text, text2)
+
+ # no progress
+ def wait(text):
+ time.sleep(4)
+ return "done"
+ wait_btn.click(wait, text, text2)
+
+ # multiple progressions
+ def do_all(data, progress=gr.Progress()):
+ load_set(data[text], data[textb], progress)
+ load_random(data, progress)
+ clean_imgs(data[text], progress)
+ progress(None)
+ wait(text)
+ return "done"
+ do_all_btn.click(do_all, {text, textb}, text2)
+
+ def track_tqdm(data, progress=gr.Progress(track_tqdm=True)):
+ for i in tqdm.tqdm(range(5), desc="outer"):
+ for j in tqdm.tqdm(range(4), desc="inner"):
+ time.sleep(1)
+ return "done"
+ track_tqdm_btn.click(track_tqdm, {text, textb}, text2)
+
+ def bind_internal_tqdm(data, progress=gr.Progress(track_tqdm=True)):
+ outdir = "__tmp/" + str(uuid4())
+ load_dataset("beans", split="train", cache_dir=outdir)
+ shutil.rmtree(outdir)
+ return "done"
+ bind_internal_tqdm_btn.click(bind_internal_tqdm, {text, textb}, text2)
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/progress_component/requirements.txt b/demo/progress_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fa9cf06427ae88cdded67bd3d5853f32a1f5e34f
--- /dev/null
+++ b/demo/progress_component/requirements.txt
@@ -0,0 +1 @@
+tqdm
\ No newline at end of file
diff --git a/demo/progress_component/run.ipynb b/demo/progress_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e9e9064fc7fccd29cd2792d9f3cbb4fccd574e18
--- /dev/null
+++ b/demo/progress_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: progress_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio tqdm"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time \n", "\n", "def load_set(progress=gr.Progress()):\n", " imgs = [None] * 24\n", " for img in progress.tqdm(imgs, desc=\"Loading...\"):\n", " time.sleep(0.1)\n", " return \"Loaded\"\n", "\n", "\n", "with gr.Blocks() as demo:\n", " load = gr.Button(\"Load\")\n", " label = gr.Label(label=\"Loader\")\n", " load.click(load_set, outputs=label)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/progress_component/run.py b/demo/progress_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..81e114e185010324dd5d3ad12e63b3bbb0570feb
--- /dev/null
+++ b/demo/progress_component/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+import time
+
+def load_set(progress=gr.Progress()):
+ imgs = [None] * 24
+ for img in progress.tqdm(imgs, desc="Loading..."):
+ time.sleep(0.1)
+ return "Loaded"
+
+
+with gr.Blocks() as demo:
+ load = gr.Button("Load")
+ label = gr.Label(label="Loader")
+ load.click(load_set, outputs=label)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/progress_simple/run.ipynb b/demo/progress_simple/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..60198be6c7d43c2ee2abf25c7c3d7c815feeead8
--- /dev/null
+++ b/demo/progress_simple/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: progress_simple"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "def slowly_reverse(word, progress=gr.Progress()):\n", " progress(0, desc=\"Starting\")\n", " time.sleep(1)\n", " progress(0.05)\n", " new_string = \"\"\n", " for letter in progress.tqdm(word, desc=\"Reversing\"):\n", " time.sleep(0.25)\n", " new_string = letter + new_string\n", " return new_string\n", "\n", "demo = gr.Interface(slowly_reverse, gr.Text(), gr.Text())\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/progress_simple/run.py b/demo/progress_simple/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b2e28b4484e33a6d48eb79ccb6cfbed9e79cca7
--- /dev/null
+++ b/demo/progress_simple/run.py
@@ -0,0 +1,17 @@
+import gradio as gr
+import time
+
+def slowly_reverse(word, progress=gr.Progress()):
+ progress(0, desc="Starting")
+ time.sleep(1)
+ progress(0.05)
+ new_string = ""
+ for letter in progress.tqdm(word, desc="Reversing"):
+ time.sleep(0.25)
+ new_string = letter + new_string
+ return new_string
+
+demo = gr.Interface(slowly_reverse, gr.Text(), gr.Text())
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/question-answering/requirements.txt b/demo/question-answering/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39dab0fdd98d55da5ce06ddf1dacbdbda14b1372
--- /dev/null
+++ b/demo/question-answering/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
\ No newline at end of file
diff --git a/demo/question-answering/run.ipynb b/demo/question-answering/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b62032797a6e70a4a892dda0585cdc96b5dc852d
--- /dev/null
+++ b/demo/question-answering/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: question-answering"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "from transformers import AutoModelForQuestionAnswering, AutoTokenizer, pipeline\n", "\n", "model_name = \"deepset/roberta-base-squad2\"\n", "\n", "nlp = pipeline(\"question-answering\", model=model_name, tokenizer=model_name)\n", "\n", "context = \"The Amazon rainforest, also known in English as Amazonia or the Amazon Jungle, is a moist broadleaf forest that covers most of the Amazon basin of South America. This basin encompasses 7,000,000 square kilometres (2,700,000 sq mi), of which 5,500,000 square kilometres (2,100,000 sq mi) are covered by the rainforest. This region includes territory belonging to nine nations. The majority of the forest is contained within Brazil, with 60% of the rainforest, followed by Peru with 13%, Colombia with 10%, and with minor amounts in Venezuela, Ecuador, Bolivia, Guyana, Suriname and French Guiana. The Amazon represents over half of the planet's remaining rainforests, and comprises the largest and most biodiverse tract of tropical rainforest in the world, with an estimated 390 billion individual trees divided into 16,000 species.\"\n", "question = \"Which continent is the Amazon rainforest in?\"\n", "\n", "\n", "def predict(context, question):\n", " res = nlp({\"question\": question, \"context\": context})\n", " return res[\"answer\"], res[\"score\"]\n", "\n", "\n", "gr.Interface(\n", " predict,\n", " inputs=[\n", " gr.Textbox(lines=7, value=context, label=\"Context Paragraph\"),\n", " gr.Textbox(lines=2, value=question, label=\"Question\"),\n", " ],\n", " outputs=[gr.Textbox(label=\"Answer\"), gr.Textbox(label=\"Score\")],\n", ").launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/question-answering/run.py b/demo/question-answering/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ccc419cdd06862adf329afd31d33400be8e4bfe
--- /dev/null
+++ b/demo/question-answering/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+
+from transformers import AutoModelForQuestionAnswering, AutoTokenizer, pipeline
+
+model_name = "deepset/roberta-base-squad2"
+
+nlp = pipeline("question-answering", model=model_name, tokenizer=model_name)
+
+context = "The Amazon rainforest, also known in English as Amazonia or the Amazon Jungle, is a moist broadleaf forest that covers most of the Amazon basin of South America. This basin encompasses 7,000,000 square kilometres (2,700,000 sq mi), of which 5,500,000 square kilometres (2,100,000 sq mi) are covered by the rainforest. This region includes territory belonging to nine nations. The majority of the forest is contained within Brazil, with 60% of the rainforest, followed by Peru with 13%, Colombia with 10%, and with minor amounts in Venezuela, Ecuador, Bolivia, Guyana, Suriname and French Guiana. The Amazon represents over half of the planet's remaining rainforests, and comprises the largest and most biodiverse tract of tropical rainforest in the world, with an estimated 390 billion individual trees divided into 16,000 species."
+question = "Which continent is the Amazon rainforest in?"
+
+
+def predict(context, question):
+ res = nlp({"question": question, "context": context})
+ return res["answer"], res["score"]
+
+
+gr.Interface(
+ predict,
+ inputs=[
+ gr.Textbox(lines=7, value=context, label="Context Paragraph"),
+ gr.Textbox(lines=2, value=question, label="Question"),
+ ],
+ outputs=[gr.Textbox(label="Answer"), gr.Textbox(label="Score")],
+).launch()
diff --git a/demo/queue_full_e2e_test/run.ipynb b/demo/queue_full_e2e_test/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..fca70fd9328a20d3670344c4bbcd7e2af04d9b3d
--- /dev/null
+++ b/demo/queue_full_e2e_test/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: queue_full_e2e_test"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "import random\n", "\n", "n_calls = 0\n", "\n", "def get_random_number():\n", " global n_calls\n", " if n_calls == 1:\n", " n_calls += 1\n", " raise gr.Error(\"This is a gradio error\")\n", " n_calls += 1\n", " time.sleep(5)\n", " return random.randrange(1, 10)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " first = gr.Button(\"First Call\")\n", " second = gr.Button(\"Second Call\")\n", " third = gr.Button(\"Third Call\")\n", " fourth = gr.Button(\"Fourth Call\")\n", " with gr.Column():\n", " first_o = gr.Number(label=\"First Result\")\n", " second_o = gr.Number(label=\"Second Result\")\n", " third_o = gr.Number(label=\"Third Result\")\n", " fourth_o = gr.Number(label=\"Fourth Result\")\n", " \n", " first.click(get_random_number, None, first_o, concurrency_id=\"f\")\n", " second.click(get_random_number, None, second_o, concurrency_id=\"f\")\n", " third.click(get_random_number, None, third_o, concurrency_id=\"f\")\n", " fourth.click(get_random_number, None, fourth_o, concurrency_id=\"f\")\n", "\n", "demo.queue(max_size=2)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/queue_full_e2e_test/run.py b/demo/queue_full_e2e_test/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1e1a06634d2d86d49c0740cf26c320f86832569
--- /dev/null
+++ b/demo/queue_full_e2e_test/run.py
@@ -0,0 +1,38 @@
+import gradio as gr
+import time
+import random
+
+n_calls = 0
+
+def get_random_number():
+ global n_calls
+ if n_calls == 1:
+ n_calls += 1
+ raise gr.Error("This is a gradio error")
+ n_calls += 1
+ time.sleep(5)
+ return random.randrange(1, 10)
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ first = gr.Button("First Call")
+ second = gr.Button("Second Call")
+ third = gr.Button("Third Call")
+ fourth = gr.Button("Fourth Call")
+ with gr.Column():
+ first_o = gr.Number(label="First Result")
+ second_o = gr.Number(label="Second Result")
+ third_o = gr.Number(label="Third Result")
+ fourth_o = gr.Number(label="Fourth Result")
+
+ first.click(get_random_number, None, first_o, concurrency_id="f")
+ second.click(get_random_number, None, second_o, concurrency_id="f")
+ third.click(get_random_number, None, third_o, concurrency_id="f")
+ fourth.click(get_random_number, None, fourth_o, concurrency_id="f")
+
+demo.queue(max_size=2)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/radio_component/run.ipynb b/demo/radio_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7ab1b08111f0f7bbec54276f168a9f27ade1a6ba
--- /dev/null
+++ b/demo/radio_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: radio_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Radio(choices=[\"First Choice\", \"Second Choice\", \"Third Choice\"])\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/radio_component/run.py b/demo/radio_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..97396da00b05f7c4198995ab208a19469f6bcb69
--- /dev/null
+++ b/demo/radio_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Radio(choices=["First Choice", "Second Choice", "Third Choice"])
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/random_demos.py b/demo/random_demos.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c206f4323ed8698bb60de67ffdab7f1cbcdfe5b
--- /dev/null
+++ b/demo/random_demos.py
@@ -0,0 +1,40 @@
+"""Opens X demos randomly for quick inspection
+
+Usage: python random_demos.py
+Example: python random_demos.py 8
+
+Assumes:
+- This is being run from the gradio/demo/ directory
+"""
+
+from __future__ import annotations
+
+import argparse
+import importlib
+import os
+import random
+
+import gradio as gr
+
+parser = argparse.ArgumentParser()
+parser.add_argument("num_demos", help="number of demos to launch", type=int, default=4)
+args = parser.parse_args()
+
+# get the list of directory names
+demos_list = next(os.walk('.'))[1]
+
+# Some demos are just too large or need to be run in a special way, so we'll just skip them
+demos_list.remove('streaming_wav2vec')
+demos_list.remove('blocks_neural_instrument_coding')
+demos_list.remove('flagged')
+
+for d, demo_name in enumerate(random.sample(demos_list, args.num_demos)):
+ print(f"Launching demo {d+1}/{args.num_demos}: {demo_name}")
+ # import the run.py file from inside the directory specified by args.demo_name
+ run = importlib.import_module(f"{demo_name}.run")
+ demo: gr.Blocks = run.demo
+ if d == args.num_demos - 1:
+ demo.launch(prevent_thread_lock=False, inbrowser=True) # prevent main thread from exiting
+ else:
+ demo.launch(prevent_thread_lock=True, inbrowser=True)
+
\ No newline at end of file
diff --git a/demo/request_ip_headers/run.ipynb b/demo/request_ip_headers/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3e7810f8503790d9e06de48967b1393cc0425764
--- /dev/null
+++ b/demo/request_ip_headers/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: request_ip_headers"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def predict(text, request: gr.Request):\n", " headers = request.headers\n", " host = request.client.host\n", " user_agent = request.headers[\"user-agent\"]\n", " return {\n", " \"ip\": host,\n", " \"user_agent\": user_agent,\n", " \"headers\": headers,\n", " }\n", "\n", "\n", "gr.Interface(predict, \"text\", \"json\").queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/request_ip_headers/run.py b/demo/request_ip_headers/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbd9fff25ccd1fdb22f63353c3dd578a563c6337
--- /dev/null
+++ b/demo/request_ip_headers/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+
+def predict(text, request: gr.Request):
+ headers = request.headers
+ host = request.client.host
+ user_agent = request.headers["user-agent"]
+ return {
+ "ip": host,
+ "user_agent": user_agent,
+ "headers": headers,
+ }
+
+
+gr.Interface(predict, "text", "json").queue().launch()
diff --git a/demo/reverse_audio/audio/cantina.wav b/demo/reverse_audio/audio/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/reverse_audio/audio/cantina.wav differ
diff --git a/demo/reverse_audio/audio/recording1.wav b/demo/reverse_audio/audio/recording1.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a58ba5006d4afbfce2b13764e0fc8768286a340d
Binary files /dev/null and b/demo/reverse_audio/audio/recording1.wav differ
diff --git a/demo/reverse_audio/run.ipynb b/demo/reverse_audio/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..84d467acb75d069e6eaea0e775a8676ab02cc303
--- /dev/null
+++ b/demo/reverse_audio/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: reverse_audio"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('audio')\n", "!wget -q -O audio/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/reverse_audio/audio/cantina.wav\n", "!wget -q -O audio/recording1.wav https://github.com/gradio-app/gradio/raw/main/demo/reverse_audio/audio/recording1.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "\n", "import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def reverse_audio(audio):\n", " sr, data = audio\n", " return (sr, np.flipud(data))\n", "\n", "\n", "input_audio = gr.Audio(\n", " sources=[\"microphone\"],\n", " waveform_options=gr.WaveformOptions(\n", " waveform_color=\"#01C6FF\",\n", " waveform_progress_color=\"#0066B4\",\n", " skip_length=2,\n", " show_controls=False,\n", " ),\n", ")\n", "demo = gr.Interface(\n", " fn=reverse_audio,\n", " inputs=input_audio,\n", " outputs=\"audio\",\n", " examples=[\n", " \"https://samplelib.com/lib/preview/mp3/sample-3s.mp3\",\n", " os.path.join(os.path.abspath(''), \"audio/recording1.wav\"),\n", " ],\n", " cache_examples=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/reverse_audio/run.py b/demo/reverse_audio/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4192e8d03a7630e6b97806fb7a9308006e4c896d
--- /dev/null
+++ b/demo/reverse_audio/run.py
@@ -0,0 +1,34 @@
+import os
+
+import numpy as np
+
+import gradio as gr
+
+
+def reverse_audio(audio):
+ sr, data = audio
+ return (sr, np.flipud(data))
+
+
+input_audio = gr.Audio(
+ sources=["microphone"],
+ waveform_options=gr.WaveformOptions(
+ waveform_color="#01C6FF",
+ waveform_progress_color="#0066B4",
+ skip_length=2,
+ show_controls=False,
+ ),
+)
+demo = gr.Interface(
+ fn=reverse_audio,
+ inputs=input_audio,
+ outputs="audio",
+ examples=[
+ "https://samplelib.com/lib/preview/mp3/sample-3s.mp3",
+ os.path.join(os.path.dirname(__file__), "audio/recording1.wav"),
+ ],
+ cache_examples=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/reverse_audio/screenshot.png b/demo/reverse_audio/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..796151630ac2bb931d09cfa511c0084a6fc391a1
Binary files /dev/null and b/demo/reverse_audio/screenshot.png differ
diff --git a/demo/reverse_audio_2/requirements.txt b/demo/reverse_audio_2/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..296d654528b719e554528b956c4bf5a1516e812c
--- /dev/null
+++ b/demo/reverse_audio_2/requirements.txt
@@ -0,0 +1 @@
+numpy
\ No newline at end of file
diff --git a/demo/reverse_audio_2/run.ipynb b/demo/reverse_audio_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e0d50ab098386e8ba9e3fc97c2b6777cc7c85659
--- /dev/null
+++ b/demo/reverse_audio_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: reverse_audio_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "\n", "\n", "def reverse_audio(audio):\n", " sr, data = audio\n", " return (sr, np.flipud(data))\n", "\n", "\n", "demo = gr.Interface(fn=reverse_audio, \n", " inputs=\"microphone\", \n", " outputs=\"audio\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/reverse_audio_2/run.py b/demo/reverse_audio_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a10b40cc4d797436a046219c28726bd4e644de9
--- /dev/null
+++ b/demo/reverse_audio_2/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+import numpy as np
+
+
+def reverse_audio(audio):
+ sr, data = audio
+ return (sr, np.flipud(data))
+
+
+demo = gr.Interface(fn=reverse_audio,
+ inputs="microphone",
+ outputs="audio")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/reversible_flow/run.ipynb b/demo/reversible_flow/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..00b2dc5642705fed3d0c95f8897da4e644314891
--- /dev/null
+++ b/demo/reversible_flow/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: reversible_flow"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def increase(num):\n", " return num + 1\n", "\n", "with gr.Blocks() as demo:\n", " a = gr.Number(label=\"a\")\n", " b = gr.Number(label=\"b\")\n", " atob = gr.Button(\"a > b\")\n", " btoa = gr.Button(\"b > a\")\n", " atob.click(increase, a, b)\n", " btoa.click(increase, b, a)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/reversible_flow/run.py b/demo/reversible_flow/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff5db0343f200265fbee262f7451ca6d2e5920fc
--- /dev/null
+++ b/demo/reversible_flow/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+
+def increase(num):
+ return num + 1
+
+with gr.Blocks() as demo:
+ a = gr.Number(label="a")
+ b = gr.Number(label="b")
+ atob = gr.Button("a > b")
+ btoa = gr.Button("b > a")
+ atob.click(increase, a, b)
+ btoa.click(increase, b, a)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/rows_and_columns/images/cheetah.jpg b/demo/rows_and_columns/images/cheetah.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/demo/rows_and_columns/images/cheetah.jpg differ
diff --git a/demo/rows_and_columns/run.ipynb b/demo/rows_and_columns/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..97214e96241339bcf90d53a38b921dbe85290b5f
--- /dev/null
+++ b/demo/rows_and_columns/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: rows_and_columns"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('images')\n", "!wget -q -O images/cheetah.jpg https://github.com/gradio-app/gradio/raw/main/demo/rows_and_columns/images/cheetah.jpg"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " text1 = gr.Textbox(label=\"t1\")\n", " slider2 = gr.Textbox(label=\"s2\")\n", " drop3 = gr.Dropdown([\"a\", \"b\", \"c\"], label=\"d3\")\n", " with gr.Row():\n", " with gr.Column(scale=1, min_width=600):\n", " text1 = gr.Textbox(label=\"prompt 1\")\n", " text2 = gr.Textbox(label=\"prompt 2\")\n", " inbtw = gr.Button(\"Between\")\n", " text4 = gr.Textbox(label=\"prompt 1\")\n", " text5 = gr.Textbox(label=\"prompt 2\")\n", " with gr.Column(scale=2, min_width=600):\n", " img1 = gr.Image(\"images/cheetah.jpg\")\n", " btn = gr.Button(\"Go\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/rows_and_columns/run.py b/demo/rows_and_columns/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5dbdd74b3b0be6cc0ae60969fcf05912e26544f
--- /dev/null
+++ b/demo/rows_and_columns/run.py
@@ -0,0 +1,20 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ text1 = gr.Textbox(label="t1")
+ slider2 = gr.Textbox(label="s2")
+ drop3 = gr.Dropdown(["a", "b", "c"], label="d3")
+ with gr.Row():
+ with gr.Column(scale=1, min_width=600):
+ text1 = gr.Textbox(label="prompt 1")
+ text2 = gr.Textbox(label="prompt 2")
+ inbtw = gr.Button("Between")
+ text4 = gr.Textbox(label="prompt 1")
+ text5 = gr.Textbox(label="prompt 2")
+ with gr.Column(scale=2, min_width=600):
+ img1 = gr.Image("images/cheetah.jpg")
+ btn = gr.Button("Go")
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/sales_projections/requirements.txt b/demo/sales_projections/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..44974cf43c7d87ca1f9cc74aba8d87b4dd23e9b8
--- /dev/null
+++ b/demo/sales_projections/requirements.txt
@@ -0,0 +1,3 @@
+pandas
+numpy
+matplotlib
\ No newline at end of file
diff --git a/demo/sales_projections/run.ipynb b/demo/sales_projections/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3d75704d202c618e955e95751cdd3494a1823774
--- /dev/null
+++ b/demo/sales_projections/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sales_projections"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pandas numpy matplotlib"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def sales_projections(employee_data):\n", " sales_data = employee_data.iloc[:, 1:4].astype(\"int\").to_numpy()\n", " regression_values = np.apply_along_axis(\n", " lambda row: np.array(np.poly1d(np.polyfit([0, 1, 2], row, 2))), 0, sales_data\n", " )\n", " projected_months = np.repeat(\n", " np.expand_dims(np.arange(3, 12), 0), len(sales_data), axis=0\n", " )\n", " projected_values = np.array(\n", " [\n", " month * month * regression[0] + month * regression[1] + regression[2]\n", " for month, regression in zip(projected_months, regression_values)\n", " ]\n", " )\n", " plt.plot(projected_values.T)\n", " plt.legend(employee_data[\"Name\"])\n", " return employee_data, plt.gcf(), regression_values\n", "\n", "\n", "demo = gr.Interface(\n", " sales_projections,\n", " gr.Dataframe(\n", " headers=[\"Name\", \"Jan Sales\", \"Feb Sales\", \"Mar Sales\"],\n", " value=[[\"Jon\", 12, 14, 18], [\"Alice\", 14, 17, 2], [\"Sana\", 8, 9.5, 12]],\n", " ),\n", " [\"dataframe\", \"plot\", \"numpy\"],\n", " description=\"Enter sales figures for employees to predict sales trajectory over year.\",\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sales_projections/run.py b/demo/sales_projections/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..33cdea5ae0afd49a1bcd57b343b78b2234e5bb77
--- /dev/null
+++ b/demo/sales_projections/run.py
@@ -0,0 +1,36 @@
+import matplotlib.pyplot as plt
+import numpy as np
+
+import gradio as gr
+
+
+def sales_projections(employee_data):
+ sales_data = employee_data.iloc[:, 1:4].astype("int").to_numpy()
+ regression_values = np.apply_along_axis(
+ lambda row: np.array(np.poly1d(np.polyfit([0, 1, 2], row, 2))), 0, sales_data
+ )
+ projected_months = np.repeat(
+ np.expand_dims(np.arange(3, 12), 0), len(sales_data), axis=0
+ )
+ projected_values = np.array(
+ [
+ month * month * regression[0] + month * regression[1] + regression[2]
+ for month, regression in zip(projected_months, regression_values)
+ ]
+ )
+ plt.plot(projected_values.T)
+ plt.legend(employee_data["Name"])
+ return employee_data, plt.gcf(), regression_values
+
+
+demo = gr.Interface(
+ sales_projections,
+ gr.Dataframe(
+ headers=["Name", "Jan Sales", "Feb Sales", "Mar Sales"],
+ value=[["Jon", 12, 14, 18], ["Alice", 14, 17, 2], ["Sana", 8, 9.5, 12]],
+ ),
+ ["dataframe", "plot", "numpy"],
+ description="Enter sales figures for employees to predict sales trajectory over year.",
+)
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/sales_projections/screenshot.gif b/demo/sales_projections/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2460d235a20e02d6a46e00903f330c80ee873334
--- /dev/null
+++ b/demo/sales_projections/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bf5c0ef79446b0cb270d556225ef8866084226bdf79c888f359183c2a19e7245
+size 5872200
diff --git a/demo/same-person-or-different/DESCRIPTION.md b/demo/same-person-or-different/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..f2821dc25933fc6f754876bb186221822d8ce7ec
--- /dev/null
+++ b/demo/same-person-or-different/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo identifies if two speakers are the same person using Gradio's Audio and HTML components.
\ No newline at end of file
diff --git a/demo/same-person-or-different/packages.txt b/demo/same-person-or-different/packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a9f1eea092d5e971b5475b82ee835cec7f196bad
--- /dev/null
+++ b/demo/same-person-or-different/packages.txt
@@ -0,0 +1 @@
+ffmpeg
\ No newline at end of file
diff --git a/demo/same-person-or-different/requirements.txt b/demo/same-person-or-different/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..baca89850c284e4dc6477356274e433f91c2308b
--- /dev/null
+++ b/demo/same-person-or-different/requirements.txt
@@ -0,0 +1,2 @@
+git+https://github.com/huggingface/transformers
+torchaudio
diff --git a/demo/same-person-or-different/run.ipynb b/demo/same-person-or-different/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a37c4e3446405061020ed8ebd133a724b9ba5954
--- /dev/null
+++ b/demo/same-person-or-different/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: same-person-or-different\n", "### This demo identifies if two speakers are the same person using Gradio's Audio and HTML components.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio git+https://github.com/huggingface/transformers torchaudio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/same-person-or-different/packages.txt\n", "os.mkdir('samples')\n", "!wget -q -O samples/cate_blanch.mp3 https://github.com/gradio-app/gradio/raw/main/demo/same-person-or-different/samples/cate_blanch.mp3\n", "!wget -q -O samples/cate_blanch_2.mp3 https://github.com/gradio-app/gradio/raw/main/demo/same-person-or-different/samples/cate_blanch_2.mp3\n", "!wget -q -O samples/heath_ledger.mp3 https://github.com/gradio-app/gradio/raw/main/demo/same-person-or-different/samples/heath_ledger.mp3"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "from torchaudio.sox_effects import apply_effects_file\n", "from transformers import AutoFeatureExtractor, AutoModelForAudioXVector\n", "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", "\n", "OUTPUT_OK = (\n", " \"\"\"\n", " \n", "
The speakers are \n", "
{:.1f}% \n", "
similar \n", "
Welcome, human! \n", "
(You must get at least 85% to be considered the same person) \n", "
\n", "\"\"\"\n", ")\n", "OUTPUT_FAIL = (\n", " \"\"\"\n", "
\n", "
The speakers are \n", "
{:.1f}% \n", "
similar \n", "
You shall not pass! \n", "
(You must get at least 85% to be considered the same person) \n", "
\n", "\"\"\"\n", ")\n", "\n", "EFFECTS = [\n", " [\"remix\", \"-\"],\n", " [\"channels\", \"1\"],\n", " [\"rate\", \"16000\"],\n", " [\"gain\", \"-1.0\"],\n", " [\"silence\", \"1\", \"0.1\", \"0.1%\", \"-1\", \"0.1\", \"0.1%\"],\n", " [\"trim\", \"0\", \"10\"],\n", "]\n", "\n", "THRESHOLD = 0.85\n", "\n", "model_name = \"microsoft/unispeech-sat-base-plus-sv\"\n", "feature_extractor = AutoFeatureExtractor.from_pretrained(model_name)\n", "model = AutoModelForAudioXVector.from_pretrained(model_name).to(device)\n", "cosine_sim = torch.nn.CosineSimilarity(dim=-1)\n", "\n", "\n", "def similarity_fn(path1, path2):\n", " if not (path1 and path2):\n", " return '
ERROR: Please record audio for *both* speakers! '\n", "\n", " wav1, _ = apply_effects_file(path1, EFFECTS)\n", " wav2, _ = apply_effects_file(path2, EFFECTS)\n", " print(wav1.shape, wav2.shape)\n", "\n", " input1 = feature_extractor(wav1.squeeze(0), return_tensors=\"pt\", sampling_rate=16000).input_values.to(device)\n", " input2 = feature_extractor(wav2.squeeze(0), return_tensors=\"pt\", sampling_rate=16000).input_values.to(device)\n", "\n", " with torch.no_grad():\n", " emb1 = model(input1).embeddings\n", " emb2 = model(input2).embeddings\n", " emb1 = torch.nn.functional.normalize(emb1, dim=-1).cpu()\n", " emb2 = torch.nn.functional.normalize(emb2, dim=-1).cpu()\n", " similarity = cosine_sim(emb1, emb2).numpy()[0]\n", "\n", " if similarity >= THRESHOLD:\n", " output = OUTPUT_OK.format(similarity * 100)\n", " else:\n", " output = OUTPUT_FAIL.format(similarity * 100)\n", "\n", " return output\n", "\n", "inputs = [\n", " gr.Audio(sources=[\"microphone\"], type=\"filepath\", label=\"Speaker #1\"),\n", " gr.Audio(sources=[\"microphone\"], type=\"filepath\", label=\"Speaker #2\"),\n", "]\n", "output = gr.HTML(label=\"\")\n", "\n", "\n", "description = (\n", " \"This demo from Microsoft will compare two speech samples and determine if they are from the same speaker. \"\n", " \"Try it with your own voice!\"\n", ")\n", "article = (\n", " \"
\"\n", " \"\ud83c\udf99\ufe0f Learn more about UniSpeech-SAT | \"\n", " \"\ud83d\udcda UniSpeech-SAT paper | \"\n", " \"\ud83d\udcda X-Vector paper \"\n", " \"
\"\n", ")\n", "examples = [\n", " [\"samples/cate_blanch.mp3\", \"samples/cate_blanch_2.mp3\"],\n", " [\"samples/cate_blanch.mp3\", \"samples/heath_ledger.mp3\"],\n", "]\n", "\n", "interface = gr.Interface(\n", " fn=similarity_fn,\n", " inputs=inputs,\n", " outputs=output,\n", " layout=\"horizontal\",\n", " allow_flagging=False,\n", " live=False,\n", " examples=examples,\n", " cache_examples=False\n", ")\n", "interface.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/same-person-or-different/run.py b/demo/same-person-or-different/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5313b2304a39eb35dc9db2f7033e5b468a6ff772
--- /dev/null
+++ b/demo/same-person-or-different/run.py
@@ -0,0 +1,105 @@
+import gradio as gr
+import torch
+from torchaudio.sox_effects import apply_effects_file
+from transformers import AutoFeatureExtractor, AutoModelForAudioXVector
+device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+
+OUTPUT_OK = (
+ """
+
+
The speakers are
+
{:.1f}%
+
similar
+
Welcome, human!
+
(You must get at least 85% to be considered the same person)
+
+"""
+)
+OUTPUT_FAIL = (
+ """
+
+
The speakers are
+
{:.1f}%
+
similar
+
You shall not pass!
+
(You must get at least 85% to be considered the same person)
+
+"""
+)
+
+EFFECTS = [
+ ["remix", "-"],
+ ["channels", "1"],
+ ["rate", "16000"],
+ ["gain", "-1.0"],
+ ["silence", "1", "0.1", "0.1%", "-1", "0.1", "0.1%"],
+ ["trim", "0", "10"],
+]
+
+THRESHOLD = 0.85
+
+model_name = "microsoft/unispeech-sat-base-plus-sv"
+feature_extractor = AutoFeatureExtractor.from_pretrained(model_name)
+model = AutoModelForAudioXVector.from_pretrained(model_name).to(device)
+cosine_sim = torch.nn.CosineSimilarity(dim=-1)
+
+
+def similarity_fn(path1, path2):
+ if not (path1 and path2):
+ return '
ERROR: Please record audio for *both* speakers! '
+
+ wav1, _ = apply_effects_file(path1, EFFECTS)
+ wav2, _ = apply_effects_file(path2, EFFECTS)
+ print(wav1.shape, wav2.shape)
+
+ input1 = feature_extractor(wav1.squeeze(0), return_tensors="pt", sampling_rate=16000).input_values.to(device)
+ input2 = feature_extractor(wav2.squeeze(0), return_tensors="pt", sampling_rate=16000).input_values.to(device)
+
+ with torch.no_grad():
+ emb1 = model(input1).embeddings
+ emb2 = model(input2).embeddings
+ emb1 = torch.nn.functional.normalize(emb1, dim=-1).cpu()
+ emb2 = torch.nn.functional.normalize(emb2, dim=-1).cpu()
+ similarity = cosine_sim(emb1, emb2).numpy()[0]
+
+ if similarity >= THRESHOLD:
+ output = OUTPUT_OK.format(similarity * 100)
+ else:
+ output = OUTPUT_FAIL.format(similarity * 100)
+
+ return output
+
+inputs = [
+ gr.Audio(sources=["microphone"], type="filepath", label="Speaker #1"),
+ gr.Audio(sources=["microphone"], type="filepath", label="Speaker #2"),
+]
+output = gr.HTML(label="")
+
+
+description = (
+ "This demo from Microsoft will compare two speech samples and determine if they are from the same speaker. "
+ "Try it with your own voice!"
+)
+article = (
+ "
"
+ "🎙️ Learn more about UniSpeech-SAT | "
+ "📚 UniSpeech-SAT paper | "
+ "📚 X-Vector paper "
+ "
"
+)
+examples = [
+ ["samples/cate_blanch.mp3", "samples/cate_blanch_2.mp3"],
+ ["samples/cate_blanch.mp3", "samples/heath_ledger.mp3"],
+]
+
+interface = gr.Interface(
+ fn=similarity_fn,
+ inputs=inputs,
+ outputs=output,
+ layout="horizontal",
+ allow_flagging=False,
+ live=False,
+ examples=examples,
+ cache_examples=False
+)
+interface.launch()
diff --git a/demo/same-person-or-different/samples/cate_blanch.mp3 b/demo/same-person-or-different/samples/cate_blanch.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..4beee74653732ae01f47089374954d77666d69bc
Binary files /dev/null and b/demo/same-person-or-different/samples/cate_blanch.mp3 differ
diff --git a/demo/same-person-or-different/samples/cate_blanch_2.mp3 b/demo/same-person-or-different/samples/cate_blanch_2.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..1acc2128c9d480adb4a8618578453041c6afaf6b
Binary files /dev/null and b/demo/same-person-or-different/samples/cate_blanch_2.mp3 differ
diff --git a/demo/same-person-or-different/samples/heath_ledger.mp3 b/demo/same-person-or-different/samples/heath_ledger.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..eb63071e1b3da9fcd072ec2801eb6165c49b0cb3
Binary files /dev/null and b/demo/same-person-or-different/samples/heath_ledger.mp3 differ
diff --git a/demo/save_file_no_output/run.ipynb b/demo/save_file_no_output/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..73988d9cafaf05380189af6052470cbf396a5562
--- /dev/null
+++ b/demo/save_file_no_output/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: save_file_no_output"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import random\n", "import string\n", "import gradio as gr \n", "\n", "def save_image_random_name(image):\n", " random_string = ''.join(random.choices(string.ascii_letters, k=20)) + '.png'\n", " image.save(random_string)\n", " print(f\"Saved image to {random_string}!\")\n", "\n", "demo = gr.Interface(\n", " fn=save_image_random_name, \n", " inputs=gr.Image(type=\"pil\"), \n", " outputs=None,\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/save_file_no_output/run.py b/demo/save_file_no_output/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..61508a714e28d8e68fcc250e80720048d1e9b31c
--- /dev/null
+++ b/demo/save_file_no_output/run.py
@@ -0,0 +1,16 @@
+import random
+import string
+import gradio as gr
+
+def save_image_random_name(image):
+ random_string = ''.join(random.choices(string.ascii_letters, k=20)) + '.png'
+ image.save(random_string)
+ print(f"Saved image to {random_string}!")
+
+demo = gr.Interface(
+ fn=save_image_random_name,
+ inputs=gr.Image(type="pil"),
+ outputs=None,
+)
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/scatter_plot/requirements.txt b/demo/scatter_plot/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7e0e60ebe2639c9bb9fc78a1be2c2888fed1fafb
--- /dev/null
+++ b/demo/scatter_plot/requirements.txt
@@ -0,0 +1,2 @@
+vega_datasets
+pandas
\ No newline at end of file
diff --git a/demo/scatter_plot/run.ipynb b/demo/scatter_plot/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..ca9e7f5a75c010f0a6418c177ce69bd36d7ebda4
--- /dev/null
+++ b/demo/scatter_plot/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatter_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "iris = data.iris()\n", "\n", "# # Or generate your own fake data\n", "\n", "# import pandas as pd\n", "# import random\n", "\n", "# cars_data = {\n", "# \"Name\": [\"car name \" + f\" {int(i/10)}\" for i in range(400)],\n", "# \"Miles_per_Gallon\": [random.randint(10, 30) for _ in range(400)],\n", "# \"Origin\": [random.choice([\"USA\", \"Europe\", \"Japan\"]) for _ in range(400)],\n", "# \"Horsepower\": [random.randint(50, 250) for _ in range(400)],\n", "# }\n", "\n", "# iris_data = {\n", "# \"petalWidth\": [round(random.uniform(0, 2.5), 2) for _ in range(150)],\n", "# \"petalLength\": [round(random.uniform(0, 7), 2) for _ in range(150)],\n", "# \"species\": [\n", "# random.choice([\"setosa\", \"versicolor\", \"virginica\"]) for _ in range(150)\n", "# ],\n", "# }\n", "\n", "# cars = pd.DataFrame(cars_data)\n", "# iris = pd.DataFrame(iris_data)\n", "\n", "\n", "def scatter_plot_fn(dataset):\n", " if dataset == \"iris\":\n", " return gr.ScatterPlot(\n", " value=iris,\n", " x=\"petalWidth\",\n", " y=\"petalLength\",\n", " color=\"species\",\n", " title=\"Iris Dataset\",\n", " color_legend_title=\"Species\",\n", " x_title=\"Petal Width\",\n", " y_title=\"Petal Length\",\n", " tooltip=[\"petalWidth\", \"petalLength\", \"species\"],\n", " caption=\"\",\n", " )\n", " else:\n", " return gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " caption=\"MPG vs Horsepower of various cars\",\n", " )\n", "\n", "\n", "with gr.Blocks() as scatter_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(choices=[\"cars\", \"iris\"], value=\"cars\")\n", " with gr.Column():\n", " plot = gr.ScatterPlot()\n", " dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)\n", " scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "if __name__ == \"__main__\":\n", " scatter_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/scatter_plot/run.py b/demo/scatter_plot/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5cc11df2690fb1c146987b7587925931b216aa9e
--- /dev/null
+++ b/demo/scatter_plot/run.py
@@ -0,0 +1,69 @@
+import gradio as gr
+from vega_datasets import data
+
+cars = data.cars()
+iris = data.iris()
+
+# # Or generate your own fake data
+
+# import pandas as pd
+# import random
+
+# cars_data = {
+# "Name": ["car name " + f" {int(i/10)}" for i in range(400)],
+# "Miles_per_Gallon": [random.randint(10, 30) for _ in range(400)],
+# "Origin": [random.choice(["USA", "Europe", "Japan"]) for _ in range(400)],
+# "Horsepower": [random.randint(50, 250) for _ in range(400)],
+# }
+
+# iris_data = {
+# "petalWidth": [round(random.uniform(0, 2.5), 2) for _ in range(150)],
+# "petalLength": [round(random.uniform(0, 7), 2) for _ in range(150)],
+# "species": [
+# random.choice(["setosa", "versicolor", "virginica"]) for _ in range(150)
+# ],
+# }
+
+# cars = pd.DataFrame(cars_data)
+# iris = pd.DataFrame(iris_data)
+
+
+def scatter_plot_fn(dataset):
+ if dataset == "iris":
+ return gr.ScatterPlot(
+ value=iris,
+ x="petalWidth",
+ y="petalLength",
+ color="species",
+ title="Iris Dataset",
+ color_legend_title="Species",
+ x_title="Petal Width",
+ y_title="Petal Length",
+ tooltip=["petalWidth", "petalLength", "species"],
+ caption="",
+ )
+ else:
+ return gr.ScatterPlot(
+ value=cars,
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ tooltip="Name",
+ title="Car Data",
+ y_title="Miles per Gallon",
+ color_legend_title="Origin of Car",
+ caption="MPG vs Horsepower of various cars",
+ )
+
+
+with gr.Blocks() as scatter_plot:
+ with gr.Row():
+ with gr.Column():
+ dataset = gr.Dropdown(choices=["cars", "iris"], value="cars")
+ with gr.Column():
+ plot = gr.ScatterPlot()
+ dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)
+ scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)
+
+if __name__ == "__main__":
+ scatter_plot.launch()
diff --git a/demo/scatterplot_component/requirements.txt b/demo/scatterplot_component/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d1c8a7ae0396d12417907feb8ef43fb4bcc8e89c
--- /dev/null
+++ b/demo/scatterplot_component/requirements.txt
@@ -0,0 +1 @@
+vega_datasets
\ No newline at end of file
diff --git a/demo/scatterplot_component/run.ipynb b/demo/scatterplot_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..79ac60139652f1fec8b757db2b6de4c510fd1708
--- /dev/null
+++ b/demo/scatterplot_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatterplot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "\n", "with gr.Blocks() as demo:\n", " gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " container=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/scatterplot_component/run.py b/demo/scatterplot_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7069c873b2393510a9aa65ee2db3b8736cde7a7
--- /dev/null
+++ b/demo/scatterplot_component/run.py
@@ -0,0 +1,20 @@
+import gradio as gr
+from vega_datasets import data
+
+cars = data.cars()
+
+with gr.Blocks() as demo:
+ gr.ScatterPlot(
+ value=cars,
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ tooltip="Name",
+ title="Car Data",
+ y_title="Miles per Gallon",
+ color_legend_title="Origin of Car",
+ container=False,
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/score_tracker/run.ipynb b/demo/score_tracker/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..6030d1e5b6be9ef06fc9550055ef68fd22844944
--- /dev/null
+++ b/demo/score_tracker/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: score_tracker"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "scores = []\n", "\n", "def track_score(score):\n", " scores.append(score)\n", " top_scores = sorted(scores, reverse=True)[:3]\n", " return top_scores\n", "\n", "demo = gr.Interface(\n", " track_score, \n", " gr.Number(label=\"Score\"), \n", " gr.JSON(label=\"Top Scores\")\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/score_tracker/run.py b/demo/score_tracker/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b024faf61739119dbcad381e8456ba4cfb97d82d
--- /dev/null
+++ b/demo/score_tracker/run.py
@@ -0,0 +1,16 @@
+import gradio as gr
+
+scores = []
+
+def track_score(score):
+ scores.append(score)
+ top_scores = sorted(scores, reverse=True)[:3]
+ return top_scores
+
+demo = gr.Interface(
+ track_score,
+ gr.Number(label="Score"),
+ gr.JSON(label="Top Scores")
+)
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/sentence_builder/run.ipynb b/demo/sentence_builder/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8b154a371fe80b8b80a76dc4b167f704712d2420
--- /dev/null
+++ b/demo/sentence_builder/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sentence_builder"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def sentence_builder(quantity, animal, countries, place, activity_list, morning):\n", " return f\"\"\"The {quantity} {animal}s from {\" and \".join(countries)} went to the {place} where they {\" and \".join(activity_list)} until the {\"morning\" if morning else \"night\"}\"\"\"\n", "\n", "\n", "demo = gr.Interface(\n", " sentence_builder,\n", " [\n", " gr.Slider(2, 20, value=4, label=\"Count\", info=\"Choose between 2 and 20\"),\n", " gr.Dropdown(\n", " [\"cat\", \"dog\", \"bird\"], label=\"Animal\", info=\"Will add more animals later!\"\n", " ),\n", " gr.CheckboxGroup([\"USA\", \"Japan\", \"Pakistan\"], label=\"Countries\", info=\"Where are they from?\"),\n", " gr.Radio([\"park\", \"zoo\", \"road\"], label=\"Location\", info=\"Where did they go?\"),\n", " gr.Dropdown(\n", " [\"ran\", \"swam\", \"ate\", \"slept\"], value=[\"swam\", \"slept\"], multiselect=True, label=\"Activity\", info=\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nisl eget ultricies aliquam, nunc nisl aliquet nunc, eget aliquam nisl nunc vel nisl.\"\n", " ),\n", " gr.Checkbox(label=\"Morning\", info=\"Did they do it in the morning?\"),\n", " ],\n", " \"text\",\n", " examples=[\n", " [2, \"cat\", [\"Japan\", \"Pakistan\"], \"park\", [\"ate\", \"swam\"], True],\n", " [4, \"dog\", [\"Japan\"], \"zoo\", [\"ate\", \"swam\"], False],\n", " [10, \"bird\", [\"USA\", \"Pakistan\"], \"road\", [\"ran\"], False],\n", " [8, \"cat\", [\"Pakistan\"], \"zoo\", [\"ate\"], True],\n", " ]\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sentence_builder/run.py b/demo/sentence_builder/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c193c0648072c2b53316af271607b1679e44c0c7
--- /dev/null
+++ b/demo/sentence_builder/run.py
@@ -0,0 +1,32 @@
+import gradio as gr
+
+
+def sentence_builder(quantity, animal, countries, place, activity_list, morning):
+ return f"""The {quantity} {animal}s from {" and ".join(countries)} went to the {place} where they {" and ".join(activity_list)} until the {"morning" if morning else "night"}"""
+
+
+demo = gr.Interface(
+ sentence_builder,
+ [
+ gr.Slider(2, 20, value=4, label="Count", info="Choose between 2 and 20"),
+ gr.Dropdown(
+ ["cat", "dog", "bird"], label="Animal", info="Will add more animals later!"
+ ),
+ gr.CheckboxGroup(["USA", "Japan", "Pakistan"], label="Countries", info="Where are they from?"),
+ gr.Radio(["park", "zoo", "road"], label="Location", info="Where did they go?"),
+ gr.Dropdown(
+ ["ran", "swam", "ate", "slept"], value=["swam", "slept"], multiselect=True, label="Activity", info="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nisl eget ultricies aliquam, nunc nisl aliquet nunc, eget aliquam nisl nunc vel nisl."
+ ),
+ gr.Checkbox(label="Morning", info="Did they do it in the morning?"),
+ ],
+ "text",
+ examples=[
+ [2, "cat", ["Japan", "Pakistan"], "park", ["ate", "swam"], True],
+ [4, "dog", ["Japan"], "zoo", ["ate", "swam"], False],
+ [10, "bird", ["USA", "Pakistan"], "road", ["ran"], False],
+ [8, "cat", ["Pakistan"], "zoo", ["ate"], True],
+ ]
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/sentence_builder/screenshot.png b/demo/sentence_builder/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..8cf53e4d15cb38acf8ce94b16d944960d34b4adf
Binary files /dev/null and b/demo/sentence_builder/screenshot.png differ
diff --git a/demo/sentiment_analysis/DESCRIPTION.md b/demo/sentiment_analysis/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..affa1e8db01e5fb70dc6fd559bc8b4d150993124
--- /dev/null
+++ b/demo/sentiment_analysis/DESCRIPTION.md
@@ -0,0 +1 @@
+This sentiment analaysis demo takes in input text and returns its classification for either positive, negative or neutral using Gradio's Label output.
\ No newline at end of file
diff --git a/demo/sentiment_analysis/requirements.txt b/demo/sentiment_analysis/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6fa2de44417ce85838334618e6430c5e1abc6a5d
--- /dev/null
+++ b/demo/sentiment_analysis/requirements.txt
@@ -0,0 +1 @@
+nltk
\ No newline at end of file
diff --git a/demo/sentiment_analysis/run.ipynb b/demo/sentiment_analysis/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..29326a5e8d5269edf48abe9e7fd6df4ada0e1934
--- /dev/null
+++ b/demo/sentiment_analysis/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sentiment_analysis\n", "### This sentiment analaysis demo takes in input text and returns its classification for either positive, negative or neutral using Gradio's Label output.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio nltk"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import nltk\n", "from nltk.sentiment.vader import SentimentIntensityAnalyzer\n", "\n", "nltk.download(\"vader_lexicon\")\n", "sid = SentimentIntensityAnalyzer()\n", "\n", "def sentiment_analysis(text):\n", " scores = sid.polarity_scores(text)\n", " del scores[\"compound\"]\n", " return scores\n", "\n", "demo = gr.Interface(\n", " fn=sentiment_analysis, \n", " inputs=gr.Textbox(placeholder=\"Enter a positive or negative sentence here...\"), \n", " outputs=\"label\", \n", " examples=[[\"This is wonderful!\"]])\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sentiment_analysis/run.py b/demo/sentiment_analysis/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd7dedcdbbfed4bbb4eb961ccf462fa3f5ba3ef3
--- /dev/null
+++ b/demo/sentiment_analysis/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+import nltk
+from nltk.sentiment.vader import SentimentIntensityAnalyzer
+
+nltk.download("vader_lexicon")
+sid = SentimentIntensityAnalyzer()
+
+def sentiment_analysis(text):
+ scores = sid.polarity_scores(text)
+ del scores["compound"]
+ return scores
+
+demo = gr.Interface(
+ fn=sentiment_analysis,
+ inputs=gr.Textbox(placeholder="Enter a positive or negative sentence here..."),
+ outputs="label",
+ examples=[["This is wonderful!"]])
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/sepia_filter/run.ipynb b/demo/sepia_filter/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..eef299cbb92ae81c8f178af308d3d72d9bb7297f
--- /dev/null
+++ b/demo/sepia_filter/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sepia_filter"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "import gradio as gr\n", "\n", "def sepia(input_img):\n", " sepia_filter = np.array([\n", " [0.393, 0.769, 0.189], \n", " [0.349, 0.686, 0.168], \n", " [0.272, 0.534, 0.131]\n", " ])\n", " sepia_img = input_img.dot(sepia_filter.T)\n", " sepia_img /= sepia_img.max()\n", " return sepia_img\n", "\n", "demo = gr.Interface(sepia, gr.Image(), \"image\")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sepia_filter/run.py b/demo/sepia_filter/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..9977659549b12eda126feab666c2012290f8ced7
--- /dev/null
+++ b/demo/sepia_filter/run.py
@@ -0,0 +1,16 @@
+import numpy as np
+import gradio as gr
+
+def sepia(input_img):
+ sepia_filter = np.array([
+ [0.393, 0.769, 0.189],
+ [0.349, 0.686, 0.168],
+ [0.272, 0.534, 0.131]
+ ])
+ sepia_img = input_img.dot(sepia_filter.T)
+ sepia_img /= sepia_img.max()
+ return sepia_img
+
+demo = gr.Interface(sepia, gr.Image(), "image")
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/sepia_filter/screenshot.gif b/demo/sepia_filter/screenshot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6169b786aa203bcfab5e8b0da023ff646716a084
--- /dev/null
+++ b/demo/sepia_filter/screenshot.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9e7091eff30c08a023ba18c44181e743637afe20b9e2111ba0b657c1c2817648
+size 3726270
diff --git a/demo/sine_curve/requirements.txt b/demo/sine_curve/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d42d0ad03bdf8ecf9756a38df5cedf8fe431db79
--- /dev/null
+++ b/demo/sine_curve/requirements.txt
@@ -0,0 +1 @@
+plotly
\ No newline at end of file
diff --git a/demo/sine_curve/run.ipynb b/demo/sine_curve/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..08683bbbf7e7cdd070f41c365cf9bfee5d49f462
--- /dev/null
+++ b/demo/sine_curve/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sine_curve"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import math\n", "import gradio as gr\n", "import plotly.express as px\n", "import numpy as np\n", "\n", "\n", "plot_end = 2 * math.pi\n", "\n", "\n", "def get_plot(period=1):\n", " global plot_end\n", " x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)\n", " y = np.sin(2*math.pi*period * x)\n", " fig = px.line(x=x, y=y)\n", " plot_end += 2 * math.pi\n", " if plot_end > 1000:\n", " plot_end = 2 * math.pi\n", " return fig\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Markdown(\"Change the value of the slider to automatically update the plot\")\n", " period = gr.Slider(label=\"Period of plot\", value=1, minimum=0, maximum=10, step=1)\n", " plot = gr.Plot(label=\"Plot (updates every half second)\")\n", "\n", " dep = demo.load(get_plot, None, plot, every=1)\n", " period.change(get_plot, period, plot, every=1, cancels=[dep])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sine_curve/run.py b/demo/sine_curve/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4f0fc7ce71a6f1edec2010ab1f65424a1567f009
--- /dev/null
+++ b/demo/sine_curve/run.py
@@ -0,0 +1,33 @@
+import math
+import gradio as gr
+import plotly.express as px
+import numpy as np
+
+
+plot_end = 2 * math.pi
+
+
+def get_plot(period=1):
+ global plot_end
+ x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)
+ y = np.sin(2*math.pi*period * x)
+ fig = px.line(x=x, y=y)
+ plot_end += 2 * math.pi
+ if plot_end > 1000:
+ plot_end = 2 * math.pi
+ return fig
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ gr.Markdown("Change the value of the slider to automatically update the plot")
+ period = gr.Slider(label="Period of plot", value=1, minimum=0, maximum=10, step=1)
+ plot = gr.Plot(label="Plot (updates every half second)")
+
+ dep = demo.load(get_plot, None, plot, every=1)
+ period.change(get_plot, period, plot, every=1, cancels=[dep])
+
+
+if __name__ == "__main__":
+ demo.queue().launch()
diff --git a/demo/slider_component/run.ipynb b/demo/slider_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..50cf32dadf35454ae24d1ea468f3e44e01052c4c
--- /dev/null
+++ b/demo/slider_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: slider_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Slider()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/slider_component/run.py b/demo/slider_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..45b1bbfa764cb208855ea851594e20194b227e48
--- /dev/null
+++ b/demo/slider_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Slider()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/slider_release/run.ipynb b/demo/slider_release/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..efb64c5194a7b5861eef7098c70ed44fabded7f9
--- /dev/null
+++ b/demo/slider_release/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: slider_release"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def identity(x, state):\n", " state += 1\n", " return x, state, state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " slider = gr.Slider(0, 100, step=0.1)\n", " state = gr.State(value=0)\n", " with gr.Row():\n", " number = gr.Number(label=\"On release\")\n", " number2 = gr.Number(label=\"Number of events fired\")\n", " slider.release(identity, inputs=[slider, state], outputs=[number, state, number2], api_name=\"predict\")\n", "\n", "if __name__ == \"__main__\":\n", " print(\"here\")\n", " demo.launch()\n", " print(demo.server_port)\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/slider_release/run.py b/demo/slider_release/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3eb183a2da554905032c097738d9ed939c1e0c11
--- /dev/null
+++ b/demo/slider_release/run.py
@@ -0,0 +1,20 @@
+import gradio as gr
+
+
+def identity(x, state):
+ state += 1
+ return x, state, state
+
+
+with gr.Blocks() as demo:
+ slider = gr.Slider(0, 100, step=0.1)
+ state = gr.State(value=0)
+ with gr.Row():
+ number = gr.Number(label="On release")
+ number2 = gr.Number(label="Number of events fired")
+ slider.release(identity, inputs=[slider, state], outputs=[number, state, number2], api_name="predict")
+
+if __name__ == "__main__":
+ print("here")
+ demo.launch()
+ print(demo.server_port)
diff --git a/demo/sort_records/polars_sort.csv b/demo/sort_records/polars_sort.csv
new file mode 100644
index 0000000000000000000000000000000000000000..3620f4c1ecb842db76e30a3011aef3af12e825f4
--- /dev/null
+++ b/demo/sort_records/polars_sort.csv
@@ -0,0 +1,4 @@
+Item,Quantity
+apple,56
+banana,12
+orange,30
diff --git a/demo/sort_records/run.ipynb b/demo/sort_records/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..c48b62e9cdcf724aa1e6d0d23c9224d2e4a7c3f9
--- /dev/null
+++ b/demo/sort_records/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sort_records"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/sort_records/polars_sort.csv"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "def sort_records(records):\n", " return records.sort(\"Quantity\")\n", "\n", "demo = gr.Interface(\n", " sort_records,\n", " gr.Dataframe(\n", " headers=[\"Item\", \"Quantity\"],\n", " datatype=[\"str\", \"number\"],\n", " row_count=3,\n", " col_count=(2, \"fixed\"),\n", " type=\"polars\"\n", " ),\n", " \"dataframe\",\n", " description=\"Sort by Quantity\",\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"polars_sort.csv\")],\n", " ],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sort_records/run.py b/demo/sort_records/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..4113c3f8ac98df4c7f44f8490c9a13c7a466169b
--- /dev/null
+++ b/demo/sort_records/run.py
@@ -0,0 +1,24 @@
+import gradio as gr
+import os
+
+def sort_records(records):
+ return records.sort("Quantity")
+
+demo = gr.Interface(
+ sort_records,
+ gr.Dataframe(
+ headers=["Item", "Quantity"],
+ datatype=["str", "number"],
+ row_count=3,
+ col_count=(2, "fixed"),
+ type="polars"
+ ),
+ "dataframe",
+ description="Sort by Quantity",
+ examples=[
+ [os.path.join(os.path.dirname(__file__), "polars_sort.csv")],
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/sound_alert/beep.mp3 b/demo/sound_alert/beep.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..cd3a3ecded0158e5ececd0520a73cfe59915e2a3
Binary files /dev/null and b/demo/sound_alert/beep.mp3 differ
diff --git a/demo/sound_alert/run.ipynb b/demo/sound_alert/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b2c49b4c17cc9971b1f20e03210cab23404239eb
--- /dev/null
+++ b/demo/sound_alert/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: sound_alert"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/sound_alert/beep.mp3"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import time\n", "import gradio as gr\n", "\n", "\n", "js_function = \"() => {new Audio('file=beep.mp3').play();}\"\n", "\n", "def task(x):\n", " time.sleep(2)\n", " return \"Hello, \" + x \n", "\n", "with gr.Blocks() as demo:\n", " name = gr.Textbox(label=\"name\")\n", " greeting = gr.Textbox(label=\"greeting\")\n", " name.blur(task, name, greeting)\n", " greeting.change(None, [], [], js=js_function)\n", " \n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/sound_alert/run.py b/demo/sound_alert/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6313c7484a078ab9e300541f7478817d3ebfe374
--- /dev/null
+++ b/demo/sound_alert/run.py
@@ -0,0 +1,17 @@
+import time
+import gradio as gr
+
+
+js_function = "() => {new Audio('file=beep.mp3').play();}"
+
+def task(x):
+ time.sleep(2)
+ return "Hello, " + x
+
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="name")
+ greeting = gr.Textbox(label="greeting")
+ name.blur(task, name, greeting)
+ greeting.change(None, [], [], js=js_function)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/spectogram/requirements.txt b/demo/spectogram/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ca6034584e0ec2dde9b16b581bab6d6a8327a59a
--- /dev/null
+++ b/demo/spectogram/requirements.txt
@@ -0,0 +1,3 @@
+scipy
+numpy
+matplotlib
\ No newline at end of file
diff --git a/demo/spectogram/run.ipynb b/demo/spectogram/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f5968d14a4b632822220e24bbd124fa1d324c3e6
--- /dev/null
+++ b/demo/spectogram/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: spectogram"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio scipy numpy matplotlib"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt\n", "import numpy as np\n", "from scipy import signal\n", "\n", "import gradio as gr\n", "\n", "\n", "def spectrogram(audio):\n", " sr, data = audio\n", " if len(data.shape) == 2:\n", " data = np.mean(data, axis=0)\n", " frequencies, times, spectrogram_data = signal.spectrogram(\n", " data, sr, window=\"hamming\"\n", " )\n", " plt.pcolormesh(times, frequencies, np.log10(spectrogram_data))\n", " return plt\n", "\n", "\n", "demo = gr.Interface(spectrogram, \"audio\", \"plot\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/spectogram/run.py b/demo/spectogram/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..599fba4cc2f395acfa1cf47888ffb3443a6176df
--- /dev/null
+++ b/demo/spectogram/run.py
@@ -0,0 +1,22 @@
+import matplotlib.pyplot as plt
+import numpy as np
+from scipy import signal
+
+import gradio as gr
+
+
+def spectrogram(audio):
+ sr, data = audio
+ if len(data.shape) == 2:
+ data = np.mean(data, axis=0)
+ frequencies, times, spectrogram_data = signal.spectrogram(
+ data, sr, window="hamming"
+ )
+ plt.pcolormesh(times, frequencies, np.log10(spectrogram_data))
+ return plt
+
+
+demo = gr.Interface(spectrogram, "audio", "plot")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/spectogram/screenshot.png b/demo/spectogram/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f8d9d148ae18ff5d042f566d7e0a68c644f0d58
Binary files /dev/null and b/demo/spectogram/screenshot.png differ
diff --git a/demo/stable-diffusion/DESCRIPTION.md b/demo/stable-diffusion/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..0a59ff6b244acf3b95db244fd94cba10b6679ef0
--- /dev/null
+++ b/demo/stable-diffusion/DESCRIPTION.md
@@ -0,0 +1 @@
+Note: This is a simplified version of the code needed to create the Stable Diffusion demo. See full code here: https://hf.co/spaces/stabilityai/stable-diffusion/tree/main
\ No newline at end of file
diff --git a/demo/stable-diffusion/requirements.txt b/demo/stable-diffusion/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bb40240976b3d44f2a7b27e1f0c08d0bb5d292ff
--- /dev/null
+++ b/demo/stable-diffusion/requirements.txt
@@ -0,0 +1,5 @@
+diffusers
+transformers
+nvidia-ml-py3
+ftfy
+torch
\ No newline at end of file
diff --git a/demo/stable-diffusion/run.ipynb b/demo/stable-diffusion/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..95d61e17990300dfb105b5014fe183c0861a0bd3
--- /dev/null
+++ b/demo/stable-diffusion/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stable-diffusion\n", "### Note: This is a simplified version of the code needed to create the Stable Diffusion demo. See full code here: https://hf.co/spaces/stabilityai/stable-diffusion/tree/main\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio diffusers transformers nvidia-ml-py3 ftfy torch"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "from diffusers import StableDiffusionPipeline\n", "from PIL import Image\n", "import os\n", "\n", "auth_token = os.getenv(\"auth_token\")\n", "model_id = \"CompVis/stable-diffusion-v1-4\"\n", "device = \"cpu\"\n", "pipe = StableDiffusionPipeline.from_pretrained(\n", " model_id, use_auth_token=auth_token, revision=\"fp16\", torch_dtype=torch.float16\n", ")\n", "pipe = pipe.to(device)\n", "\n", "\n", "def infer(prompt, samples, steps, scale, seed):\n", " generator = torch.Generator(device=device).manual_seed(seed)\n", " images_list = pipe(\n", " [prompt] * samples,\n", " num_inference_steps=steps,\n", " guidance_scale=scale,\n", " generator=generator,\n", " )\n", " images = []\n", " safe_image = Image.open(r\"unsafe.png\")\n", " for i, image in enumerate(images_list[\"sample\"]):\n", " if images_list[\"nsfw_content_detected\"][i]:\n", " images.append(safe_image)\n", " else:\n", " images.append(image)\n", " return images\n", "\n", "\n", "block = gr.Blocks()\n", "\n", "with block:\n", " with gr.Group():\n", " with gr.Row():\n", " text = gr.Textbox(\n", " label=\"Enter your prompt\",\n", " max_lines=1,\n", " placeholder=\"Enter your prompt\",\n", " container=False,\n", " )\n", " btn = gr.Button(\"Generate image\")\n", " gallery = gr.Gallery(\n", " label=\"Generated images\",\n", " show_label=False,\n", " elem_id=\"gallery\",\n", " columns=[2],\n", " height=\"auto\",\n", " )\n", "\n", " advanced_button = gr.Button(\"Advanced options\", elem_id=\"advanced-btn\")\n", "\n", " with gr.Row(elem_id=\"advanced-options\"):\n", " samples = gr.Slider(label=\"Images\", minimum=1, maximum=4, value=4, step=1)\n", " steps = gr.Slider(label=\"Steps\", minimum=1, maximum=50, value=45, step=1)\n", " scale = gr.Slider(\n", " label=\"Guidance Scale\", minimum=0, maximum=50, value=7.5, step=0.1\n", " )\n", " seed = gr.Slider(\n", " label=\"Seed\",\n", " minimum=0,\n", " maximum=2147483647,\n", " step=1,\n", " randomize=True,\n", " )\n", " gr.on([text.submit, btn.click], infer, inputs=[text, samples, steps, scale, seed], outputs=gallery)\n", " advanced_button.click(\n", " None,\n", " [],\n", " text,\n", " )\n", "\n", "block.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stable-diffusion/run.py b/demo/stable-diffusion/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9ee8b66624b4b7fa24d7ed1dc72f43a38ab9d1b
--- /dev/null
+++ b/demo/stable-diffusion/run.py
@@ -0,0 +1,76 @@
+import gradio as gr
+import torch
+from diffusers import StableDiffusionPipeline
+from PIL import Image
+import os
+
+auth_token = os.getenv("auth_token")
+model_id = "CompVis/stable-diffusion-v1-4"
+device = "cpu"
+pipe = StableDiffusionPipeline.from_pretrained(
+ model_id, use_auth_token=auth_token, revision="fp16", torch_dtype=torch.float16
+)
+pipe = pipe.to(device)
+
+
+def infer(prompt, samples, steps, scale, seed):
+ generator = torch.Generator(device=device).manual_seed(seed)
+ images_list = pipe(
+ [prompt] * samples,
+ num_inference_steps=steps,
+ guidance_scale=scale,
+ generator=generator,
+ )
+ images = []
+ safe_image = Image.open(r"unsafe.png")
+ for i, image in enumerate(images_list["sample"]):
+ if images_list["nsfw_content_detected"][i]:
+ images.append(safe_image)
+ else:
+ images.append(image)
+ return images
+
+
+block = gr.Blocks()
+
+with block:
+ with gr.Group():
+ with gr.Row():
+ text = gr.Textbox(
+ label="Enter your prompt",
+ max_lines=1,
+ placeholder="Enter your prompt",
+ container=False,
+ )
+ btn = gr.Button("Generate image")
+ gallery = gr.Gallery(
+ label="Generated images",
+ show_label=False,
+ elem_id="gallery",
+ columns=[2],
+ height="auto",
+ )
+
+ advanced_button = gr.Button("Advanced options", elem_id="advanced-btn")
+
+ with gr.Row(elem_id="advanced-options"):
+ samples = gr.Slider(label="Images", minimum=1, maximum=4, value=4, step=1)
+ steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=45, step=1)
+ scale = gr.Slider(
+ label="Guidance Scale", minimum=0, maximum=50, value=7.5, step=0.1
+ )
+ seed = gr.Slider(
+ label="Seed",
+ minimum=0,
+ maximum=2147483647,
+ step=1,
+ randomize=True,
+ )
+ gr.on([text.submit, btn.click], infer, inputs=[text, samples, steps, scale, seed], outputs=gallery)
+ advanced_button.click(
+ None,
+ [],
+ text,
+ )
+
+block.launch()
diff --git a/demo/state_component/run.ipynb b/demo/state_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5a50fd98b37159c8e4bb0066565c97fecb09d08c
--- /dev/null
+++ b/demo/state_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: state_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.State()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/state_component/run.py b/demo/state_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..b895b79c9e734f2eb61f4654f800586c07628082
--- /dev/null
+++ b/demo/state_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.State()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/stock_forecast/requirements.txt b/demo/stock_forecast/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..806f22116faa6610345f0899927f952ae5dfedcd
--- /dev/null
+++ b/demo/stock_forecast/requirements.txt
@@ -0,0 +1,2 @@
+numpy
+matplotlib
\ No newline at end of file
diff --git a/demo/stock_forecast/run.ipynb b/demo/stock_forecast/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5fce6697fcb896143d579de8172e62d024cc70f2
--- /dev/null
+++ b/demo/stock_forecast/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stock_forecast"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy matplotlib"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import gradio as gr\n", "\n", "\n", "def plot_forecast(final_year, companies, noise, show_legend, point_style):\n", " start_year = 2020\n", " x = np.arange(start_year, final_year + 1)\n", " year_count = x.shape[0]\n", " plt_format = ({\"cross\": \"X\", \"line\": \"-\", \"circle\": \"o--\"})[point_style]\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " for i, company in enumerate(companies):\n", " series = np.arange(0, year_count, dtype=float)\n", " series = series**2 * (i + 1)\n", " series += np.random.rand(year_count) * noise\n", " ax.plot(x, series, plt_format)\n", " if show_legend:\n", " plt.legend(companies)\n", " return fig\n", "\n", "\n", "demo = gr.Interface(\n", " plot_forecast,\n", " [\n", " gr.Radio([2025, 2030, 2035, 2040], label=\"Project to:\"),\n", " gr.CheckboxGroup([\"Google\", \"Microsoft\", \"Gradio\"], label=\"Company Selection\"),\n", " gr.Slider(1, 100, label=\"Noise Level\"),\n", " gr.Checkbox(label=\"Show Legend\"),\n", " gr.Dropdown([\"cross\", \"line\", \"circle\"], label=\"Style\"),\n", " ],\n", " gr.Plot(label=\"forecast\"),\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stock_forecast/run.py b/demo/stock_forecast/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f1318c71db5974d591b5e40b9455882c6f0c5e0
--- /dev/null
+++ b/demo/stock_forecast/run.py
@@ -0,0 +1,37 @@
+import matplotlib.pyplot as plt
+import numpy as np
+
+import gradio as gr
+
+
+def plot_forecast(final_year, companies, noise, show_legend, point_style):
+ start_year = 2020
+ x = np.arange(start_year, final_year + 1)
+ year_count = x.shape[0]
+ plt_format = ({"cross": "X", "line": "-", "circle": "o--"})[point_style]
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ for i, company in enumerate(companies):
+ series = np.arange(0, year_count, dtype=float)
+ series = series**2 * (i + 1)
+ series += np.random.rand(year_count) * noise
+ ax.plot(x, series, plt_format)
+ if show_legend:
+ plt.legend(companies)
+ return fig
+
+
+demo = gr.Interface(
+ plot_forecast,
+ [
+ gr.Radio([2025, 2030, 2035, 2040], label="Project to:"),
+ gr.CheckboxGroup(["Google", "Microsoft", "Gradio"], label="Company Selection"),
+ gr.Slider(1, 100, label="Noise Level"),
+ gr.Checkbox(label="Show Legend"),
+ gr.Dropdown(["cross", "line", "circle"], label="Style"),
+ ],
+ gr.Plot(label="forecast"),
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/stock_forecast/screenshot.png b/demo/stock_forecast/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..7dbecd2cd32a6444656d36fb62ac0c9af1bfb97a
Binary files /dev/null and b/demo/stock_forecast/screenshot.png differ
diff --git a/demo/stream_asr/requirements.txt b/demo/stream_asr/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0175df5ca84e01c29d1a629d623955dafaf7d65b
--- /dev/null
+++ b/demo/stream_asr/requirements.txt
@@ -0,0 +1,3 @@
+torch
+torchaudio
+transformers
\ No newline at end of file
diff --git a/demo/stream_asr/run.ipynb b/demo/stream_asr/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..11a7b8de503eff50713468c9687e81d15cb05ced
--- /dev/null
+++ b/demo/stream_asr/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stream_asr"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch torchaudio transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import pipeline\n", "import numpy as np\n", "\n", "transcriber = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\")\n", "\n", "def transcribe(stream, new_chunk):\n", " sr, y = new_chunk\n", " y = y.astype(np.float32)\n", " y /= np.max(np.abs(y))\n", "\n", " if stream is not None:\n", " stream = np.concatenate([stream, y])\n", " else:\n", " stream = y\n", " return stream, transcriber({\"sampling_rate\": sr, \"raw\": stream})[\"text\"]\n", "\n", "\n", "demo = gr.Interface(\n", " transcribe,\n", " [\"state\", gr.Audio(sources=[\"microphone\"], streaming=True)],\n", " [\"state\", \"text\"],\n", " live=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stream_asr/run.py b/demo/stream_asr/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce5b6f72562893af7eb11ed23b85f08d41f79370
--- /dev/null
+++ b/demo/stream_asr/run.py
@@ -0,0 +1,27 @@
+import gradio as gr
+from transformers import pipeline
+import numpy as np
+
+transcriber = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")
+
+def transcribe(stream, new_chunk):
+ sr, y = new_chunk
+ y = y.astype(np.float32)
+ y /= np.max(np.abs(y))
+
+ if stream is not None:
+ stream = np.concatenate([stream, y])
+ else:
+ stream = y
+ return stream, transcriber({"sampling_rate": sr, "raw": stream})["text"]
+
+
+demo = gr.Interface(
+ transcribe,
+ ["state", gr.Audio(sources=["microphone"], streaming=True)],
+ ["state", "text"],
+ live=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/stream_audio/run.ipynb b/demo/stream_audio/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..980bdde941e7dffade21978f45600ed42382f8cb
--- /dev/null
+++ b/demo/stream_audio/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stream_audio"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "\n", "def add_to_stream(audio, instream):\n", " time.sleep(1)\n", " if audio is None:\n", " return gr.Audio(), instream\n", " if instream is None:\n", " ret = audio\n", " else:\n", " ret = (audio[0], np.concatenate((instream[1], audio[1])))\n", " return ret, ret\n", "\n", "\n", "with gr.Blocks() as demo:\n", " inp = gr.Audio(sources=[\"microphone\"])\n", " out = gr.Audio()\n", " stream = gr.State()\n", " clear = gr.Button(\"Clear\")\n", "\n", " inp.stream(add_to_stream, [inp, stream], [out, stream])\n", " clear.click(lambda: [None, None, None], None, [inp, out, stream])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stream_audio/run.py b/demo/stream_audio/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0af573d4500f0dc29dd1539781cb4ff0b49889
--- /dev/null
+++ b/demo/stream_audio/run.py
@@ -0,0 +1,27 @@
+import gradio as gr
+import numpy as np
+import time
+
+def add_to_stream(audio, instream):
+ time.sleep(1)
+ if audio is None:
+ return gr.Audio(), instream
+ if instream is None:
+ ret = audio
+ else:
+ ret = (audio[0], np.concatenate((instream[1], audio[1])))
+ return ret, ret
+
+
+with gr.Blocks() as demo:
+ inp = gr.Audio(sources=["microphone"])
+ out = gr.Audio()
+ stream = gr.State()
+ clear = gr.Button("Clear")
+
+ inp.stream(add_to_stream, [inp, stream], [out, stream])
+ clear.click(lambda: [None, None, None], None, [inp, out, stream])
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/stream_audio_out/audio/cantina.wav b/demo/stream_audio_out/audio/cantina.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41f020438468229763ec4a2321325e5916e09106
Binary files /dev/null and b/demo/stream_audio_out/audio/cantina.wav differ
diff --git a/demo/stream_audio_out/run.ipynb b/demo/stream_audio_out/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..af33bb68d67a190e2a2d288de31e469486db5a8b
--- /dev/null
+++ b/demo/stream_audio_out/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stream_audio_out"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('audio')\n", "!wget -q -O audio/cantina.wav https://github.com/gradio-app/gradio/raw/main/demo/stream_audio_out/audio/cantina.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pydub import AudioSegment\n", "from time import sleep\n", "\n", "with gr.Blocks() as demo:\n", " input_audio = gr.Audio(label=\"Input Audio\", type=\"filepath\", format=\"mp3\")\n", " with gr.Row():\n", " with gr.Column():\n", " stream_as_file_btn = gr.Button(\"Stream as File\")\n", " format = gr.Radio([\"wav\", \"mp3\"], value=\"wav\", label=\"Format\")\n", " stream_as_file_output = gr.Audio(streaming=True)\n", "\n", " def stream_file(audio_file, format):\n", " audio = AudioSegment.from_file(audio_file)\n", " i = 0\n", " chunk_size = 1000\n", " while chunk_size * i < len(audio):\n", " chunk = audio[chunk_size * i : chunk_size * (i + 1)]\n", " i += 1\n", " if chunk:\n", " file = f\"/tmp/{i}.{format}\"\n", " chunk.export(file, format=format)\n", " yield file\n", " sleep(0.5)\n", "\n", " stream_as_file_btn.click(\n", " stream_file, [input_audio, format], stream_as_file_output\n", " )\n", "\n", " gr.Examples(\n", " [[\"audio/cantina.wav\", \"wav\"], [\"audio/cantina.wav\", \"mp3\"]],\n", " [input_audio, format],\n", " fn=stream_file,\n", " outputs=stream_as_file_output,\n", " cache_examples=True,\n", " )\n", "\n", " with gr.Column():\n", " stream_as_bytes_btn = gr.Button(\"Stream as Bytes\")\n", " stream_as_bytes_output = gr.Audio(format=\"bytes\", streaming=True)\n", "\n", " def stream_bytes(audio_file):\n", " chunk_size = 20_000\n", " with open(audio_file, \"rb\") as f:\n", " while True:\n", " chunk = f.read(chunk_size)\n", " if chunk:\n", " yield chunk\n", " sleep(1)\n", " else:\n", " break\n", " stream_as_bytes_btn.click(stream_bytes, input_audio, stream_as_bytes_output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stream_audio_out/run.py b/demo/stream_audio_out/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2528e2163339430015cf940853a203b5ac8a2eca
--- /dev/null
+++ b/demo/stream_audio_out/run.py
@@ -0,0 +1,55 @@
+import gradio as gr
+from pydub import AudioSegment
+from time import sleep
+
+with gr.Blocks() as demo:
+ input_audio = gr.Audio(label="Input Audio", type="filepath", format="mp3")
+ with gr.Row():
+ with gr.Column():
+ stream_as_file_btn = gr.Button("Stream as File")
+ format = gr.Radio(["wav", "mp3"], value="wav", label="Format")
+ stream_as_file_output = gr.Audio(streaming=True)
+
+ def stream_file(audio_file, format):
+ audio = AudioSegment.from_file(audio_file)
+ i = 0
+ chunk_size = 1000
+ while chunk_size * i < len(audio):
+ chunk = audio[chunk_size * i : chunk_size * (i + 1)]
+ i += 1
+ if chunk:
+ file = f"/tmp/{i}.{format}"
+ chunk.export(file, format=format)
+ yield file
+ sleep(0.5)
+
+ stream_as_file_btn.click(
+ stream_file, [input_audio, format], stream_as_file_output
+ )
+
+ gr.Examples(
+ [["audio/cantina.wav", "wav"], ["audio/cantina.wav", "mp3"]],
+ [input_audio, format],
+ fn=stream_file,
+ outputs=stream_as_file_output,
+ cache_examples=True,
+ )
+
+ with gr.Column():
+ stream_as_bytes_btn = gr.Button("Stream as Bytes")
+ stream_as_bytes_output = gr.Audio(format="bytes", streaming=True)
+
+ def stream_bytes(audio_file):
+ chunk_size = 20_000
+ with open(audio_file, "rb") as f:
+ while True:
+ chunk = f.read(chunk_size)
+ if chunk:
+ yield chunk
+ sleep(1)
+ else:
+ break
+ stream_as_bytes_btn.click(stream_bytes, input_audio, stream_as_bytes_output)
+
+if __name__ == "__main__":
+ demo.queue().launch()
diff --git a/demo/stream_frames/run.ipynb b/demo/stream_frames/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9543887421138fcdd81040fe581d38e582c1edee
--- /dev/null
+++ b/demo/stream_frames/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stream_frames"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "\n", "def flip(im):\n", " return np.flipud(im)\n", "\n", "demo = gr.Interface(\n", " flip, \n", " gr.Image(sources=[\"webcam\"], streaming=True), \n", " \"image\",\n", " live=True\n", ")\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", " "]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stream_frames/run.py b/demo/stream_frames/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..547fc11eec2f626fd4aa0baa13189abdd951d5cc
--- /dev/null
+++ b/demo/stream_frames/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+import numpy as np
+
+def flip(im):
+ return np.flipud(im)
+
+demo = gr.Interface(
+ flip,
+ gr.Image(sources=["webcam"], streaming=True),
+ "image",
+ live=True
+)
+if __name__ == "__main__":
+ demo.launch()
+
\ No newline at end of file
diff --git a/demo/streaming_wav2vec/requirements.txt b/demo/streaming_wav2vec/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4f492ddc93de3952474c43b325c02b1b0fcdec9c
--- /dev/null
+++ b/demo/streaming_wav2vec/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
diff --git a/demo/streaming_wav2vec/run.ipynb b/demo/streaming_wav2vec/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5c5d89dfef5a21eef24a46012d4aab386e1f168d
--- /dev/null
+++ b/demo/streaming_wav2vec/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: streaming_wav2vec"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from transformers import pipeline\n", "import gradio as gr\n", "import time\n", "\n", "p = pipeline(\"automatic-speech-recognition\")\n", "\n", "def transcribe(audio, state=\"\"):\n", " time.sleep(2)\n", " text = p(audio)[\"text\"]\n", " state += text + \" \"\n", " return state, state\n", "\n", "demo = gr.Interface(\n", " fn=transcribe, \n", " inputs=[\n", " gr.Audio(sources=[\"microphone\"], type=\"filepath\", streaming=True), \n", " \"state\"\n", " ],\n", " outputs=[\n", " \"textbox\",\n", " \"state\"\n", " ],\n", " live=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/streaming_wav2vec/run.py b/demo/streaming_wav2vec/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f335069998622a2accfb9867c53cde9d20da8412
--- /dev/null
+++ b/demo/streaming_wav2vec/run.py
@@ -0,0 +1,27 @@
+from transformers import pipeline
+import gradio as gr
+import time
+
+p = pipeline("automatic-speech-recognition")
+
+def transcribe(audio, state=""):
+ time.sleep(2)
+ text = p(audio)["text"]
+ state += text + " "
+ return state, state
+
+demo = gr.Interface(
+ fn=transcribe,
+ inputs=[
+ gr.Audio(sources=["microphone"], type="filepath", streaming=True),
+ "state"
+ ],
+ outputs=[
+ "textbox",
+ "state"
+ ],
+ live=True
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/stt_or_tts/run.ipynb b/demo/stt_or_tts/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5a5c0a382076aa799d5aed9932ee9244b648d950
--- /dev/null
+++ b/demo/stt_or_tts/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: stt_or_tts"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "tts_examples = [\n", " \"I love learning machine learning\",\n", " \"How do you do?\",\n", "]\n", "\n", "tts_demo = gr.load(\n", " \"huggingface/facebook/fastspeech2-en-ljspeech\",\n", " title=None,\n", " examples=tts_examples,\n", " description=\"Give me something to say!\",\n", " cache_examples=False\n", ")\n", "\n", "stt_demo = gr.load(\n", " \"huggingface/facebook/wav2vec2-base-960h\",\n", " title=None,\n", " inputs=\"mic\",\n", " description=\"Let me try to guess what you're saying!\",\n", ")\n", "\n", "demo = gr.TabbedInterface([tts_demo, stt_demo], [\"Text-to-speech\", \"Speech-to-text\"])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/stt_or_tts/run.py b/demo/stt_or_tts/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..98c97dd376115171a085b1e9cf570026551abf5a
--- /dev/null
+++ b/demo/stt_or_tts/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+
+tts_examples = [
+ "I love learning machine learning",
+ "How do you do?",
+]
+
+tts_demo = gr.load(
+ "huggingface/facebook/fastspeech2-en-ljspeech",
+ title=None,
+ examples=tts_examples,
+ description="Give me something to say!",
+ cache_examples=False
+)
+
+stt_demo = gr.load(
+ "huggingface/facebook/wav2vec2-base-960h",
+ title=None,
+ inputs="mic",
+ description="Let me try to guess what you're saying!",
+)
+
+demo = gr.TabbedInterface([tts_demo, stt_demo], ["Text-to-speech", "Speech-to-text"])
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/tabbed_interface_lite/run.ipynb b/demo/tabbed_interface_lite/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..4f3b3faa767d6ab329777e0b0e93088f21cba3db
--- /dev/null
+++ b/demo/tabbed_interface_lite/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tabbed_interface_lite"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "hello_world = gr.Interface(lambda name: \"Hello \" + name, \"text\", \"text\")\n", "bye_world = gr.Interface(lambda name: \"Bye \" + name, \"text\", \"text\")\n", "\n", "demo = gr.TabbedInterface([hello_world, bye_world], [\"Hello World\", \"Bye World\"])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/tabbed_interface_lite/run.py b/demo/tabbed_interface_lite/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e804c927cd334d4946f24d164838da64192d59e
--- /dev/null
+++ b/demo/tabbed_interface_lite/run.py
@@ -0,0 +1,9 @@
+import gradio as gr
+
+hello_world = gr.Interface(lambda name: "Hello " + name, "text", "text")
+bye_world = gr.Interface(lambda name: "Bye " + name, "text", "text")
+
+demo = gr.TabbedInterface([hello_world, bye_world], ["Hello World", "Bye World"])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/tax_calculator/DESCRIPTION.md b/demo/tax_calculator/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..9ed8163846588560534af4fdc9f50738f3b7e0c5
--- /dev/null
+++ b/demo/tax_calculator/DESCRIPTION.md
@@ -0,0 +1 @@
+Calculate taxes using Textbox, Radio, and Dataframe components
\ No newline at end of file
diff --git a/demo/tax_calculator/run.ipynb b/demo/tax_calculator/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a531071b1b664ce6b7594fbf7c79172279b53b9d
--- /dev/null
+++ b/demo/tax_calculator/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tax_calculator\n", "### Calculate taxes using Textbox, Radio, and Dataframe components\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def tax_calculator(income, marital_status, assets):\n", " tax_brackets = [(10, 0), (25, 8), (60, 12), (120, 20), (250, 30)]\n", " total_deductible = sum(assets[\"Cost\"])\n", " taxable_income = income - total_deductible\n", "\n", " total_tax = 0\n", " for bracket, rate in tax_brackets:\n", " if taxable_income > bracket:\n", " total_tax += (taxable_income - bracket) * rate / 100\n", "\n", " if marital_status == \"Married\":\n", " total_tax *= 0.75\n", " elif marital_status == \"Divorced\":\n", " total_tax *= 0.8\n", "\n", " return round(total_tax)\n", "\n", "demo = gr.Interface(\n", " tax_calculator,\n", " [\n", " \"number\",\n", " gr.Radio([\"Single\", \"Married\", \"Divorced\"]),\n", " gr.Dataframe(\n", " headers=[\"Item\", \"Cost\"],\n", " datatype=[\"str\", \"number\"],\n", " label=\"Assets Purchased this Year\",\n", " ),\n", " ],\n", " \"number\",\n", " examples=[\n", " [10000, \"Married\", [[\"Suit\", 5000], [\"Laptop\", 800], [\"Car\", 1800]]],\n", " [80000, \"Single\", [[\"Suit\", 800], [\"Watch\", 1800], [\"Car\", 800]]],\n", " ],\n", ")\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/tax_calculator/run.py b/demo/tax_calculator/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..622ef244c6a951fdcf82efc99d88b5a326b2225a
--- /dev/null
+++ b/demo/tax_calculator/run.py
@@ -0,0 +1,38 @@
+import gradio as gr
+
+def tax_calculator(income, marital_status, assets):
+ tax_brackets = [(10, 0), (25, 8), (60, 12), (120, 20), (250, 30)]
+ total_deductible = sum(assets["Cost"])
+ taxable_income = income - total_deductible
+
+ total_tax = 0
+ for bracket, rate in tax_brackets:
+ if taxable_income > bracket:
+ total_tax += (taxable_income - bracket) * rate / 100
+
+ if marital_status == "Married":
+ total_tax *= 0.75
+ elif marital_status == "Divorced":
+ total_tax *= 0.8
+
+ return round(total_tax)
+
+demo = gr.Interface(
+ tax_calculator,
+ [
+ "number",
+ gr.Radio(["Single", "Married", "Divorced"]),
+ gr.Dataframe(
+ headers=["Item", "Cost"],
+ datatype=["str", "number"],
+ label="Assets Purchased this Year",
+ ),
+ ],
+ "number",
+ examples=[
+ [10000, "Married", [["Suit", 5000], ["Laptop", 800], ["Car", 1800]]],
+ [80000, "Single", [["Suit", 800], ["Watch", 1800], ["Car", 800]]],
+ ],
+)
+
+demo.launch()
diff --git a/demo/text_analysis/DESCRIPTION.md b/demo/text_analysis/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..dddeb4380f6b229af46b702093c00b4b946cc1f3
--- /dev/null
+++ b/demo/text_analysis/DESCRIPTION.md
@@ -0,0 +1 @@
+This simple demo takes advantage of Gradio's HighlightedText, JSON and HTML outputs to create a clear NER segmentation.
\ No newline at end of file
diff --git a/demo/text_analysis/requirements.txt b/demo/text_analysis/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..33ea94c42fe4087ae42c8b2bf66509e23a68e834
--- /dev/null
+++ b/demo/text_analysis/requirements.txt
@@ -0,0 +1 @@
+spacy
\ No newline at end of file
diff --git a/demo/text_analysis/run.ipynb b/demo/text_analysis/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b95ad000185ad4785a34c99a3609ab57ad41e839
--- /dev/null
+++ b/demo/text_analysis/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: text_analysis\n", "### This simple demo takes advantage of Gradio's HighlightedText, JSON and HTML outputs to create a clear NER segmentation.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio spacy"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "os.system('python -m spacy download en_core_web_sm')\n", "import spacy\n", "from spacy import displacy\n", "\n", "nlp = spacy.load(\"en_core_web_sm\")\n", "\n", "def text_analysis(text):\n", " doc = nlp(text)\n", " html = displacy.render(doc, style=\"dep\", page=True)\n", " html = (\n", " \"
\"\n", " + html\n", " + \"
\"\n", " )\n", " pos_count = {\n", " \"char_count\": len(text),\n", " \"token_count\": 0,\n", " }\n", " pos_tokens = []\n", "\n", " for token in doc:\n", " pos_tokens.extend([(token.text, token.pos_), (\" \", None)])\n", "\n", " return pos_tokens, pos_count, html\n", "\n", "demo = gr.Interface(\n", " text_analysis,\n", " gr.Textbox(placeholder=\"Enter sentence here...\"),\n", " [\"highlight\", \"json\", \"html\"],\n", " examples=[\n", " [\"What a beautiful morning for a walk!\"],\n", " [\"It was the best of times, it was the worst of times.\"],\n", " ],\n", ")\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/text_analysis/run.py b/demo/text_analysis/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..30f18c79624b5695a705196cc313aaa3a2999699
--- /dev/null
+++ b/demo/text_analysis/run.py
@@ -0,0 +1,38 @@
+import gradio as gr
+import os
+os.system('python -m spacy download en_core_web_sm')
+import spacy
+from spacy import displacy
+
+nlp = spacy.load("en_core_web_sm")
+
+def text_analysis(text):
+ doc = nlp(text)
+ html = displacy.render(doc, style="dep", page=True)
+ html = (
+ "
"
+ + html
+ + "
"
+ )
+ pos_count = {
+ "char_count": len(text),
+ "token_count": 0,
+ }
+ pos_tokens = []
+
+ for token in doc:
+ pos_tokens.extend([(token.text, token.pos_), (" ", None)])
+
+ return pos_tokens, pos_count, html
+
+demo = gr.Interface(
+ text_analysis,
+ gr.Textbox(placeholder="Enter sentence here..."),
+ ["highlight", "json", "html"],
+ examples=[
+ ["What a beautiful morning for a walk!"],
+ ["It was the best of times, it was the worst of times."],
+ ],
+)
+
+demo.launch()
diff --git a/demo/text_analysis/screenshot.png b/demo/text_analysis/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..95d4756abda43f86a38bc5d7f5b5dbb6b7ef98be
Binary files /dev/null and b/demo/text_analysis/screenshot.png differ
diff --git a/demo/text_analysis/setup.sh b/demo/text_analysis/setup.sh
new file mode 100644
index 0000000000000000000000000000000000000000..ad8bb8ee847c128cbc233e57fa8f1b0d62c84d4e
--- /dev/null
+++ b/demo/text_analysis/setup.sh
@@ -0,0 +1 @@
+python -m spacy download en_core_web_sm
\ No newline at end of file
diff --git a/demo/text_generation/DESCRIPTION.md b/demo/text_generation/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..5b9716ddf8174a1002511bca9d854d095a895021
--- /dev/null
+++ b/demo/text_generation/DESCRIPTION.md
@@ -0,0 +1 @@
+This text generation demo takes in input text and returns generated text. It uses the Transformers library to set up the model and has two examples.
\ No newline at end of file
diff --git a/demo/text_generation/requirements.txt b/demo/text_generation/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..05ec8d9af8f237f0cfbefc987a2dfbbd8444a16a
--- /dev/null
+++ b/demo/text_generation/requirements.txt
@@ -0,0 +1,3 @@
+git+https://github.com/huggingface/transformers
+gradio
+torch
\ No newline at end of file
diff --git a/demo/text_generation/run.ipynb b/demo/text_generation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f73a87e97640441f4780db1a2e0a03fc0b039f52
--- /dev/null
+++ b/demo/text_generation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: text_generation\n", "### This text generation demo takes in input text and returns generated text. It uses the Transformers library to set up the model and has two examples.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio git+https://github.com/huggingface/transformers gradio torch"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import pipeline\n", "\n", "generator = pipeline('text-generation', model='gpt2')\n", "\n", "def generate(text):\n", " result = generator(text, max_length=30, num_return_sequences=1)\n", " return result[0][\"generated_text\"]\n", "\n", "examples = [\n", " [\"The Moon's orbit around Earth has\"],\n", " [\"The smooth Borealis basin in the Northern Hemisphere covers 40%\"],\n", "]\n", "\n", "demo = gr.Interface(\n", " fn=generate,\n", " inputs=gr.Textbox(lines=5, label=\"Input Text\"),\n", " outputs=gr.Textbox(label=\"Generated Text\"),\n", " examples=examples\n", ")\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/text_generation/run.py b/demo/text_generation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c78d089f90e252f2bbda7b75509d2b4d8b4a809e
--- /dev/null
+++ b/demo/text_generation/run.py
@@ -0,0 +1,22 @@
+import gradio as gr
+from transformers import pipeline
+
+generator = pipeline('text-generation', model='gpt2')
+
+def generate(text):
+ result = generator(text, max_length=30, num_return_sequences=1)
+ return result[0]["generated_text"]
+
+examples = [
+ ["The Moon's orbit around Earth has"],
+ ["The smooth Borealis basin in the Northern Hemisphere covers 40%"],
+]
+
+demo = gr.Interface(
+ fn=generate,
+ inputs=gr.Textbox(lines=5, label="Input Text"),
+ outputs=gr.Textbox(label="Generated Text"),
+ examples=examples
+)
+
+demo.launch()
diff --git a/demo/textbox_component/run.ipynb b/demo/textbox_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..94f2ac6b69222bd4b29a0fd237b70c7a7eaff0f6
--- /dev/null
+++ b/demo/textbox_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: textbox_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.Textbox()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/textbox_component/run.py b/demo/textbox_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..14c513b3f1b7ce4fc289a7e570fd274edbd8ccdf
--- /dev/null
+++ b/demo/textbox_component/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Textbox()
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/theme_builder/run.ipynb b/demo/theme_builder/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..568820d9dcf11d85ed597a7c7d686e0e0ac7d7c3
--- /dev/null
+++ b/demo/theme_builder/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_builder"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "demo = gr.themes.builder\n", "\n", "if __name__ == \"__main__\":\n", " demo()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_builder/run.py b/demo/theme_builder/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d089dbf28154b49b3c02ce781294542015c31e4
--- /dev/null
+++ b/demo/theme_builder/run.py
@@ -0,0 +1,6 @@
+import gradio as gr
+
+demo = gr.themes.builder
+
+if __name__ == "__main__":
+ demo()
\ No newline at end of file
diff --git a/demo/theme_extended_step_1/run.ipynb b/demo/theme_extended_step_1/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..efb81c6c98affb71b36ff7973487e0e480d37869
--- /dev/null
+++ b/demo/theme_extended_step_1/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_extended_step_1"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "with gr.Blocks(theme=gr.themes.Default(primary_hue=\"red\", secondary_hue=\"pink\")) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", " \n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_extended_step_1/run.py b/demo/theme_extended_step_1/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..89d68e0bc1ce40a8cfa5904989a5dbb4b5fd5c2a
--- /dev/null
+++ b/demo/theme_extended_step_1/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+import time
+
+with gr.Blocks(theme=gr.themes.Default(primary_hue="red", secondary_hue="pink")) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/theme_extended_step_2/run.ipynb b/demo/theme_extended_step_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..670f0746a218c1476bba3eaa9590ae27fe80c475
--- /dev/null
+++ b/demo/theme_extended_step_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_extended_step_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "with gr.Blocks(theme=gr.themes.Default(spacing_size=\"sm\", radius_size=\"none\")) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", " \n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_extended_step_2/run.py b/demo/theme_extended_step_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..bee768324055bc2965a0de1647cd424656de4695
--- /dev/null
+++ b/demo/theme_extended_step_2/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+import time
+
+with gr.Blocks(theme=gr.themes.Default(spacing_size="sm", radius_size="none")) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/theme_extended_step_3/run.ipynb b/demo/theme_extended_step_3/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7c7bcf0136c618c87334105a1aff6ab492b57455
--- /dev/null
+++ b/demo/theme_extended_step_3/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_extended_step_3"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "with gr.Blocks(\n", " theme=gr.themes.Default(\n", " font=[gr.themes.GoogleFont(\"Inconsolata\"), \"Arial\", \"sans-serif\"]\n", " )\n", ") as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", "\n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_extended_step_3/run.py b/demo/theme_extended_step_3/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d808c033976edecdded424c69af76050b73256dd
--- /dev/null
+++ b/demo/theme_extended_step_3/run.py
@@ -0,0 +1,23 @@
+import gradio as gr
+import time
+
+with gr.Blocks(
+ theme=gr.themes.Default(
+ font=[gr.themes.GoogleFont("Inconsolata"), "Arial", "sans-serif"]
+ )
+) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/theme_extended_step_4/run.ipynb b/demo/theme_extended_step_4/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9ec1ce46b00f1167dee1b59bc063f208d30732bb
--- /dev/null
+++ b/demo/theme_extended_step_4/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_extended_step_4"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "theme = gr.themes.Default(primary_hue=\"blue\").set(\n", " loader_color=\"#FF0000\",\n", " slider_color=\"#FF0000\",\n", ")\n", "\n", "with gr.Blocks(\n", " theme=theme\n", ") as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", "\n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_extended_step_4/run.py b/demo/theme_extended_step_4/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a199dd653db092db9ff4c1a4d5aa6cd206fcd13
--- /dev/null
+++ b/demo/theme_extended_step_4/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+import time
+
+theme = gr.themes.Default(primary_hue="blue").set(
+ loader_color="#FF0000",
+ slider_color="#FF0000",
+)
+
+with gr.Blocks(
+ theme=theme
+) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/theme_new_step_1/run.ipynb b/demo/theme_new_step_1/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..afea6a7d651cb8317a895205492907d8a4db49da
--- /dev/null
+++ b/demo/theme_new_step_1/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_new_step_1"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from gradio.themes.base import Base\n", "import time\n", "\n", "class Seafoam(Base):\n", " pass\n", "\n", "seafoam = Seafoam()\n", "\n", "with gr.Blocks(theme=seafoam) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", " \n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_new_step_1/run.py b/demo/theme_new_step_1/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..a77a6e339aec8bdbb5490082309b71938a6ce2a5
--- /dev/null
+++ b/demo/theme_new_step_1/run.py
@@ -0,0 +1,25 @@
+import gradio as gr
+from gradio.themes.base import Base
+import time
+
+class Seafoam(Base):
+ pass
+
+seafoam = Seafoam()
+
+with gr.Blocks(theme=seafoam) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/theme_new_step_2/run.ipynb b/demo/theme_new_step_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..968d9294fbe8e0890baf8efc3a100c094ab7ed8f
--- /dev/null
+++ b/demo/theme_new_step_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_new_step_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from __future__ import annotations\n", "from typing import Iterable\n", "import gradio as gr\n", "from gradio.themes.base import Base\n", "from gradio.themes.utils import colors, fonts, sizes\n", "import time\n", "\n", "\n", "class Seafoam(Base):\n", " def __init__(\n", " self,\n", " *,\n", " primary_hue: colors.Color | str = colors.emerald,\n", " secondary_hue: colors.Color | str = colors.blue,\n", " neutral_hue: colors.Color | str = colors.gray,\n", " spacing_size: sizes.Size | str = sizes.spacing_md,\n", " radius_size: sizes.Size | str = sizes.radius_md,\n", " text_size: sizes.Size | str = sizes.text_lg,\n", " font: fonts.Font\n", " | str\n", " | Iterable[fonts.Font | str] = (\n", " fonts.GoogleFont(\"Quicksand\"),\n", " \"ui-sans-serif\",\n", " \"sans-serif\",\n", " ),\n", " font_mono: fonts.Font\n", " | str\n", " | Iterable[fonts.Font | str] = (\n", " fonts.GoogleFont(\"IBM Plex Mono\"),\n", " \"ui-monospace\",\n", " \"monospace\",\n", " ),\n", " ):\n", " super().__init__(\n", " primary_hue=primary_hue,\n", " secondary_hue=secondary_hue,\n", " neutral_hue=neutral_hue,\n", " spacing_size=spacing_size,\n", " radius_size=radius_size,\n", " text_size=text_size,\n", " font=font,\n", " font_mono=font_mono,\n", " )\n", "\n", "\n", "seafoam = Seafoam()\n", "\n", "with gr.Blocks(theme=seafoam) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", "\n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_new_step_2/run.py b/demo/theme_new_step_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..bdb38984082e8ffffeaf3c682e53ec7fd9ac3f3c
--- /dev/null
+++ b/demo/theme_new_step_2/run.py
@@ -0,0 +1,63 @@
+from __future__ import annotations
+from typing import Iterable
+import gradio as gr
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+import time
+
+
+class Seafoam(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.emerald,
+ secondary_hue: colors.Color | str = colors.blue,
+ neutral_hue: colors.Color | str = colors.gray,
+ spacing_size: sizes.Size | str = sizes.spacing_md,
+ radius_size: sizes.Size | str = sizes.radius_md,
+ text_size: sizes.Size | str = sizes.text_lg,
+ font: fonts.Font
+ | str
+ | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Quicksand"),
+ "ui-sans-serif",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font
+ | str
+ | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+
+
+seafoam = Seafoam()
+
+with gr.Blocks(theme=seafoam) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/theme_new_step_3/run.ipynb b/demo/theme_new_step_3/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..35d4b07f529c30d4b84a9503af9bd374c528333b
--- /dev/null
+++ b/demo/theme_new_step_3/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_new_step_3"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from __future__ import annotations\n", "from typing import Iterable\n", "import gradio as gr\n", "from gradio.themes.base import Base\n", "from gradio.themes.utils import colors, fonts, sizes\n", "import time\n", "\n", "\n", "class Seafoam(Base):\n", " def __init__(\n", " self,\n", " *,\n", " primary_hue: colors.Color | str = colors.emerald,\n", " secondary_hue: colors.Color | str = colors.blue,\n", " neutral_hue: colors.Color | str = colors.blue,\n", " spacing_size: sizes.Size | str = sizes.spacing_md,\n", " radius_size: sizes.Size | str = sizes.radius_md,\n", " text_size: sizes.Size | str = sizes.text_lg,\n", " font: fonts.Font\n", " | str\n", " | Iterable[fonts.Font | str] = (\n", " fonts.GoogleFont(\"Quicksand\"),\n", " \"ui-sans-serif\",\n", " \"sans-serif\",\n", " ),\n", " font_mono: fonts.Font\n", " | str\n", " | Iterable[fonts.Font | str] = (\n", " fonts.GoogleFont(\"IBM Plex Mono\"),\n", " \"ui-monospace\",\n", " \"monospace\",\n", " ),\n", " ):\n", " super().__init__(\n", " primary_hue=primary_hue,\n", " secondary_hue=secondary_hue,\n", " neutral_hue=neutral_hue,\n", " spacing_size=spacing_size,\n", " radius_size=radius_size,\n", " text_size=text_size,\n", " font=font,\n", " font_mono=font_mono,\n", " )\n", " super().set(\n", " body_background_fill=\"repeating-linear-gradient(45deg, *primary_200, *primary_200 10px, *primary_50 10px, *primary_50 20px)\",\n", " body_background_fill_dark=\"repeating-linear-gradient(45deg, *primary_800, *primary_800 10px, *primary_900 10px, *primary_900 20px)\",\n", " button_primary_background_fill=\"linear-gradient(90deg, *primary_300, *secondary_400)\",\n", " button_primary_background_fill_hover=\"linear-gradient(90deg, *primary_200, *secondary_300)\",\n", " button_primary_text_color=\"white\",\n", " button_primary_background_fill_dark=\"linear-gradient(90deg, *primary_600, *secondary_800)\",\n", " slider_color=\"*secondary_300\",\n", " slider_color_dark=\"*secondary_600\",\n", " block_title_text_weight=\"600\",\n", " block_border_width=\"3px\",\n", " block_shadow=\"*shadow_drop_lg\",\n", " button_shadow=\"*shadow_drop_lg\",\n", " button_large_padding=\"32px\",\n", " )\n", "\n", "\n", "seafoam = Seafoam()\n", "\n", "with gr.Blocks(theme=seafoam) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", "\n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_new_step_3/run.py b/demo/theme_new_step_3/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..e530196557b4954ee5ef0580a5d0a58e575ebd89
--- /dev/null
+++ b/demo/theme_new_step_3/run.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+from typing import Iterable
+import gradio as gr
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+import time
+
+
+class Seafoam(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.emerald,
+ secondary_hue: colors.Color | str = colors.blue,
+ neutral_hue: colors.Color | str = colors.blue,
+ spacing_size: sizes.Size | str = sizes.spacing_md,
+ radius_size: sizes.Size | str = sizes.radius_md,
+ text_size: sizes.Size | str = sizes.text_lg,
+ font: fonts.Font
+ | str
+ | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Quicksand"),
+ "ui-sans-serif",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font
+ | str
+ | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+ super().set(
+ body_background_fill="repeating-linear-gradient(45deg, *primary_200, *primary_200 10px, *primary_50 10px, *primary_50 20px)",
+ body_background_fill_dark="repeating-linear-gradient(45deg, *primary_800, *primary_800 10px, *primary_900 10px, *primary_900 20px)",
+ button_primary_background_fill="linear-gradient(90deg, *primary_300, *secondary_400)",
+ button_primary_background_fill_hover="linear-gradient(90deg, *primary_200, *secondary_300)",
+ button_primary_text_color="white",
+ button_primary_background_fill_dark="linear-gradient(90deg, *primary_600, *secondary_800)",
+ slider_color="*secondary_300",
+ slider_color_dark="*secondary_600",
+ block_title_text_weight="600",
+ block_border_width="3px",
+ block_shadow="*shadow_drop_lg",
+ button_shadow="*shadow_drop_lg",
+ button_large_padding="32px",
+ )
+
+
+seafoam = Seafoam()
+
+with gr.Blocks(theme=seafoam) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/theme_soft/run.ipynb b/demo/theme_soft/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..836f7cc595bc15db8b78907e8e69f9ced1649b23
--- /dev/null
+++ b/demo/theme_soft/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: theme_soft"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import time\n", "\n", "with gr.Blocks(theme=gr.themes.Soft()) as demo:\n", " textbox = gr.Textbox(label=\"Name\")\n", " slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n", " with gr.Row():\n", " button = gr.Button(\"Submit\", variant=\"primary\")\n", " clear = gr.Button(\"Clear\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " def repeat(name, count):\n", " time.sleep(3)\n", " return name * count\n", " \n", " button.click(repeat, [textbox, slider], output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/theme_soft/run.py b/demo/theme_soft/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ca9b9b6a664eee1a94c0059752ea2e7b284339e
--- /dev/null
+++ b/demo/theme_soft/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+import time
+
+with gr.Blocks(theme=gr.themes.Soft()) as demo:
+ textbox = gr.Textbox(label="Name")
+ slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
+ with gr.Row():
+ button = gr.Button("Submit", variant="primary")
+ clear = gr.Button("Clear")
+ output = gr.Textbox(label="Output")
+
+ def repeat(name, count):
+ time.sleep(3)
+ return name * count
+
+ button.click(repeat, [textbox, slider], output)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/tictactoe/run.ipynb b/demo/tictactoe/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e220923ffdb049e86884093585357177f30469e1
--- /dev/null
+++ b/demo/tictactoe/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tictactoe"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " turn = gr.Textbox(\"X\", interactive=False, label=\"Turn\")\n", " board = gr.Dataframe(value=[[\"\", \"\", \"\"]] * 3, interactive=False, type=\"array\")\n", "\n", " def place(board, turn, evt: gr.SelectData):\n", " if evt.value:\n", " return board, turn\n", " board[evt.index[0]][evt.index[1]] = turn\n", " turn = \"O\" if turn == \"X\" else \"X\"\n", " return board, turn\n", "\n", " board.select(place, [board, turn], [board, turn], show_progress=\"hidden\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/tictactoe/run.py b/demo/tictactoe/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..aae7280afb50c4bddbd505372647d72fa9f8b702
--- /dev/null
+++ b/demo/tictactoe/run.py
@@ -0,0 +1,17 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ turn = gr.Textbox("X", interactive=False, label="Turn")
+ board = gr.Dataframe(value=[["", "", ""]] * 3, interactive=False, type="array")
+
+ def place(board, turn, evt: gr.SelectData):
+ if evt.value:
+ return board, turn
+ board[evt.index[0]][evt.index[1]] = turn
+ turn = "O" if turn == "X" else "X"
+ return board, turn
+
+ board.select(place, [board, turn], [board, turn], show_progress="hidden")
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/timeseries-forecasting-with-prophet/DESCRIPTION.md b/demo/timeseries-forecasting-with-prophet/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..2914bc9f6a4b0bbffaeddf4f2e898abb20497447
--- /dev/null
+++ b/demo/timeseries-forecasting-with-prophet/DESCRIPTION.md
@@ -0,0 +1 @@
+A simple dashboard showing pypi stats for python libraries. Updates on load, and has no buttons!
\ No newline at end of file
diff --git a/demo/timeseries-forecasting-with-prophet/requirements.txt b/demo/timeseries-forecasting-with-prophet/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..22bb6574ca2759aa20e6248eda9498e22d6160eb
--- /dev/null
+++ b/demo/timeseries-forecasting-with-prophet/requirements.txt
@@ -0,0 +1,5 @@
+holidays==0.24
+prophet==1.1.2
+pandas
+pypistats
+plotly
\ No newline at end of file
diff --git a/demo/timeseries-forecasting-with-prophet/run.ipynb b/demo/timeseries-forecasting-with-prophet/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..38ed5d74e22f96ccf9b5a35440153c91238207fe
--- /dev/null
+++ b/demo/timeseries-forecasting-with-prophet/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: timeseries-forecasting-with-prophet\n", "### A simple dashboard showing pypi stats for python libraries. Updates on load, and has no buttons!\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio holidays==0.24 prophet==1.1.2 pandas pypistats plotly"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pypistats\n", "from datetime import date\n", "from dateutil.relativedelta import relativedelta\n", "import pandas as pd\n", "from prophet import Prophet\n", "pd.options.plotting.backend = \"plotly\"\n", "\n", "def get_forecast(lib, time):\n", "\n", " data = pypistats.overall(lib, total=True, format=\"pandas\")\n", " data = data.groupby(\"category\").get_group(\"with_mirrors\").sort_values(\"date\")\n", " start_date = date.today() - relativedelta(months=int(time.split(\" \")[0]))\n", " df = data[(data['date'] > str(start_date))] \n", "\n", " df1 = df[['date','downloads']]\n", " df1.columns = ['ds','y']\n", "\n", " m = Prophet()\n", " m.fit(df1)\n", " future = m.make_future_dataframe(periods=90)\n", " forecast = m.predict(future)\n", " fig1 = m.plot(forecast)\n", " return fig1 \n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " **Pypi Download Stats \ud83d\udcc8 with Prophet Forecasting**: see live download stats for popular open-source libraries \ud83e\udd17 along with a 3 month forecast using Prophet. The [ source code for this Gradio demo is here](https://huggingface.co/spaces/gradio/timeseries-forecasting-with-prophet/blob/main/app.py).\n", " \"\"\")\n", " with gr.Row():\n", " lib = gr.Dropdown([\"pandas\", \"scikit-learn\", \"torch\", \"prophet\"], label=\"Library\", value=\"pandas\")\n", " time = gr.Dropdown([\"3 months\", \"6 months\", \"9 months\", \"12 months\"], label=\"Downloads over the last...\", value=\"12 months\")\n", "\n", " plt = gr.Plot()\n", "\n", " lib.change(get_forecast, [lib, time], plt, queue=False)\n", " time.change(get_forecast, [lib, time], plt, queue=False) \n", " demo.load(get_forecast, [lib, time], plt, queue=False) \n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/timeseries-forecasting-with-prophet/run.py b/demo/timeseries-forecasting-with-prophet/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..373a6de4bf8fa877ea2c6d21184113daf0141ce5
--- /dev/null
+++ b/demo/timeseries-forecasting-with-prophet/run.py
@@ -0,0 +1,41 @@
+import gradio as gr
+import pypistats
+from datetime import date
+from dateutil.relativedelta import relativedelta
+import pandas as pd
+from prophet import Prophet
+pd.options.plotting.backend = "plotly"
+
+def get_forecast(lib, time):
+
+ data = pypistats.overall(lib, total=True, format="pandas")
+ data = data.groupby("category").get_group("with_mirrors").sort_values("date")
+ start_date = date.today() - relativedelta(months=int(time.split(" ")[0]))
+ df = data[(data['date'] > str(start_date))]
+
+ df1 = df[['date','downloads']]
+ df1.columns = ['ds','y']
+
+ m = Prophet()
+ m.fit(df1)
+ future = m.make_future_dataframe(periods=90)
+ forecast = m.predict(future)
+ fig1 = m.plot(forecast)
+ return fig1
+
+with gr.Blocks() as demo:
+ gr.Markdown(
+ """
+ **Pypi Download Stats 📈 with Prophet Forecasting**: see live download stats for popular open-source libraries 🤗 along with a 3 month forecast using Prophet. The [ source code for this Gradio demo is here](https://huggingface.co/spaces/gradio/timeseries-forecasting-with-prophet/blob/main/app.py).
+ """)
+ with gr.Row():
+ lib = gr.Dropdown(["pandas", "scikit-learn", "torch", "prophet"], label="Library", value="pandas")
+ time = gr.Dropdown(["3 months", "6 months", "9 months", "12 months"], label="Downloads over the last...", value="12 months")
+
+ plt = gr.Plot()
+
+ lib.change(get_forecast, [lib, time], plt, queue=False)
+ time.change(get_forecast, [lib, time], plt, queue=False)
+ demo.load(get_forecast, [lib, time], plt, queue=False)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/titanic_survival/files/titanic.csv b/demo/titanic_survival/files/titanic.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5cc466e97cf12f155d19b9f717425214075d0b7a
--- /dev/null
+++ b/demo/titanic_survival/files/titanic.csv
@@ -0,0 +1,892 @@
+PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
+1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
+2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
+3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
+4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
+5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
+6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
+7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
+8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
+9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
+10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
+11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
+12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
+13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
+14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S
+15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S
+16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S
+17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q
+18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S
+19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S
+20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C
+21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S
+22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S
+23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q
+24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S
+25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S
+26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S
+27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C
+28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S
+29,1,3,"O'Dwyer, Miss. Ellen ""Nellie""",female,,0,0,330959,7.8792,,Q
+30,0,3,"Todoroff, Mr. Lalio",male,,0,0,349216,7.8958,,S
+31,0,1,"Uruchurtu, Don. Manuel E",male,40,0,0,PC 17601,27.7208,,C
+32,1,1,"Spencer, Mrs. William Augustus (Marie Eugenie)",female,,1,0,PC 17569,146.5208,B78,C
+33,1,3,"Glynn, Miss. Mary Agatha",female,,0,0,335677,7.75,,Q
+34,0,2,"Wheadon, Mr. Edward H",male,66,0,0,C.A. 24579,10.5,,S
+35,0,1,"Meyer, Mr. Edgar Joseph",male,28,1,0,PC 17604,82.1708,,C
+36,0,1,"Holverson, Mr. Alexander Oskar",male,42,1,0,113789,52,,S
+37,1,3,"Mamee, Mr. Hanna",male,,0,0,2677,7.2292,,C
+38,0,3,"Cann, Mr. Ernest Charles",male,21,0,0,A./5. 2152,8.05,,S
+39,0,3,"Vander Planke, Miss. Augusta Maria",female,18,2,0,345764,18,,S
+40,1,3,"Nicola-Yarred, Miss. Jamila",female,14,1,0,2651,11.2417,,C
+41,0,3,"Ahlin, Mrs. Johan (Johanna Persdotter Larsson)",female,40,1,0,7546,9.475,,S
+42,0,2,"Turpin, Mrs. William John Robert (Dorothy Ann Wonnacott)",female,27,1,0,11668,21,,S
+43,0,3,"Kraeff, Mr. Theodor",male,,0,0,349253,7.8958,,C
+44,1,2,"Laroche, Miss. Simonne Marie Anne Andree",female,3,1,2,SC/Paris 2123,41.5792,,C
+45,1,3,"Devaney, Miss. Margaret Delia",female,19,0,0,330958,7.8792,,Q
+46,0,3,"Rogers, Mr. William John",male,,0,0,S.C./A.4. 23567,8.05,,S
+47,0,3,"Lennon, Mr. Denis",male,,1,0,370371,15.5,,Q
+48,1,3,"O'Driscoll, Miss. Bridget",female,,0,0,14311,7.75,,Q
+49,0,3,"Samaan, Mr. Youssef",male,,2,0,2662,21.6792,,C
+50,0,3,"Arnold-Franchi, Mrs. Josef (Josefine Franchi)",female,18,1,0,349237,17.8,,S
+51,0,3,"Panula, Master. Juha Niilo",male,7,4,1,3101295,39.6875,,S
+52,0,3,"Nosworthy, Mr. Richard Cater",male,21,0,0,A/4. 39886,7.8,,S
+53,1,1,"Harper, Mrs. Henry Sleeper (Myna Haxtun)",female,49,1,0,PC 17572,76.7292,D33,C
+54,1,2,"Faunthorpe, Mrs. Lizzie (Elizabeth Anne Wilkinson)",female,29,1,0,2926,26,,S
+55,0,1,"Ostby, Mr. Engelhart Cornelius",male,65,0,1,113509,61.9792,B30,C
+56,1,1,"Woolner, Mr. Hugh",male,,0,0,19947,35.5,C52,S
+57,1,2,"Rugg, Miss. Emily",female,21,0,0,C.A. 31026,10.5,,S
+58,0,3,"Novel, Mr. Mansouer",male,28.5,0,0,2697,7.2292,,C
+59,1,2,"West, Miss. Constance Mirium",female,5,1,2,C.A. 34651,27.75,,S
+60,0,3,"Goodwin, Master. William Frederick",male,11,5,2,CA 2144,46.9,,S
+61,0,3,"Sirayanian, Mr. Orsen",male,22,0,0,2669,7.2292,,C
+62,1,1,"Icard, Miss. Amelie",female,38,0,0,113572,80,B28,
+63,0,1,"Harris, Mr. Henry Birkhardt",male,45,1,0,36973,83.475,C83,S
+64,0,3,"Skoog, Master. Harald",male,4,3,2,347088,27.9,,S
+65,0,1,"Stewart, Mr. Albert A",male,,0,0,PC 17605,27.7208,,C
+66,1,3,"Moubarek, Master. Gerios",male,,1,1,2661,15.2458,,C
+67,1,2,"Nye, Mrs. (Elizabeth Ramell)",female,29,0,0,C.A. 29395,10.5,F33,S
+68,0,3,"Crease, Mr. Ernest James",male,19,0,0,S.P. 3464,8.1583,,S
+69,1,3,"Andersson, Miss. Erna Alexandra",female,17,4,2,3101281,7.925,,S
+70,0,3,"Kink, Mr. Vincenz",male,26,2,0,315151,8.6625,,S
+71,0,2,"Jenkin, Mr. Stephen Curnow",male,32,0,0,C.A. 33111,10.5,,S
+72,0,3,"Goodwin, Miss. Lillian Amy",female,16,5,2,CA 2144,46.9,,S
+73,0,2,"Hood, Mr. Ambrose Jr",male,21,0,0,S.O.C. 14879,73.5,,S
+74,0,3,"Chronopoulos, Mr. Apostolos",male,26,1,0,2680,14.4542,,C
+75,1,3,"Bing, Mr. Lee",male,32,0,0,1601,56.4958,,S
+76,0,3,"Moen, Mr. Sigurd Hansen",male,25,0,0,348123,7.65,F G73,S
+77,0,3,"Staneff, Mr. Ivan",male,,0,0,349208,7.8958,,S
+78,0,3,"Moutal, Mr. Rahamin Haim",male,,0,0,374746,8.05,,S
+79,1,2,"Caldwell, Master. Alden Gates",male,0.83,0,2,248738,29,,S
+80,1,3,"Dowdell, Miss. Elizabeth",female,30,0,0,364516,12.475,,S
+81,0,3,"Waelens, Mr. Achille",male,22,0,0,345767,9,,S
+82,1,3,"Sheerlinck, Mr. Jan Baptist",male,29,0,0,345779,9.5,,S
+83,1,3,"McDermott, Miss. Brigdet Delia",female,,0,0,330932,7.7875,,Q
+84,0,1,"Carrau, Mr. Francisco M",male,28,0,0,113059,47.1,,S
+85,1,2,"Ilett, Miss. Bertha",female,17,0,0,SO/C 14885,10.5,,S
+86,1,3,"Backstrom, Mrs. Karl Alfred (Maria Mathilda Gustafsson)",female,33,3,0,3101278,15.85,,S
+87,0,3,"Ford, Mr. William Neal",male,16,1,3,W./C. 6608,34.375,,S
+88,0,3,"Slocovski, Mr. Selman Francis",male,,0,0,SOTON/OQ 392086,8.05,,S
+89,1,1,"Fortune, Miss. Mabel Helen",female,23,3,2,19950,263,C23 C25 C27,S
+90,0,3,"Celotti, Mr. Francesco",male,24,0,0,343275,8.05,,S
+91,0,3,"Christmann, Mr. Emil",male,29,0,0,343276,8.05,,S
+92,0,3,"Andreasson, Mr. Paul Edvin",male,20,0,0,347466,7.8542,,S
+93,0,1,"Chaffee, Mr. Herbert Fuller",male,46,1,0,W.E.P. 5734,61.175,E31,S
+94,0,3,"Dean, Mr. Bertram Frank",male,26,1,2,C.A. 2315,20.575,,S
+95,0,3,"Coxon, Mr. Daniel",male,59,0,0,364500,7.25,,S
+96,0,3,"Shorney, Mr. Charles Joseph",male,,0,0,374910,8.05,,S
+97,0,1,"Goldschmidt, Mr. George B",male,71,0,0,PC 17754,34.6542,A5,C
+98,1,1,"Greenfield, Mr. William Bertram",male,23,0,1,PC 17759,63.3583,D10 D12,C
+99,1,2,"Doling, Mrs. John T (Ada Julia Bone)",female,34,0,1,231919,23,,S
+100,0,2,"Kantor, Mr. Sinai",male,34,1,0,244367,26,,S
+101,0,3,"Petranec, Miss. Matilda",female,28,0,0,349245,7.8958,,S
+102,0,3,"Petroff, Mr. Pastcho (""Pentcho"")",male,,0,0,349215,7.8958,,S
+103,0,1,"White, Mr. Richard Frasar",male,21,0,1,35281,77.2875,D26,S
+104,0,3,"Johansson, Mr. Gustaf Joel",male,33,0,0,7540,8.6542,,S
+105,0,3,"Gustafsson, Mr. Anders Vilhelm",male,37,2,0,3101276,7.925,,S
+106,0,3,"Mionoff, Mr. Stoytcho",male,28,0,0,349207,7.8958,,S
+107,1,3,"Salkjelsvik, Miss. Anna Kristine",female,21,0,0,343120,7.65,,S
+108,1,3,"Moss, Mr. Albert Johan",male,,0,0,312991,7.775,,S
+109,0,3,"Rekic, Mr. Tido",male,38,0,0,349249,7.8958,,S
+110,1,3,"Moran, Miss. Bertha",female,,1,0,371110,24.15,,Q
+111,0,1,"Porter, Mr. Walter Chamberlain",male,47,0,0,110465,52,C110,S
+112,0,3,"Zabour, Miss. Hileni",female,14.5,1,0,2665,14.4542,,C
+113,0,3,"Barton, Mr. David John",male,22,0,0,324669,8.05,,S
+114,0,3,"Jussila, Miss. Katriina",female,20,1,0,4136,9.825,,S
+115,0,3,"Attalah, Miss. Malake",female,17,0,0,2627,14.4583,,C
+116,0,3,"Pekoniemi, Mr. Edvard",male,21,0,0,STON/O 2. 3101294,7.925,,S
+117,0,3,"Connors, Mr. Patrick",male,70.5,0,0,370369,7.75,,Q
+118,0,2,"Turpin, Mr. William John Robert",male,29,1,0,11668,21,,S
+119,0,1,"Baxter, Mr. Quigg Edmond",male,24,0,1,PC 17558,247.5208,B58 B60,C
+120,0,3,"Andersson, Miss. Ellis Anna Maria",female,2,4,2,347082,31.275,,S
+121,0,2,"Hickman, Mr. Stanley George",male,21,2,0,S.O.C. 14879,73.5,,S
+122,0,3,"Moore, Mr. Leonard Charles",male,,0,0,A4. 54510,8.05,,S
+123,0,2,"Nasser, Mr. Nicholas",male,32.5,1,0,237736,30.0708,,C
+124,1,2,"Webber, Miss. Susan",female,32.5,0,0,27267,13,E101,S
+125,0,1,"White, Mr. Percival Wayland",male,54,0,1,35281,77.2875,D26,S
+126,1,3,"Nicola-Yarred, Master. Elias",male,12,1,0,2651,11.2417,,C
+127,0,3,"McMahon, Mr. Martin",male,,0,0,370372,7.75,,Q
+128,1,3,"Madsen, Mr. Fridtjof Arne",male,24,0,0,C 17369,7.1417,,S
+129,1,3,"Peter, Miss. Anna",female,,1,1,2668,22.3583,F E69,C
+130,0,3,"Ekstrom, Mr. Johan",male,45,0,0,347061,6.975,,S
+131,0,3,"Drazenoic, Mr. Jozef",male,33,0,0,349241,7.8958,,C
+132,0,3,"Coelho, Mr. Domingos Fernandeo",male,20,0,0,SOTON/O.Q. 3101307,7.05,,S
+133,0,3,"Robins, Mrs. Alexander A (Grace Charity Laury)",female,47,1,0,A/5. 3337,14.5,,S
+134,1,2,"Weisz, Mrs. Leopold (Mathilde Francoise Pede)",female,29,1,0,228414,26,,S
+135,0,2,"Sobey, Mr. Samuel James Hayden",male,25,0,0,C.A. 29178,13,,S
+136,0,2,"Richard, Mr. Emile",male,23,0,0,SC/PARIS 2133,15.0458,,C
+137,1,1,"Newsom, Miss. Helen Monypeny",female,19,0,2,11752,26.2833,D47,S
+138,0,1,"Futrelle, Mr. Jacques Heath",male,37,1,0,113803,53.1,C123,S
+139,0,3,"Osen, Mr. Olaf Elon",male,16,0,0,7534,9.2167,,S
+140,0,1,"Giglio, Mr. Victor",male,24,0,0,PC 17593,79.2,B86,C
+141,0,3,"Boulos, Mrs. Joseph (Sultana)",female,,0,2,2678,15.2458,,C
+142,1,3,"Nysten, Miss. Anna Sofia",female,22,0,0,347081,7.75,,S
+143,1,3,"Hakkarainen, Mrs. Pekka Pietari (Elin Matilda Dolck)",female,24,1,0,STON/O2. 3101279,15.85,,S
+144,0,3,"Burke, Mr. Jeremiah",male,19,0,0,365222,6.75,,Q
+145,0,2,"Andrew, Mr. Edgardo Samuel",male,18,0,0,231945,11.5,,S
+146,0,2,"Nicholls, Mr. Joseph Charles",male,19,1,1,C.A. 33112,36.75,,S
+147,1,3,"Andersson, Mr. August Edvard (""Wennerstrom"")",male,27,0,0,350043,7.7958,,S
+148,0,3,"Ford, Miss. Robina Maggie ""Ruby""",female,9,2,2,W./C. 6608,34.375,,S
+149,0,2,"Navratil, Mr. Michel (""Louis M Hoffman"")",male,36.5,0,2,230080,26,F2,S
+150,0,2,"Byles, Rev. Thomas Roussel Davids",male,42,0,0,244310,13,,S
+151,0,2,"Bateman, Rev. Robert James",male,51,0,0,S.O.P. 1166,12.525,,S
+152,1,1,"Pears, Mrs. Thomas (Edith Wearne)",female,22,1,0,113776,66.6,C2,S
+153,0,3,"Meo, Mr. Alfonzo",male,55.5,0,0,A.5. 11206,8.05,,S
+154,0,3,"van Billiard, Mr. Austin Blyler",male,40.5,0,2,A/5. 851,14.5,,S
+155,0,3,"Olsen, Mr. Ole Martin",male,,0,0,Fa 265302,7.3125,,S
+156,0,1,"Williams, Mr. Charles Duane",male,51,0,1,PC 17597,61.3792,,C
+157,1,3,"Gilnagh, Miss. Katherine ""Katie""",female,16,0,0,35851,7.7333,,Q
+158,0,3,"Corn, Mr. Harry",male,30,0,0,SOTON/OQ 392090,8.05,,S
+159,0,3,"Smiljanic, Mr. Mile",male,,0,0,315037,8.6625,,S
+160,0,3,"Sage, Master. Thomas Henry",male,,8,2,CA. 2343,69.55,,S
+161,0,3,"Cribb, Mr. John Hatfield",male,44,0,1,371362,16.1,,S
+162,1,2,"Watt, Mrs. James (Elizabeth ""Bessie"" Inglis Milne)",female,40,0,0,C.A. 33595,15.75,,S
+163,0,3,"Bengtsson, Mr. John Viktor",male,26,0,0,347068,7.775,,S
+164,0,3,"Calic, Mr. Jovo",male,17,0,0,315093,8.6625,,S
+165,0,3,"Panula, Master. Eino Viljami",male,1,4,1,3101295,39.6875,,S
+166,1,3,"Goldsmith, Master. Frank John William ""Frankie""",male,9,0,2,363291,20.525,,S
+167,1,1,"Chibnall, Mrs. (Edith Martha Bowerman)",female,,0,1,113505,55,E33,S
+168,0,3,"Skoog, Mrs. William (Anna Bernhardina Karlsson)",female,45,1,4,347088,27.9,,S
+169,0,1,"Baumann, Mr. John D",male,,0,0,PC 17318,25.925,,S
+170,0,3,"Ling, Mr. Lee",male,28,0,0,1601,56.4958,,S
+171,0,1,"Van der hoef, Mr. Wyckoff",male,61,0,0,111240,33.5,B19,S
+172,0,3,"Rice, Master. Arthur",male,4,4,1,382652,29.125,,Q
+173,1,3,"Johnson, Miss. Eleanor Ileen",female,1,1,1,347742,11.1333,,S
+174,0,3,"Sivola, Mr. Antti Wilhelm",male,21,0,0,STON/O 2. 3101280,7.925,,S
+175,0,1,"Smith, Mr. James Clinch",male,56,0,0,17764,30.6958,A7,C
+176,0,3,"Klasen, Mr. Klas Albin",male,18,1,1,350404,7.8542,,S
+177,0,3,"Lefebre, Master. Henry Forbes",male,,3,1,4133,25.4667,,S
+178,0,1,"Isham, Miss. Ann Elizabeth",female,50,0,0,PC 17595,28.7125,C49,C
+179,0,2,"Hale, Mr. Reginald",male,30,0,0,250653,13,,S
+180,0,3,"Leonard, Mr. Lionel",male,36,0,0,LINE,0,,S
+181,0,3,"Sage, Miss. Constance Gladys",female,,8,2,CA. 2343,69.55,,S
+182,0,2,"Pernot, Mr. Rene",male,,0,0,SC/PARIS 2131,15.05,,C
+183,0,3,"Asplund, Master. Clarence Gustaf Hugo",male,9,4,2,347077,31.3875,,S
+184,1,2,"Becker, Master. Richard F",male,1,2,1,230136,39,F4,S
+185,1,3,"Kink-Heilmann, Miss. Luise Gretchen",female,4,0,2,315153,22.025,,S
+186,0,1,"Rood, Mr. Hugh Roscoe",male,,0,0,113767,50,A32,S
+187,1,3,"O'Brien, Mrs. Thomas (Johanna ""Hannah"" Godfrey)",female,,1,0,370365,15.5,,Q
+188,1,1,"Romaine, Mr. Charles Hallace (""Mr C Rolmane"")",male,45,0,0,111428,26.55,,S
+189,0,3,"Bourke, Mr. John",male,40,1,1,364849,15.5,,Q
+190,0,3,"Turcin, Mr. Stjepan",male,36,0,0,349247,7.8958,,S
+191,1,2,"Pinsky, Mrs. (Rosa)",female,32,0,0,234604,13,,S
+192,0,2,"Carbines, Mr. William",male,19,0,0,28424,13,,S
+193,1,3,"Andersen-Jensen, Miss. Carla Christine Nielsine",female,19,1,0,350046,7.8542,,S
+194,1,2,"Navratil, Master. Michel M",male,3,1,1,230080,26,F2,S
+195,1,1,"Brown, Mrs. James Joseph (Margaret Tobin)",female,44,0,0,PC 17610,27.7208,B4,C
+196,1,1,"Lurette, Miss. Elise",female,58,0,0,PC 17569,146.5208,B80,C
+197,0,3,"Mernagh, Mr. Robert",male,,0,0,368703,7.75,,Q
+198,0,3,"Olsen, Mr. Karl Siegwart Andreas",male,42,0,1,4579,8.4042,,S
+199,1,3,"Madigan, Miss. Margaret ""Maggie""",female,,0,0,370370,7.75,,Q
+200,0,2,"Yrois, Miss. Henriette (""Mrs Harbeck"")",female,24,0,0,248747,13,,S
+201,0,3,"Vande Walle, Mr. Nestor Cyriel",male,28,0,0,345770,9.5,,S
+202,0,3,"Sage, Mr. Frederick",male,,8,2,CA. 2343,69.55,,S
+203,0,3,"Johanson, Mr. Jakob Alfred",male,34,0,0,3101264,6.4958,,S
+204,0,3,"Youseff, Mr. Gerious",male,45.5,0,0,2628,7.225,,C
+205,1,3,"Cohen, Mr. Gurshon ""Gus""",male,18,0,0,A/5 3540,8.05,,S
+206,0,3,"Strom, Miss. Telma Matilda",female,2,0,1,347054,10.4625,G6,S
+207,0,3,"Backstrom, Mr. Karl Alfred",male,32,1,0,3101278,15.85,,S
+208,1,3,"Albimona, Mr. Nassef Cassem",male,26,0,0,2699,18.7875,,C
+209,1,3,"Carr, Miss. Helen ""Ellen""",female,16,0,0,367231,7.75,,Q
+210,1,1,"Blank, Mr. Henry",male,40,0,0,112277,31,A31,C
+211,0,3,"Ali, Mr. Ahmed",male,24,0,0,SOTON/O.Q. 3101311,7.05,,S
+212,1,2,"Cameron, Miss. Clear Annie",female,35,0,0,F.C.C. 13528,21,,S
+213,0,3,"Perkin, Mr. John Henry",male,22,0,0,A/5 21174,7.25,,S
+214,0,2,"Givard, Mr. Hans Kristensen",male,30,0,0,250646,13,,S
+215,0,3,"Kiernan, Mr. Philip",male,,1,0,367229,7.75,,Q
+216,1,1,"Newell, Miss. Madeleine",female,31,1,0,35273,113.275,D36,C
+217,1,3,"Honkanen, Miss. Eliina",female,27,0,0,STON/O2. 3101283,7.925,,S
+218,0,2,"Jacobsohn, Mr. Sidney Samuel",male,42,1,0,243847,27,,S
+219,1,1,"Bazzani, Miss. Albina",female,32,0,0,11813,76.2917,D15,C
+220,0,2,"Harris, Mr. Walter",male,30,0,0,W/C 14208,10.5,,S
+221,1,3,"Sunderland, Mr. Victor Francis",male,16,0,0,SOTON/OQ 392089,8.05,,S
+222,0,2,"Bracken, Mr. James H",male,27,0,0,220367,13,,S
+223,0,3,"Green, Mr. George Henry",male,51,0,0,21440,8.05,,S
+224,0,3,"Nenkoff, Mr. Christo",male,,0,0,349234,7.8958,,S
+225,1,1,"Hoyt, Mr. Frederick Maxfield",male,38,1,0,19943,90,C93,S
+226,0,3,"Berglund, Mr. Karl Ivar Sven",male,22,0,0,PP 4348,9.35,,S
+227,1,2,"Mellors, Mr. William John",male,19,0,0,SW/PP 751,10.5,,S
+228,0,3,"Lovell, Mr. John Hall (""Henry"")",male,20.5,0,0,A/5 21173,7.25,,S
+229,0,2,"Fahlstrom, Mr. Arne Jonas",male,18,0,0,236171,13,,S
+230,0,3,"Lefebre, Miss. Mathilde",female,,3,1,4133,25.4667,,S
+231,1,1,"Harris, Mrs. Henry Birkhardt (Irene Wallach)",female,35,1,0,36973,83.475,C83,S
+232,0,3,"Larsson, Mr. Bengt Edvin",male,29,0,0,347067,7.775,,S
+233,0,2,"Sjostedt, Mr. Ernst Adolf",male,59,0,0,237442,13.5,,S
+234,1,3,"Asplund, Miss. Lillian Gertrud",female,5,4,2,347077,31.3875,,S
+235,0,2,"Leyson, Mr. Robert William Norman",male,24,0,0,C.A. 29566,10.5,,S
+236,0,3,"Harknett, Miss. Alice Phoebe",female,,0,0,W./C. 6609,7.55,,S
+237,0,2,"Hold, Mr. Stephen",male,44,1,0,26707,26,,S
+238,1,2,"Collyer, Miss. Marjorie ""Lottie""",female,8,0,2,C.A. 31921,26.25,,S
+239,0,2,"Pengelly, Mr. Frederick William",male,19,0,0,28665,10.5,,S
+240,0,2,"Hunt, Mr. George Henry",male,33,0,0,SCO/W 1585,12.275,,S
+241,0,3,"Zabour, Miss. Thamine",female,,1,0,2665,14.4542,,C
+242,1,3,"Murphy, Miss. Katherine ""Kate""",female,,1,0,367230,15.5,,Q
+243,0,2,"Coleridge, Mr. Reginald Charles",male,29,0,0,W./C. 14263,10.5,,S
+244,0,3,"Maenpaa, Mr. Matti Alexanteri",male,22,0,0,STON/O 2. 3101275,7.125,,S
+245,0,3,"Attalah, Mr. Sleiman",male,30,0,0,2694,7.225,,C
+246,0,1,"Minahan, Dr. William Edward",male,44,2,0,19928,90,C78,Q
+247,0,3,"Lindahl, Miss. Agda Thorilda Viktoria",female,25,0,0,347071,7.775,,S
+248,1,2,"Hamalainen, Mrs. William (Anna)",female,24,0,2,250649,14.5,,S
+249,1,1,"Beckwith, Mr. Richard Leonard",male,37,1,1,11751,52.5542,D35,S
+250,0,2,"Carter, Rev. Ernest Courtenay",male,54,1,0,244252,26,,S
+251,0,3,"Reed, Mr. James George",male,,0,0,362316,7.25,,S
+252,0,3,"Strom, Mrs. Wilhelm (Elna Matilda Persson)",female,29,1,1,347054,10.4625,G6,S
+253,0,1,"Stead, Mr. William Thomas",male,62,0,0,113514,26.55,C87,S
+254,0,3,"Lobb, Mr. William Arthur",male,30,1,0,A/5. 3336,16.1,,S
+255,0,3,"Rosblom, Mrs. Viktor (Helena Wilhelmina)",female,41,0,2,370129,20.2125,,S
+256,1,3,"Touma, Mrs. Darwis (Hanne Youssef Razi)",female,29,0,2,2650,15.2458,,C
+257,1,1,"Thorne, Mrs. Gertrude Maybelle",female,,0,0,PC 17585,79.2,,C
+258,1,1,"Cherry, Miss. Gladys",female,30,0,0,110152,86.5,B77,S
+259,1,1,"Ward, Miss. Anna",female,35,0,0,PC 17755,512.3292,,C
+260,1,2,"Parrish, Mrs. (Lutie Davis)",female,50,0,1,230433,26,,S
+261,0,3,"Smith, Mr. Thomas",male,,0,0,384461,7.75,,Q
+262,1,3,"Asplund, Master. Edvin Rojj Felix",male,3,4,2,347077,31.3875,,S
+263,0,1,"Taussig, Mr. Emil",male,52,1,1,110413,79.65,E67,S
+264,0,1,"Harrison, Mr. William",male,40,0,0,112059,0,B94,S
+265,0,3,"Henry, Miss. Delia",female,,0,0,382649,7.75,,Q
+266,0,2,"Reeves, Mr. David",male,36,0,0,C.A. 17248,10.5,,S
+267,0,3,"Panula, Mr. Ernesti Arvid",male,16,4,1,3101295,39.6875,,S
+268,1,3,"Persson, Mr. Ernst Ulrik",male,25,1,0,347083,7.775,,S
+269,1,1,"Graham, Mrs. William Thompson (Edith Junkins)",female,58,0,1,PC 17582,153.4625,C125,S
+270,1,1,"Bissette, Miss. Amelia",female,35,0,0,PC 17760,135.6333,C99,S
+271,0,1,"Cairns, Mr. Alexander",male,,0,0,113798,31,,S
+272,1,3,"Tornquist, Mr. William Henry",male,25,0,0,LINE,0,,S
+273,1,2,"Mellinger, Mrs. (Elizabeth Anne Maidment)",female,41,0,1,250644,19.5,,S
+274,0,1,"Natsch, Mr. Charles H",male,37,0,1,PC 17596,29.7,C118,C
+275,1,3,"Healy, Miss. Hanora ""Nora""",female,,0,0,370375,7.75,,Q
+276,1,1,"Andrews, Miss. Kornelia Theodosia",female,63,1,0,13502,77.9583,D7,S
+277,0,3,"Lindblom, Miss. Augusta Charlotta",female,45,0,0,347073,7.75,,S
+278,0,2,"Parkes, Mr. Francis ""Frank""",male,,0,0,239853,0,,S
+279,0,3,"Rice, Master. Eric",male,7,4,1,382652,29.125,,Q
+280,1,3,"Abbott, Mrs. Stanton (Rosa Hunt)",female,35,1,1,C.A. 2673,20.25,,S
+281,0,3,"Duane, Mr. Frank",male,65,0,0,336439,7.75,,Q
+282,0,3,"Olsson, Mr. Nils Johan Goransson",male,28,0,0,347464,7.8542,,S
+283,0,3,"de Pelsmaeker, Mr. Alfons",male,16,0,0,345778,9.5,,S
+284,1,3,"Dorking, Mr. Edward Arthur",male,19,0,0,A/5. 10482,8.05,,S
+285,0,1,"Smith, Mr. Richard William",male,,0,0,113056,26,A19,S
+286,0,3,"Stankovic, Mr. Ivan",male,33,0,0,349239,8.6625,,C
+287,1,3,"de Mulder, Mr. Theodore",male,30,0,0,345774,9.5,,S
+288,0,3,"Naidenoff, Mr. Penko",male,22,0,0,349206,7.8958,,S
+289,1,2,"Hosono, Mr. Masabumi",male,42,0,0,237798,13,,S
+290,1,3,"Connolly, Miss. Kate",female,22,0,0,370373,7.75,,Q
+291,1,1,"Barber, Miss. Ellen ""Nellie""",female,26,0,0,19877,78.85,,S
+292,1,1,"Bishop, Mrs. Dickinson H (Helen Walton)",female,19,1,0,11967,91.0792,B49,C
+293,0,2,"Levy, Mr. Rene Jacques",male,36,0,0,SC/Paris 2163,12.875,D,C
+294,0,3,"Haas, Miss. Aloisia",female,24,0,0,349236,8.85,,S
+295,0,3,"Mineff, Mr. Ivan",male,24,0,0,349233,7.8958,,S
+296,0,1,"Lewy, Mr. Ervin G",male,,0,0,PC 17612,27.7208,,C
+297,0,3,"Hanna, Mr. Mansour",male,23.5,0,0,2693,7.2292,,C
+298,0,1,"Allison, Miss. Helen Loraine",female,2,1,2,113781,151.55,C22 C26,S
+299,1,1,"Saalfeld, Mr. Adolphe",male,,0,0,19988,30.5,C106,S
+300,1,1,"Baxter, Mrs. James (Helene DeLaudeniere Chaput)",female,50,0,1,PC 17558,247.5208,B58 B60,C
+301,1,3,"Kelly, Miss. Anna Katherine ""Annie Kate""",female,,0,0,9234,7.75,,Q
+302,1,3,"McCoy, Mr. Bernard",male,,2,0,367226,23.25,,Q
+303,0,3,"Johnson, Mr. William Cahoone Jr",male,19,0,0,LINE,0,,S
+304,1,2,"Keane, Miss. Nora A",female,,0,0,226593,12.35,E101,Q
+305,0,3,"Williams, Mr. Howard Hugh ""Harry""",male,,0,0,A/5 2466,8.05,,S
+306,1,1,"Allison, Master. Hudson Trevor",male,0.92,1,2,113781,151.55,C22 C26,S
+307,1,1,"Fleming, Miss. Margaret",female,,0,0,17421,110.8833,,C
+308,1,1,"Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)",female,17,1,0,PC 17758,108.9,C65,C
+309,0,2,"Abelson, Mr. Samuel",male,30,1,0,P/PP 3381,24,,C
+310,1,1,"Francatelli, Miss. Laura Mabel",female,30,0,0,PC 17485,56.9292,E36,C
+311,1,1,"Hays, Miss. Margaret Bechstein",female,24,0,0,11767,83.1583,C54,C
+312,1,1,"Ryerson, Miss. Emily Borie",female,18,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+313,0,2,"Lahtinen, Mrs. William (Anna Sylfven)",female,26,1,1,250651,26,,S
+314,0,3,"Hendekovic, Mr. Ignjac",male,28,0,0,349243,7.8958,,S
+315,0,2,"Hart, Mr. Benjamin",male,43,1,1,F.C.C. 13529,26.25,,S
+316,1,3,"Nilsson, Miss. Helmina Josefina",female,26,0,0,347470,7.8542,,S
+317,1,2,"Kantor, Mrs. Sinai (Miriam Sternin)",female,24,1,0,244367,26,,S
+318,0,2,"Moraweck, Dr. Ernest",male,54,0,0,29011,14,,S
+319,1,1,"Wick, Miss. Mary Natalie",female,31,0,2,36928,164.8667,C7,S
+320,1,1,"Spedden, Mrs. Frederic Oakley (Margaretta Corning Stone)",female,40,1,1,16966,134.5,E34,C
+321,0,3,"Dennis, Mr. Samuel",male,22,0,0,A/5 21172,7.25,,S
+322,0,3,"Danoff, Mr. Yoto",male,27,0,0,349219,7.8958,,S
+323,1,2,"Slayter, Miss. Hilda Mary",female,30,0,0,234818,12.35,,Q
+324,1,2,"Caldwell, Mrs. Albert Francis (Sylvia Mae Harbaugh)",female,22,1,1,248738,29,,S
+325,0,3,"Sage, Mr. George John Jr",male,,8,2,CA. 2343,69.55,,S
+326,1,1,"Young, Miss. Marie Grice",female,36,0,0,PC 17760,135.6333,C32,C
+327,0,3,"Nysveen, Mr. Johan Hansen",male,61,0,0,345364,6.2375,,S
+328,1,2,"Ball, Mrs. (Ada E Hall)",female,36,0,0,28551,13,D,S
+329,1,3,"Goldsmith, Mrs. Frank John (Emily Alice Brown)",female,31,1,1,363291,20.525,,S
+330,1,1,"Hippach, Miss. Jean Gertrude",female,16,0,1,111361,57.9792,B18,C
+331,1,3,"McCoy, Miss. Agnes",female,,2,0,367226,23.25,,Q
+332,0,1,"Partner, Mr. Austen",male,45.5,0,0,113043,28.5,C124,S
+333,0,1,"Graham, Mr. George Edward",male,38,0,1,PC 17582,153.4625,C91,S
+334,0,3,"Vander Planke, Mr. Leo Edmondus",male,16,2,0,345764,18,,S
+335,1,1,"Frauenthal, Mrs. Henry William (Clara Heinsheimer)",female,,1,0,PC 17611,133.65,,S
+336,0,3,"Denkoff, Mr. Mitto",male,,0,0,349225,7.8958,,S
+337,0,1,"Pears, Mr. Thomas Clinton",male,29,1,0,113776,66.6,C2,S
+338,1,1,"Burns, Miss. Elizabeth Margaret",female,41,0,0,16966,134.5,E40,C
+339,1,3,"Dahl, Mr. Karl Edwart",male,45,0,0,7598,8.05,,S
+340,0,1,"Blackwell, Mr. Stephen Weart",male,45,0,0,113784,35.5,T,S
+341,1,2,"Navratil, Master. Edmond Roger",male,2,1,1,230080,26,F2,S
+342,1,1,"Fortune, Miss. Alice Elizabeth",female,24,3,2,19950,263,C23 C25 C27,S
+343,0,2,"Collander, Mr. Erik Gustaf",male,28,0,0,248740,13,,S
+344,0,2,"Sedgwick, Mr. Charles Frederick Waddington",male,25,0,0,244361,13,,S
+345,0,2,"Fox, Mr. Stanley Hubert",male,36,0,0,229236,13,,S
+346,1,2,"Brown, Miss. Amelia ""Mildred""",female,24,0,0,248733,13,F33,S
+347,1,2,"Smith, Miss. Marion Elsie",female,40,0,0,31418,13,,S
+348,1,3,"Davison, Mrs. Thomas Henry (Mary E Finck)",female,,1,0,386525,16.1,,S
+349,1,3,"Coutts, Master. William Loch ""William""",male,3,1,1,C.A. 37671,15.9,,S
+350,0,3,"Dimic, Mr. Jovan",male,42,0,0,315088,8.6625,,S
+351,0,3,"Odahl, Mr. Nils Martin",male,23,0,0,7267,9.225,,S
+352,0,1,"Williams-Lambert, Mr. Fletcher Fellows",male,,0,0,113510,35,C128,S
+353,0,3,"Elias, Mr. Tannous",male,15,1,1,2695,7.2292,,C
+354,0,3,"Arnold-Franchi, Mr. Josef",male,25,1,0,349237,17.8,,S
+355,0,3,"Yousif, Mr. Wazli",male,,0,0,2647,7.225,,C
+356,0,3,"Vanden Steen, Mr. Leo Peter",male,28,0,0,345783,9.5,,S
+357,1,1,"Bowerman, Miss. Elsie Edith",female,22,0,1,113505,55,E33,S
+358,0,2,"Funk, Miss. Annie Clemmer",female,38,0,0,237671,13,,S
+359,1,3,"McGovern, Miss. Mary",female,,0,0,330931,7.8792,,Q
+360,1,3,"Mockler, Miss. Helen Mary ""Ellie""",female,,0,0,330980,7.8792,,Q
+361,0,3,"Skoog, Mr. Wilhelm",male,40,1,4,347088,27.9,,S
+362,0,2,"del Carlo, Mr. Sebastiano",male,29,1,0,SC/PARIS 2167,27.7208,,C
+363,0,3,"Barbara, Mrs. (Catherine David)",female,45,0,1,2691,14.4542,,C
+364,0,3,"Asim, Mr. Adola",male,35,0,0,SOTON/O.Q. 3101310,7.05,,S
+365,0,3,"O'Brien, Mr. Thomas",male,,1,0,370365,15.5,,Q
+366,0,3,"Adahl, Mr. Mauritz Nils Martin",male,30,0,0,C 7076,7.25,,S
+367,1,1,"Warren, Mrs. Frank Manley (Anna Sophia Atkinson)",female,60,1,0,110813,75.25,D37,C
+368,1,3,"Moussa, Mrs. (Mantoura Boulos)",female,,0,0,2626,7.2292,,C
+369,1,3,"Jermyn, Miss. Annie",female,,0,0,14313,7.75,,Q
+370,1,1,"Aubart, Mme. Leontine Pauline",female,24,0,0,PC 17477,69.3,B35,C
+371,1,1,"Harder, Mr. George Achilles",male,25,1,0,11765,55.4417,E50,C
+372,0,3,"Wiklund, Mr. Jakob Alfred",male,18,1,0,3101267,6.4958,,S
+373,0,3,"Beavan, Mr. William Thomas",male,19,0,0,323951,8.05,,S
+374,0,1,"Ringhini, Mr. Sante",male,22,0,0,PC 17760,135.6333,,C
+375,0,3,"Palsson, Miss. Stina Viola",female,3,3,1,349909,21.075,,S
+376,1,1,"Meyer, Mrs. Edgar Joseph (Leila Saks)",female,,1,0,PC 17604,82.1708,,C
+377,1,3,"Landergren, Miss. Aurora Adelia",female,22,0,0,C 7077,7.25,,S
+378,0,1,"Widener, Mr. Harry Elkins",male,27,0,2,113503,211.5,C82,C
+379,0,3,"Betros, Mr. Tannous",male,20,0,0,2648,4.0125,,C
+380,0,3,"Gustafsson, Mr. Karl Gideon",male,19,0,0,347069,7.775,,S
+381,1,1,"Bidois, Miss. Rosalie",female,42,0,0,PC 17757,227.525,,C
+382,1,3,"Nakid, Miss. Maria (""Mary"")",female,1,0,2,2653,15.7417,,C
+383,0,3,"Tikkanen, Mr. Juho",male,32,0,0,STON/O 2. 3101293,7.925,,S
+384,1,1,"Holverson, Mrs. Alexander Oskar (Mary Aline Towner)",female,35,1,0,113789,52,,S
+385,0,3,"Plotcharsky, Mr. Vasil",male,,0,0,349227,7.8958,,S
+386,0,2,"Davies, Mr. Charles Henry",male,18,0,0,S.O.C. 14879,73.5,,S
+387,0,3,"Goodwin, Master. Sidney Leonard",male,1,5,2,CA 2144,46.9,,S
+388,1,2,"Buss, Miss. Kate",female,36,0,0,27849,13,,S
+389,0,3,"Sadlier, Mr. Matthew",male,,0,0,367655,7.7292,,Q
+390,1,2,"Lehmann, Miss. Bertha",female,17,0,0,SC 1748,12,,C
+391,1,1,"Carter, Mr. William Ernest",male,36,1,2,113760,120,B96 B98,S
+392,1,3,"Jansson, Mr. Carl Olof",male,21,0,0,350034,7.7958,,S
+393,0,3,"Gustafsson, Mr. Johan Birger",male,28,2,0,3101277,7.925,,S
+394,1,1,"Newell, Miss. Marjorie",female,23,1,0,35273,113.275,D36,C
+395,1,3,"Sandstrom, Mrs. Hjalmar (Agnes Charlotta Bengtsson)",female,24,0,2,PP 9549,16.7,G6,S
+396,0,3,"Johansson, Mr. Erik",male,22,0,0,350052,7.7958,,S
+397,0,3,"Olsson, Miss. Elina",female,31,0,0,350407,7.8542,,S
+398,0,2,"McKane, Mr. Peter David",male,46,0,0,28403,26,,S
+399,0,2,"Pain, Dr. Alfred",male,23,0,0,244278,10.5,,S
+400,1,2,"Trout, Mrs. William H (Jessie L)",female,28,0,0,240929,12.65,,S
+401,1,3,"Niskanen, Mr. Juha",male,39,0,0,STON/O 2. 3101289,7.925,,S
+402,0,3,"Adams, Mr. John",male,26,0,0,341826,8.05,,S
+403,0,3,"Jussila, Miss. Mari Aina",female,21,1,0,4137,9.825,,S
+404,0,3,"Hakkarainen, Mr. Pekka Pietari",male,28,1,0,STON/O2. 3101279,15.85,,S
+405,0,3,"Oreskovic, Miss. Marija",female,20,0,0,315096,8.6625,,S
+406,0,2,"Gale, Mr. Shadrach",male,34,1,0,28664,21,,S
+407,0,3,"Widegren, Mr. Carl/Charles Peter",male,51,0,0,347064,7.75,,S
+408,1,2,"Richards, Master. William Rowe",male,3,1,1,29106,18.75,,S
+409,0,3,"Birkeland, Mr. Hans Martin Monsen",male,21,0,0,312992,7.775,,S
+410,0,3,"Lefebre, Miss. Ida",female,,3,1,4133,25.4667,,S
+411,0,3,"Sdycoff, Mr. Todor",male,,0,0,349222,7.8958,,S
+412,0,3,"Hart, Mr. Henry",male,,0,0,394140,6.8583,,Q
+413,1,1,"Minahan, Miss. Daisy E",female,33,1,0,19928,90,C78,Q
+414,0,2,"Cunningham, Mr. Alfred Fleming",male,,0,0,239853,0,,S
+415,1,3,"Sundman, Mr. Johan Julian",male,44,0,0,STON/O 2. 3101269,7.925,,S
+416,0,3,"Meek, Mrs. Thomas (Annie Louise Rowley)",female,,0,0,343095,8.05,,S
+417,1,2,"Drew, Mrs. James Vivian (Lulu Thorne Christian)",female,34,1,1,28220,32.5,,S
+418,1,2,"Silven, Miss. Lyyli Karoliina",female,18,0,2,250652,13,,S
+419,0,2,"Matthews, Mr. William John",male,30,0,0,28228,13,,S
+420,0,3,"Van Impe, Miss. Catharina",female,10,0,2,345773,24.15,,S
+421,0,3,"Gheorgheff, Mr. Stanio",male,,0,0,349254,7.8958,,C
+422,0,3,"Charters, Mr. David",male,21,0,0,A/5. 13032,7.7333,,Q
+423,0,3,"Zimmerman, Mr. Leo",male,29,0,0,315082,7.875,,S
+424,0,3,"Danbom, Mrs. Ernst Gilbert (Anna Sigrid Maria Brogren)",female,28,1,1,347080,14.4,,S
+425,0,3,"Rosblom, Mr. Viktor Richard",male,18,1,1,370129,20.2125,,S
+426,0,3,"Wiseman, Mr. Phillippe",male,,0,0,A/4. 34244,7.25,,S
+427,1,2,"Clarke, Mrs. Charles V (Ada Maria Winfield)",female,28,1,0,2003,26,,S
+428,1,2,"Phillips, Miss. Kate Florence (""Mrs Kate Louise Phillips Marshall"")",female,19,0,0,250655,26,,S
+429,0,3,"Flynn, Mr. James",male,,0,0,364851,7.75,,Q
+430,1,3,"Pickard, Mr. Berk (Berk Trembisky)",male,32,0,0,SOTON/O.Q. 392078,8.05,E10,S
+431,1,1,"Bjornstrom-Steffansson, Mr. Mauritz Hakan",male,28,0,0,110564,26.55,C52,S
+432,1,3,"Thorneycroft, Mrs. Percival (Florence Kate White)",female,,1,0,376564,16.1,,S
+433,1,2,"Louch, Mrs. Charles Alexander (Alice Adelaide Slow)",female,42,1,0,SC/AH 3085,26,,S
+434,0,3,"Kallio, Mr. Nikolai Erland",male,17,0,0,STON/O 2. 3101274,7.125,,S
+435,0,1,"Silvey, Mr. William Baird",male,50,1,0,13507,55.9,E44,S
+436,1,1,"Carter, Miss. Lucile Polk",female,14,1,2,113760,120,B96 B98,S
+437,0,3,"Ford, Miss. Doolina Margaret ""Daisy""",female,21,2,2,W./C. 6608,34.375,,S
+438,1,2,"Richards, Mrs. Sidney (Emily Hocking)",female,24,2,3,29106,18.75,,S
+439,0,1,"Fortune, Mr. Mark",male,64,1,4,19950,263,C23 C25 C27,S
+440,0,2,"Kvillner, Mr. Johan Henrik Johannesson",male,31,0,0,C.A. 18723,10.5,,S
+441,1,2,"Hart, Mrs. Benjamin (Esther Ada Bloomfield)",female,45,1,1,F.C.C. 13529,26.25,,S
+442,0,3,"Hampe, Mr. Leon",male,20,0,0,345769,9.5,,S
+443,0,3,"Petterson, Mr. Johan Emil",male,25,1,0,347076,7.775,,S
+444,1,2,"Reynaldo, Ms. Encarnacion",female,28,0,0,230434,13,,S
+445,1,3,"Johannesen-Bratthammer, Mr. Bernt",male,,0,0,65306,8.1125,,S
+446,1,1,"Dodge, Master. Washington",male,4,0,2,33638,81.8583,A34,S
+447,1,2,"Mellinger, Miss. Madeleine Violet",female,13,0,1,250644,19.5,,S
+448,1,1,"Seward, Mr. Frederic Kimber",male,34,0,0,113794,26.55,,S
+449,1,3,"Baclini, Miss. Marie Catherine",female,5,2,1,2666,19.2583,,C
+450,1,1,"Peuchen, Major. Arthur Godfrey",male,52,0,0,113786,30.5,C104,S
+451,0,2,"West, Mr. Edwy Arthur",male,36,1,2,C.A. 34651,27.75,,S
+452,0,3,"Hagland, Mr. Ingvald Olai Olsen",male,,1,0,65303,19.9667,,S
+453,0,1,"Foreman, Mr. Benjamin Laventall",male,30,0,0,113051,27.75,C111,C
+454,1,1,"Goldenberg, Mr. Samuel L",male,49,1,0,17453,89.1042,C92,C
+455,0,3,"Peduzzi, Mr. Joseph",male,,0,0,A/5 2817,8.05,,S
+456,1,3,"Jalsevac, Mr. Ivan",male,29,0,0,349240,7.8958,,C
+457,0,1,"Millet, Mr. Francis Davis",male,65,0,0,13509,26.55,E38,S
+458,1,1,"Kenyon, Mrs. Frederick R (Marion)",female,,1,0,17464,51.8625,D21,S
+459,1,2,"Toomey, Miss. Ellen",female,50,0,0,F.C.C. 13531,10.5,,S
+460,0,3,"O'Connor, Mr. Maurice",male,,0,0,371060,7.75,,Q
+461,1,1,"Anderson, Mr. Harry",male,48,0,0,19952,26.55,E12,S
+462,0,3,"Morley, Mr. William",male,34,0,0,364506,8.05,,S
+463,0,1,"Gee, Mr. Arthur H",male,47,0,0,111320,38.5,E63,S
+464,0,2,"Milling, Mr. Jacob Christian",male,48,0,0,234360,13,,S
+465,0,3,"Maisner, Mr. Simon",male,,0,0,A/S 2816,8.05,,S
+466,0,3,"Goncalves, Mr. Manuel Estanslas",male,38,0,0,SOTON/O.Q. 3101306,7.05,,S
+467,0,2,"Campbell, Mr. William",male,,0,0,239853,0,,S
+468,0,1,"Smart, Mr. John Montgomery",male,56,0,0,113792,26.55,,S
+469,0,3,"Scanlan, Mr. James",male,,0,0,36209,7.725,,Q
+470,1,3,"Baclini, Miss. Helene Barbara",female,0.75,2,1,2666,19.2583,,C
+471,0,3,"Keefe, Mr. Arthur",male,,0,0,323592,7.25,,S
+472,0,3,"Cacic, Mr. Luka",male,38,0,0,315089,8.6625,,S
+473,1,2,"West, Mrs. Edwy Arthur (Ada Mary Worth)",female,33,1,2,C.A. 34651,27.75,,S
+474,1,2,"Jerwan, Mrs. Amin S (Marie Marthe Thuillard)",female,23,0,0,SC/AH Basle 541,13.7917,D,C
+475,0,3,"Strandberg, Miss. Ida Sofia",female,22,0,0,7553,9.8375,,S
+476,0,1,"Clifford, Mr. George Quincy",male,,0,0,110465,52,A14,S
+477,0,2,"Renouf, Mr. Peter Henry",male,34,1,0,31027,21,,S
+478,0,3,"Braund, Mr. Lewis Richard",male,29,1,0,3460,7.0458,,S
+479,0,3,"Karlsson, Mr. Nils August",male,22,0,0,350060,7.5208,,S
+480,1,3,"Hirvonen, Miss. Hildur E",female,2,0,1,3101298,12.2875,,S
+481,0,3,"Goodwin, Master. Harold Victor",male,9,5,2,CA 2144,46.9,,S
+482,0,2,"Frost, Mr. Anthony Wood ""Archie""",male,,0,0,239854,0,,S
+483,0,3,"Rouse, Mr. Richard Henry",male,50,0,0,A/5 3594,8.05,,S
+484,1,3,"Turkula, Mrs. (Hedwig)",female,63,0,0,4134,9.5875,,S
+485,1,1,"Bishop, Mr. Dickinson H",male,25,1,0,11967,91.0792,B49,C
+486,0,3,"Lefebre, Miss. Jeannie",female,,3,1,4133,25.4667,,S
+487,1,1,"Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby)",female,35,1,0,19943,90,C93,S
+488,0,1,"Kent, Mr. Edward Austin",male,58,0,0,11771,29.7,B37,C
+489,0,3,"Somerton, Mr. Francis William",male,30,0,0,A.5. 18509,8.05,,S
+490,1,3,"Coutts, Master. Eden Leslie ""Neville""",male,9,1,1,C.A. 37671,15.9,,S
+491,0,3,"Hagland, Mr. Konrad Mathias Reiersen",male,,1,0,65304,19.9667,,S
+492,0,3,"Windelov, Mr. Einar",male,21,0,0,SOTON/OQ 3101317,7.25,,S
+493,0,1,"Molson, Mr. Harry Markland",male,55,0,0,113787,30.5,C30,S
+494,0,1,"Artagaveytia, Mr. Ramon",male,71,0,0,PC 17609,49.5042,,C
+495,0,3,"Stanley, Mr. Edward Roland",male,21,0,0,A/4 45380,8.05,,S
+496,0,3,"Yousseff, Mr. Gerious",male,,0,0,2627,14.4583,,C
+497,1,1,"Eustis, Miss. Elizabeth Mussey",female,54,1,0,36947,78.2667,D20,C
+498,0,3,"Shellard, Mr. Frederick William",male,,0,0,C.A. 6212,15.1,,S
+499,0,1,"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)",female,25,1,2,113781,151.55,C22 C26,S
+500,0,3,"Svensson, Mr. Olof",male,24,0,0,350035,7.7958,,S
+501,0,3,"Calic, Mr. Petar",male,17,0,0,315086,8.6625,,S
+502,0,3,"Canavan, Miss. Mary",female,21,0,0,364846,7.75,,Q
+503,0,3,"O'Sullivan, Miss. Bridget Mary",female,,0,0,330909,7.6292,,Q
+504,0,3,"Laitinen, Miss. Kristina Sofia",female,37,0,0,4135,9.5875,,S
+505,1,1,"Maioni, Miss. Roberta",female,16,0,0,110152,86.5,B79,S
+506,0,1,"Penasco y Castellana, Mr. Victor de Satode",male,18,1,0,PC 17758,108.9,C65,C
+507,1,2,"Quick, Mrs. Frederick Charles (Jane Richards)",female,33,0,2,26360,26,,S
+508,1,1,"Bradley, Mr. George (""George Arthur Brayton"")",male,,0,0,111427,26.55,,S
+509,0,3,"Olsen, Mr. Henry Margido",male,28,0,0,C 4001,22.525,,S
+510,1,3,"Lang, Mr. Fang",male,26,0,0,1601,56.4958,,S
+511,1,3,"Daly, Mr. Eugene Patrick",male,29,0,0,382651,7.75,,Q
+512,0,3,"Webber, Mr. James",male,,0,0,SOTON/OQ 3101316,8.05,,S
+513,1,1,"McGough, Mr. James Robert",male,36,0,0,PC 17473,26.2875,E25,S
+514,1,1,"Rothschild, Mrs. Martin (Elizabeth L. Barrett)",female,54,1,0,PC 17603,59.4,,C
+515,0,3,"Coleff, Mr. Satio",male,24,0,0,349209,7.4958,,S
+516,0,1,"Walker, Mr. William Anderson",male,47,0,0,36967,34.0208,D46,S
+517,1,2,"Lemore, Mrs. (Amelia Milley)",female,34,0,0,C.A. 34260,10.5,F33,S
+518,0,3,"Ryan, Mr. Patrick",male,,0,0,371110,24.15,,Q
+519,1,2,"Angle, Mrs. William A (Florence ""Mary"" Agnes Hughes)",female,36,1,0,226875,26,,S
+520,0,3,"Pavlovic, Mr. Stefo",male,32,0,0,349242,7.8958,,S
+521,1,1,"Perreault, Miss. Anne",female,30,0,0,12749,93.5,B73,S
+522,0,3,"Vovk, Mr. Janko",male,22,0,0,349252,7.8958,,S
+523,0,3,"Lahoud, Mr. Sarkis",male,,0,0,2624,7.225,,C
+524,1,1,"Hippach, Mrs. Louis Albert (Ida Sophia Fischer)",female,44,0,1,111361,57.9792,B18,C
+525,0,3,"Kassem, Mr. Fared",male,,0,0,2700,7.2292,,C
+526,0,3,"Farrell, Mr. James",male,40.5,0,0,367232,7.75,,Q
+527,1,2,"Ridsdale, Miss. Lucy",female,50,0,0,W./C. 14258,10.5,,S
+528,0,1,"Farthing, Mr. John",male,,0,0,PC 17483,221.7792,C95,S
+529,0,3,"Salonen, Mr. Johan Werner",male,39,0,0,3101296,7.925,,S
+530,0,2,"Hocking, Mr. Richard George",male,23,2,1,29104,11.5,,S
+531,1,2,"Quick, Miss. Phyllis May",female,2,1,1,26360,26,,S
+532,0,3,"Toufik, Mr. Nakli",male,,0,0,2641,7.2292,,C
+533,0,3,"Elias, Mr. Joseph Jr",male,17,1,1,2690,7.2292,,C
+534,1,3,"Peter, Mrs. Catherine (Catherine Rizk)",female,,0,2,2668,22.3583,,C
+535,0,3,"Cacic, Miss. Marija",female,30,0,0,315084,8.6625,,S
+536,1,2,"Hart, Miss. Eva Miriam",female,7,0,2,F.C.C. 13529,26.25,,S
+537,0,1,"Butt, Major. Archibald Willingham",male,45,0,0,113050,26.55,B38,S
+538,1,1,"LeRoy, Miss. Bertha",female,30,0,0,PC 17761,106.425,,C
+539,0,3,"Risien, Mr. Samuel Beard",male,,0,0,364498,14.5,,S
+540,1,1,"Frolicher, Miss. Hedwig Margaritha",female,22,0,2,13568,49.5,B39,C
+541,1,1,"Crosby, Miss. Harriet R",female,36,0,2,WE/P 5735,71,B22,S
+542,0,3,"Andersson, Miss. Ingeborg Constanzia",female,9,4,2,347082,31.275,,S
+543,0,3,"Andersson, Miss. Sigrid Elisabeth",female,11,4,2,347082,31.275,,S
+544,1,2,"Beane, Mr. Edward",male,32,1,0,2908,26,,S
+545,0,1,"Douglas, Mr. Walter Donald",male,50,1,0,PC 17761,106.425,C86,C
+546,0,1,"Nicholson, Mr. Arthur Ernest",male,64,0,0,693,26,,S
+547,1,2,"Beane, Mrs. Edward (Ethel Clarke)",female,19,1,0,2908,26,,S
+548,1,2,"Padro y Manent, Mr. Julian",male,,0,0,SC/PARIS 2146,13.8625,,C
+549,0,3,"Goldsmith, Mr. Frank John",male,33,1,1,363291,20.525,,S
+550,1,2,"Davies, Master. John Morgan Jr",male,8,1,1,C.A. 33112,36.75,,S
+551,1,1,"Thayer, Mr. John Borland Jr",male,17,0,2,17421,110.8833,C70,C
+552,0,2,"Sharp, Mr. Percival James R",male,27,0,0,244358,26,,S
+553,0,3,"O'Brien, Mr. Timothy",male,,0,0,330979,7.8292,,Q
+554,1,3,"Leeni, Mr. Fahim (""Philip Zenni"")",male,22,0,0,2620,7.225,,C
+555,1,3,"Ohman, Miss. Velin",female,22,0,0,347085,7.775,,S
+556,0,1,"Wright, Mr. George",male,62,0,0,113807,26.55,,S
+557,1,1,"Duff Gordon, Lady. (Lucille Christiana Sutherland) (""Mrs Morgan"")",female,48,1,0,11755,39.6,A16,C
+558,0,1,"Robbins, Mr. Victor",male,,0,0,PC 17757,227.525,,C
+559,1,1,"Taussig, Mrs. Emil (Tillie Mandelbaum)",female,39,1,1,110413,79.65,E67,S
+560,1,3,"de Messemaeker, Mrs. Guillaume Joseph (Emma)",female,36,1,0,345572,17.4,,S
+561,0,3,"Morrow, Mr. Thomas Rowan",male,,0,0,372622,7.75,,Q
+562,0,3,"Sivic, Mr. Husein",male,40,0,0,349251,7.8958,,S
+563,0,2,"Norman, Mr. Robert Douglas",male,28,0,0,218629,13.5,,S
+564,0,3,"Simmons, Mr. John",male,,0,0,SOTON/OQ 392082,8.05,,S
+565,0,3,"Meanwell, Miss. (Marion Ogden)",female,,0,0,SOTON/O.Q. 392087,8.05,,S
+566,0,3,"Davies, Mr. Alfred J",male,24,2,0,A/4 48871,24.15,,S
+567,0,3,"Stoytcheff, Mr. Ilia",male,19,0,0,349205,7.8958,,S
+568,0,3,"Palsson, Mrs. Nils (Alma Cornelia Berglund)",female,29,0,4,349909,21.075,,S
+569,0,3,"Doharr, Mr. Tannous",male,,0,0,2686,7.2292,,C
+570,1,3,"Jonsson, Mr. Carl",male,32,0,0,350417,7.8542,,S
+571,1,2,"Harris, Mr. George",male,62,0,0,S.W./PP 752,10.5,,S
+572,1,1,"Appleton, Mrs. Edward Dale (Charlotte Lamson)",female,53,2,0,11769,51.4792,C101,S
+573,1,1,"Flynn, Mr. John Irwin (""Irving"")",male,36,0,0,PC 17474,26.3875,E25,S
+574,1,3,"Kelly, Miss. Mary",female,,0,0,14312,7.75,,Q
+575,0,3,"Rush, Mr. Alfred George John",male,16,0,0,A/4. 20589,8.05,,S
+576,0,3,"Patchett, Mr. George",male,19,0,0,358585,14.5,,S
+577,1,2,"Garside, Miss. Ethel",female,34,0,0,243880,13,,S
+578,1,1,"Silvey, Mrs. William Baird (Alice Munger)",female,39,1,0,13507,55.9,E44,S
+579,0,3,"Caram, Mrs. Joseph (Maria Elias)",female,,1,0,2689,14.4583,,C
+580,1,3,"Jussila, Mr. Eiriik",male,32,0,0,STON/O 2. 3101286,7.925,,S
+581,1,2,"Christy, Miss. Julie Rachel",female,25,1,1,237789,30,,S
+582,1,1,"Thayer, Mrs. John Borland (Marian Longstreth Morris)",female,39,1,1,17421,110.8833,C68,C
+583,0,2,"Downton, Mr. William James",male,54,0,0,28403,26,,S
+584,0,1,"Ross, Mr. John Hugo",male,36,0,0,13049,40.125,A10,C
+585,0,3,"Paulner, Mr. Uscher",male,,0,0,3411,8.7125,,C
+586,1,1,"Taussig, Miss. Ruth",female,18,0,2,110413,79.65,E68,S
+587,0,2,"Jarvis, Mr. John Denzil",male,47,0,0,237565,15,,S
+588,1,1,"Frolicher-Stehli, Mr. Maxmillian",male,60,1,1,13567,79.2,B41,C
+589,0,3,"Gilinski, Mr. Eliezer",male,22,0,0,14973,8.05,,S
+590,0,3,"Murdlin, Mr. Joseph",male,,0,0,A./5. 3235,8.05,,S
+591,0,3,"Rintamaki, Mr. Matti",male,35,0,0,STON/O 2. 3101273,7.125,,S
+592,1,1,"Stephenson, Mrs. Walter Bertram (Martha Eustis)",female,52,1,0,36947,78.2667,D20,C
+593,0,3,"Elsbury, Mr. William James",male,47,0,0,A/5 3902,7.25,,S
+594,0,3,"Bourke, Miss. Mary",female,,0,2,364848,7.75,,Q
+595,0,2,"Chapman, Mr. John Henry",male,37,1,0,SC/AH 29037,26,,S
+596,0,3,"Van Impe, Mr. Jean Baptiste",male,36,1,1,345773,24.15,,S
+597,1,2,"Leitch, Miss. Jessie Wills",female,,0,0,248727,33,,S
+598,0,3,"Johnson, Mr. Alfred",male,49,0,0,LINE,0,,S
+599,0,3,"Boulos, Mr. Hanna",male,,0,0,2664,7.225,,C
+600,1,1,"Duff Gordon, Sir. Cosmo Edmund (""Mr Morgan"")",male,49,1,0,PC 17485,56.9292,A20,C
+601,1,2,"Jacobsohn, Mrs. Sidney Samuel (Amy Frances Christy)",female,24,2,1,243847,27,,S
+602,0,3,"Slabenoff, Mr. Petco",male,,0,0,349214,7.8958,,S
+603,0,1,"Harrington, Mr. Charles H",male,,0,0,113796,42.4,,S
+604,0,3,"Torber, Mr. Ernst William",male,44,0,0,364511,8.05,,S
+605,1,1,"Homer, Mr. Harry (""Mr E Haven"")",male,35,0,0,111426,26.55,,C
+606,0,3,"Lindell, Mr. Edvard Bengtsson",male,36,1,0,349910,15.55,,S
+607,0,3,"Karaic, Mr. Milan",male,30,0,0,349246,7.8958,,S
+608,1,1,"Daniel, Mr. Robert Williams",male,27,0,0,113804,30.5,,S
+609,1,2,"Laroche, Mrs. Joseph (Juliette Marie Louise Lafargue)",female,22,1,2,SC/Paris 2123,41.5792,,C
+610,1,1,"Shutes, Miss. Elizabeth W",female,40,0,0,PC 17582,153.4625,C125,S
+611,0,3,"Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren)",female,39,1,5,347082,31.275,,S
+612,0,3,"Jardin, Mr. Jose Neto",male,,0,0,SOTON/O.Q. 3101305,7.05,,S
+613,1,3,"Murphy, Miss. Margaret Jane",female,,1,0,367230,15.5,,Q
+614,0,3,"Horgan, Mr. John",male,,0,0,370377,7.75,,Q
+615,0,3,"Brocklebank, Mr. William Alfred",male,35,0,0,364512,8.05,,S
+616,1,2,"Herman, Miss. Alice",female,24,1,2,220845,65,,S
+617,0,3,"Danbom, Mr. Ernst Gilbert",male,34,1,1,347080,14.4,,S
+618,0,3,"Lobb, Mrs. William Arthur (Cordelia K Stanlick)",female,26,1,0,A/5. 3336,16.1,,S
+619,1,2,"Becker, Miss. Marion Louise",female,4,2,1,230136,39,F4,S
+620,0,2,"Gavey, Mr. Lawrence",male,26,0,0,31028,10.5,,S
+621,0,3,"Yasbeck, Mr. Antoni",male,27,1,0,2659,14.4542,,C
+622,1,1,"Kimball, Mr. Edwin Nelson Jr",male,42,1,0,11753,52.5542,D19,S
+623,1,3,"Nakid, Mr. Sahid",male,20,1,1,2653,15.7417,,C
+624,0,3,"Hansen, Mr. Henry Damsgaard",male,21,0,0,350029,7.8542,,S
+625,0,3,"Bowen, Mr. David John ""Dai""",male,21,0,0,54636,16.1,,S
+626,0,1,"Sutton, Mr. Frederick",male,61,0,0,36963,32.3208,D50,S
+627,0,2,"Kirkland, Rev. Charles Leonard",male,57,0,0,219533,12.35,,Q
+628,1,1,"Longley, Miss. Gretchen Fiske",female,21,0,0,13502,77.9583,D9,S
+629,0,3,"Bostandyeff, Mr. Guentcho",male,26,0,0,349224,7.8958,,S
+630,0,3,"O'Connell, Mr. Patrick D",male,,0,0,334912,7.7333,,Q
+631,1,1,"Barkworth, Mr. Algernon Henry Wilson",male,80,0,0,27042,30,A23,S
+632,0,3,"Lundahl, Mr. Johan Svensson",male,51,0,0,347743,7.0542,,S
+633,1,1,"Stahelin-Maeglin, Dr. Max",male,32,0,0,13214,30.5,B50,C
+634,0,1,"Parr, Mr. William Henry Marsh",male,,0,0,112052,0,,S
+635,0,3,"Skoog, Miss. Mabel",female,9,3,2,347088,27.9,,S
+636,1,2,"Davis, Miss. Mary",female,28,0,0,237668,13,,S
+637,0,3,"Leinonen, Mr. Antti Gustaf",male,32,0,0,STON/O 2. 3101292,7.925,,S
+638,0,2,"Collyer, Mr. Harvey",male,31,1,1,C.A. 31921,26.25,,S
+639,0,3,"Panula, Mrs. Juha (Maria Emilia Ojala)",female,41,0,5,3101295,39.6875,,S
+640,0,3,"Thorneycroft, Mr. Percival",male,,1,0,376564,16.1,,S
+641,0,3,"Jensen, Mr. Hans Peder",male,20,0,0,350050,7.8542,,S
+642,1,1,"Sagesser, Mlle. Emma",female,24,0,0,PC 17477,69.3,B35,C
+643,0,3,"Skoog, Miss. Margit Elizabeth",female,2,3,2,347088,27.9,,S
+644,1,3,"Foo, Mr. Choong",male,,0,0,1601,56.4958,,S
+645,1,3,"Baclini, Miss. Eugenie",female,0.75,2,1,2666,19.2583,,C
+646,1,1,"Harper, Mr. Henry Sleeper",male,48,1,0,PC 17572,76.7292,D33,C
+647,0,3,"Cor, Mr. Liudevit",male,19,0,0,349231,7.8958,,S
+648,1,1,"Simonius-Blumer, Col. Oberst Alfons",male,56,0,0,13213,35.5,A26,C
+649,0,3,"Willey, Mr. Edward",male,,0,0,S.O./P.P. 751,7.55,,S
+650,1,3,"Stanley, Miss. Amy Zillah Elsie",female,23,0,0,CA. 2314,7.55,,S
+651,0,3,"Mitkoff, Mr. Mito",male,,0,0,349221,7.8958,,S
+652,1,2,"Doling, Miss. Elsie",female,18,0,1,231919,23,,S
+653,0,3,"Kalvik, Mr. Johannes Halvorsen",male,21,0,0,8475,8.4333,,S
+654,1,3,"O'Leary, Miss. Hanora ""Norah""",female,,0,0,330919,7.8292,,Q
+655,0,3,"Hegarty, Miss. Hanora ""Nora""",female,18,0,0,365226,6.75,,Q
+656,0,2,"Hickman, Mr. Leonard Mark",male,24,2,0,S.O.C. 14879,73.5,,S
+657,0,3,"Radeff, Mr. Alexander",male,,0,0,349223,7.8958,,S
+658,0,3,"Bourke, Mrs. John (Catherine)",female,32,1,1,364849,15.5,,Q
+659,0,2,"Eitemiller, Mr. George Floyd",male,23,0,0,29751,13,,S
+660,0,1,"Newell, Mr. Arthur Webster",male,58,0,2,35273,113.275,D48,C
+661,1,1,"Frauenthal, Dr. Henry William",male,50,2,0,PC 17611,133.65,,S
+662,0,3,"Badt, Mr. Mohamed",male,40,0,0,2623,7.225,,C
+663,0,1,"Colley, Mr. Edward Pomeroy",male,47,0,0,5727,25.5875,E58,S
+664,0,3,"Coleff, Mr. Peju",male,36,0,0,349210,7.4958,,S
+665,1,3,"Lindqvist, Mr. Eino William",male,20,1,0,STON/O 2. 3101285,7.925,,S
+666,0,2,"Hickman, Mr. Lewis",male,32,2,0,S.O.C. 14879,73.5,,S
+667,0,2,"Butler, Mr. Reginald Fenton",male,25,0,0,234686,13,,S
+668,0,3,"Rommetvedt, Mr. Knud Paust",male,,0,0,312993,7.775,,S
+669,0,3,"Cook, Mr. Jacob",male,43,0,0,A/5 3536,8.05,,S
+670,1,1,"Taylor, Mrs. Elmer Zebley (Juliet Cummins Wright)",female,,1,0,19996,52,C126,S
+671,1,2,"Brown, Mrs. Thomas William Solomon (Elizabeth Catherine Ford)",female,40,1,1,29750,39,,S
+672,0,1,"Davidson, Mr. Thornton",male,31,1,0,F.C. 12750,52,B71,S
+673,0,2,"Mitchell, Mr. Henry Michael",male,70,0,0,C.A. 24580,10.5,,S
+674,1,2,"Wilhelms, Mr. Charles",male,31,0,0,244270,13,,S
+675,0,2,"Watson, Mr. Ennis Hastings",male,,0,0,239856,0,,S
+676,0,3,"Edvardsson, Mr. Gustaf Hjalmar",male,18,0,0,349912,7.775,,S
+677,0,3,"Sawyer, Mr. Frederick Charles",male,24.5,0,0,342826,8.05,,S
+678,1,3,"Turja, Miss. Anna Sofia",female,18,0,0,4138,9.8417,,S
+679,0,3,"Goodwin, Mrs. Frederick (Augusta Tyler)",female,43,1,6,CA 2144,46.9,,S
+680,1,1,"Cardeza, Mr. Thomas Drake Martinez",male,36,0,1,PC 17755,512.3292,B51 B53 B55,C
+681,0,3,"Peters, Miss. Katie",female,,0,0,330935,8.1375,,Q
+682,1,1,"Hassab, Mr. Hammad",male,27,0,0,PC 17572,76.7292,D49,C
+683,0,3,"Olsvigen, Mr. Thor Anderson",male,20,0,0,6563,9.225,,S
+684,0,3,"Goodwin, Mr. Charles Edward",male,14,5,2,CA 2144,46.9,,S
+685,0,2,"Brown, Mr. Thomas William Solomon",male,60,1,1,29750,39,,S
+686,0,2,"Laroche, Mr. Joseph Philippe Lemercier",male,25,1,2,SC/Paris 2123,41.5792,,C
+687,0,3,"Panula, Mr. Jaako Arnold",male,14,4,1,3101295,39.6875,,S
+688,0,3,"Dakic, Mr. Branko",male,19,0,0,349228,10.1708,,S
+689,0,3,"Fischer, Mr. Eberhard Thelander",male,18,0,0,350036,7.7958,,S
+690,1,1,"Madill, Miss. Georgette Alexandra",female,15,0,1,24160,211.3375,B5,S
+691,1,1,"Dick, Mr. Albert Adrian",male,31,1,0,17474,57,B20,S
+692,1,3,"Karun, Miss. Manca",female,4,0,1,349256,13.4167,,C
+693,1,3,"Lam, Mr. Ali",male,,0,0,1601,56.4958,,S
+694,0,3,"Saad, Mr. Khalil",male,25,0,0,2672,7.225,,C
+695,0,1,"Weir, Col. John",male,60,0,0,113800,26.55,,S
+696,0,2,"Chapman, Mr. Charles Henry",male,52,0,0,248731,13.5,,S
+697,0,3,"Kelly, Mr. James",male,44,0,0,363592,8.05,,S
+698,1,3,"Mullens, Miss. Katherine ""Katie""",female,,0,0,35852,7.7333,,Q
+699,0,1,"Thayer, Mr. John Borland",male,49,1,1,17421,110.8833,C68,C
+700,0,3,"Humblen, Mr. Adolf Mathias Nicolai Olsen",male,42,0,0,348121,7.65,F G63,S
+701,1,1,"Astor, Mrs. John Jacob (Madeleine Talmadge Force)",female,18,1,0,PC 17757,227.525,C62 C64,C
+702,1,1,"Silverthorne, Mr. Spencer Victor",male,35,0,0,PC 17475,26.2875,E24,S
+703,0,3,"Barbara, Miss. Saiide",female,18,0,1,2691,14.4542,,C
+704,0,3,"Gallagher, Mr. Martin",male,25,0,0,36864,7.7417,,Q
+705,0,3,"Hansen, Mr. Henrik Juul",male,26,1,0,350025,7.8542,,S
+706,0,2,"Morley, Mr. Henry Samuel (""Mr Henry Marshall"")",male,39,0,0,250655,26,,S
+707,1,2,"Kelly, Mrs. Florence ""Fannie""",female,45,0,0,223596,13.5,,S
+708,1,1,"Calderhead, Mr. Edward Pennington",male,42,0,0,PC 17476,26.2875,E24,S
+709,1,1,"Cleaver, Miss. Alice",female,22,0,0,113781,151.55,,S
+710,1,3,"Moubarek, Master. Halim Gonios (""William George"")",male,,1,1,2661,15.2458,,C
+711,1,1,"Mayne, Mlle. Berthe Antonine (""Mrs de Villiers"")",female,24,0,0,PC 17482,49.5042,C90,C
+712,0,1,"Klaber, Mr. Herman",male,,0,0,113028,26.55,C124,S
+713,1,1,"Taylor, Mr. Elmer Zebley",male,48,1,0,19996,52,C126,S
+714,0,3,"Larsson, Mr. August Viktor",male,29,0,0,7545,9.4833,,S
+715,0,2,"Greenberg, Mr. Samuel",male,52,0,0,250647,13,,S
+716,0,3,"Soholt, Mr. Peter Andreas Lauritz Andersen",male,19,0,0,348124,7.65,F G73,S
+717,1,1,"Endres, Miss. Caroline Louise",female,38,0,0,PC 17757,227.525,C45,C
+718,1,2,"Troutt, Miss. Edwina Celia ""Winnie""",female,27,0,0,34218,10.5,E101,S
+719,0,3,"McEvoy, Mr. Michael",male,,0,0,36568,15.5,,Q
+720,0,3,"Johnson, Mr. Malkolm Joackim",male,33,0,0,347062,7.775,,S
+721,1,2,"Harper, Miss. Annie Jessie ""Nina""",female,6,0,1,248727,33,,S
+722,0,3,"Jensen, Mr. Svend Lauritz",male,17,1,0,350048,7.0542,,S
+723,0,2,"Gillespie, Mr. William Henry",male,34,0,0,12233,13,,S
+724,0,2,"Hodges, Mr. Henry Price",male,50,0,0,250643,13,,S
+725,1,1,"Chambers, Mr. Norman Campbell",male,27,1,0,113806,53.1,E8,S
+726,0,3,"Oreskovic, Mr. Luka",male,20,0,0,315094,8.6625,,S
+727,1,2,"Renouf, Mrs. Peter Henry (Lillian Jefferys)",female,30,3,0,31027,21,,S
+728,1,3,"Mannion, Miss. Margareth",female,,0,0,36866,7.7375,,Q
+729,0,2,"Bryhl, Mr. Kurt Arnold Gottfrid",male,25,1,0,236853,26,,S
+730,0,3,"Ilmakangas, Miss. Pieta Sofia",female,25,1,0,STON/O2. 3101271,7.925,,S
+731,1,1,"Allen, Miss. Elisabeth Walton",female,29,0,0,24160,211.3375,B5,S
+732,0,3,"Hassan, Mr. Houssein G N",male,11,0,0,2699,18.7875,,C
+733,0,2,"Knight, Mr. Robert J",male,,0,0,239855,0,,S
+734,0,2,"Berriman, Mr. William John",male,23,0,0,28425,13,,S
+735,0,2,"Troupiansky, Mr. Moses Aaron",male,23,0,0,233639,13,,S
+736,0,3,"Williams, Mr. Leslie",male,28.5,0,0,54636,16.1,,S
+737,0,3,"Ford, Mrs. Edward (Margaret Ann Watson)",female,48,1,3,W./C. 6608,34.375,,S
+738,1,1,"Lesurer, Mr. Gustave J",male,35,0,0,PC 17755,512.3292,B101,C
+739,0,3,"Ivanoff, Mr. Kanio",male,,0,0,349201,7.8958,,S
+740,0,3,"Nankoff, Mr. Minko",male,,0,0,349218,7.8958,,S
+741,1,1,"Hawksford, Mr. Walter James",male,,0,0,16988,30,D45,S
+742,0,1,"Cavendish, Mr. Tyrell William",male,36,1,0,19877,78.85,C46,S
+743,1,1,"Ryerson, Miss. Susan Parker ""Suzette""",female,21,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+744,0,3,"McNamee, Mr. Neal",male,24,1,0,376566,16.1,,S
+745,1,3,"Stranden, Mr. Juho",male,31,0,0,STON/O 2. 3101288,7.925,,S
+746,0,1,"Crosby, Capt. Edward Gifford",male,70,1,1,WE/P 5735,71,B22,S
+747,0,3,"Abbott, Mr. Rossmore Edward",male,16,1,1,C.A. 2673,20.25,,S
+748,1,2,"Sinkkonen, Miss. Anna",female,30,0,0,250648,13,,S
+749,0,1,"Marvin, Mr. Daniel Warner",male,19,1,0,113773,53.1,D30,S
+750,0,3,"Connaghton, Mr. Michael",male,31,0,0,335097,7.75,,Q
+751,1,2,"Wells, Miss. Joan",female,4,1,1,29103,23,,S
+752,1,3,"Moor, Master. Meier",male,6,0,1,392096,12.475,E121,S
+753,0,3,"Vande Velde, Mr. Johannes Joseph",male,33,0,0,345780,9.5,,S
+754,0,3,"Jonkoff, Mr. Lalio",male,23,0,0,349204,7.8958,,S
+755,1,2,"Herman, Mrs. Samuel (Jane Laver)",female,48,1,2,220845,65,,S
+756,1,2,"Hamalainen, Master. Viljo",male,0.67,1,1,250649,14.5,,S
+757,0,3,"Carlsson, Mr. August Sigfrid",male,28,0,0,350042,7.7958,,S
+758,0,2,"Bailey, Mr. Percy Andrew",male,18,0,0,29108,11.5,,S
+759,0,3,"Theobald, Mr. Thomas Leonard",male,34,0,0,363294,8.05,,S
+760,1,1,"Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)",female,33,0,0,110152,86.5,B77,S
+761,0,3,"Garfirth, Mr. John",male,,0,0,358585,14.5,,S
+762,0,3,"Nirva, Mr. Iisakki Antino Aijo",male,41,0,0,SOTON/O2 3101272,7.125,,S
+763,1,3,"Barah, Mr. Hanna Assi",male,20,0,0,2663,7.2292,,C
+764,1,1,"Carter, Mrs. William Ernest (Lucile Polk)",female,36,1,2,113760,120,B96 B98,S
+765,0,3,"Eklund, Mr. Hans Linus",male,16,0,0,347074,7.775,,S
+766,1,1,"Hogeboom, Mrs. John C (Anna Andrews)",female,51,1,0,13502,77.9583,D11,S
+767,0,1,"Brewe, Dr. Arthur Jackson",male,,0,0,112379,39.6,,C
+768,0,3,"Mangan, Miss. Mary",female,30.5,0,0,364850,7.75,,Q
+769,0,3,"Moran, Mr. Daniel J",male,,1,0,371110,24.15,,Q
+770,0,3,"Gronnestad, Mr. Daniel Danielsen",male,32,0,0,8471,8.3625,,S
+771,0,3,"Lievens, Mr. Rene Aime",male,24,0,0,345781,9.5,,S
+772,0,3,"Jensen, Mr. Niels Peder",male,48,0,0,350047,7.8542,,S
+773,0,2,"Mack, Mrs. (Mary)",female,57,0,0,S.O./P.P. 3,10.5,E77,S
+774,0,3,"Elias, Mr. Dibo",male,,0,0,2674,7.225,,C
+775,1,2,"Hocking, Mrs. Elizabeth (Eliza Needs)",female,54,1,3,29105,23,,S
+776,0,3,"Myhrman, Mr. Pehr Fabian Oliver Malkolm",male,18,0,0,347078,7.75,,S
+777,0,3,"Tobin, Mr. Roger",male,,0,0,383121,7.75,F38,Q
+778,1,3,"Emanuel, Miss. Virginia Ethel",female,5,0,0,364516,12.475,,S
+779,0,3,"Kilgannon, Mr. Thomas J",male,,0,0,36865,7.7375,,Q
+780,1,1,"Robert, Mrs. Edward Scott (Elisabeth Walton McMillan)",female,43,0,1,24160,211.3375,B3,S
+781,1,3,"Ayoub, Miss. Banoura",female,13,0,0,2687,7.2292,,C
+782,1,1,"Dick, Mrs. Albert Adrian (Vera Gillespie)",female,17,1,0,17474,57,B20,S
+783,0,1,"Long, Mr. Milton Clyde",male,29,0,0,113501,30,D6,S
+784,0,3,"Johnston, Mr. Andrew G",male,,1,2,W./C. 6607,23.45,,S
+785,0,3,"Ali, Mr. William",male,25,0,0,SOTON/O.Q. 3101312,7.05,,S
+786,0,3,"Harmer, Mr. Abraham (David Lishin)",male,25,0,0,374887,7.25,,S
+787,1,3,"Sjoblom, Miss. Anna Sofia",female,18,0,0,3101265,7.4958,,S
+788,0,3,"Rice, Master. George Hugh",male,8,4,1,382652,29.125,,Q
+789,1,3,"Dean, Master. Bertram Vere",male,1,1,2,C.A. 2315,20.575,,S
+790,0,1,"Guggenheim, Mr. Benjamin",male,46,0,0,PC 17593,79.2,B82 B84,C
+791,0,3,"Keane, Mr. Andrew ""Andy""",male,,0,0,12460,7.75,,Q
+792,0,2,"Gaskell, Mr. Alfred",male,16,0,0,239865,26,,S
+793,0,3,"Sage, Miss. Stella Anna",female,,8,2,CA. 2343,69.55,,S
+794,0,1,"Hoyt, Mr. William Fisher",male,,0,0,PC 17600,30.6958,,C
+795,0,3,"Dantcheff, Mr. Ristiu",male,25,0,0,349203,7.8958,,S
+796,0,2,"Otter, Mr. Richard",male,39,0,0,28213,13,,S
+797,1,1,"Leader, Dr. Alice (Farnham)",female,49,0,0,17465,25.9292,D17,S
+798,1,3,"Osman, Mrs. Mara",female,31,0,0,349244,8.6833,,S
+799,0,3,"Ibrahim Shawah, Mr. Yousseff",male,30,0,0,2685,7.2292,,C
+800,0,3,"Van Impe, Mrs. Jean Baptiste (Rosalie Paula Govaert)",female,30,1,1,345773,24.15,,S
+801,0,2,"Ponesell, Mr. Martin",male,34,0,0,250647,13,,S
+802,1,2,"Collyer, Mrs. Harvey (Charlotte Annie Tate)",female,31,1,1,C.A. 31921,26.25,,S
+803,1,1,"Carter, Master. William Thornton II",male,11,1,2,113760,120,B96 B98,S
+804,1,3,"Thomas, Master. Assad Alexander",male,0.42,0,1,2625,8.5167,,C
+805,1,3,"Hedman, Mr. Oskar Arvid",male,27,0,0,347089,6.975,,S
+806,0,3,"Johansson, Mr. Karl Johan",male,31,0,0,347063,7.775,,S
+807,0,1,"Andrews, Mr. Thomas Jr",male,39,0,0,112050,0,A36,S
+808,0,3,"Pettersson, Miss. Ellen Natalia",female,18,0,0,347087,7.775,,S
+809,0,2,"Meyer, Mr. August",male,39,0,0,248723,13,,S
+810,1,1,"Chambers, Mrs. Norman Campbell (Bertha Griggs)",female,33,1,0,113806,53.1,E8,S
+811,0,3,"Alexander, Mr. William",male,26,0,0,3474,7.8875,,S
+812,0,3,"Lester, Mr. James",male,39,0,0,A/4 48871,24.15,,S
+813,0,2,"Slemen, Mr. Richard James",male,35,0,0,28206,10.5,,S
+814,0,3,"Andersson, Miss. Ebba Iris Alfrida",female,6,4,2,347082,31.275,,S
+815,0,3,"Tomlin, Mr. Ernest Portage",male,30.5,0,0,364499,8.05,,S
+816,0,1,"Fry, Mr. Richard",male,,0,0,112058,0,B102,S
+817,0,3,"Heininen, Miss. Wendla Maria",female,23,0,0,STON/O2. 3101290,7.925,,S
+818,0,2,"Mallet, Mr. Albert",male,31,1,1,S.C./PARIS 2079,37.0042,,C
+819,0,3,"Holm, Mr. John Fredrik Alexander",male,43,0,0,C 7075,6.45,,S
+820,0,3,"Skoog, Master. Karl Thorsten",male,10,3,2,347088,27.9,,S
+821,1,1,"Hays, Mrs. Charles Melville (Clara Jennings Gregg)",female,52,1,1,12749,93.5,B69,S
+822,1,3,"Lulic, Mr. Nikola",male,27,0,0,315098,8.6625,,S
+823,0,1,"Reuchlin, Jonkheer. John George",male,38,0,0,19972,0,,S
+824,1,3,"Moor, Mrs. (Beila)",female,27,0,1,392096,12.475,E121,S
+825,0,3,"Panula, Master. Urho Abraham",male,2,4,1,3101295,39.6875,,S
+826,0,3,"Flynn, Mr. John",male,,0,0,368323,6.95,,Q
+827,0,3,"Lam, Mr. Len",male,,0,0,1601,56.4958,,S
+828,1,2,"Mallet, Master. Andre",male,1,0,2,S.C./PARIS 2079,37.0042,,C
+829,1,3,"McCormack, Mr. Thomas Joseph",male,,0,0,367228,7.75,,Q
+830,1,1,"Stone, Mrs. George Nelson (Martha Evelyn)",female,62,0,0,113572,80,B28,
+831,1,3,"Yasbeck, Mrs. Antoni (Selini Alexander)",female,15,1,0,2659,14.4542,,C
+832,1,2,"Richards, Master. George Sibley",male,0.83,1,1,29106,18.75,,S
+833,0,3,"Saad, Mr. Amin",male,,0,0,2671,7.2292,,C
+834,0,3,"Augustsson, Mr. Albert",male,23,0,0,347468,7.8542,,S
+835,0,3,"Allum, Mr. Owen George",male,18,0,0,2223,8.3,,S
+836,1,1,"Compton, Miss. Sara Rebecca",female,39,1,1,PC 17756,83.1583,E49,C
+837,0,3,"Pasic, Mr. Jakob",male,21,0,0,315097,8.6625,,S
+838,0,3,"Sirota, Mr. Maurice",male,,0,0,392092,8.05,,S
+839,1,3,"Chip, Mr. Chang",male,32,0,0,1601,56.4958,,S
+840,1,1,"Marechal, Mr. Pierre",male,,0,0,11774,29.7,C47,C
+841,0,3,"Alhomaki, Mr. Ilmari Rudolf",male,20,0,0,SOTON/O2 3101287,7.925,,S
+842,0,2,"Mudd, Mr. Thomas Charles",male,16,0,0,S.O./P.P. 3,10.5,,S
+843,1,1,"Serepeca, Miss. Augusta",female,30,0,0,113798,31,,C
+844,0,3,"Lemberopolous, Mr. Peter L",male,34.5,0,0,2683,6.4375,,C
+845,0,3,"Culumovic, Mr. Jeso",male,17,0,0,315090,8.6625,,S
+846,0,3,"Abbing, Mr. Anthony",male,42,0,0,C.A. 5547,7.55,,S
+847,0,3,"Sage, Mr. Douglas Bullen",male,,8,2,CA. 2343,69.55,,S
+848,0,3,"Markoff, Mr. Marin",male,35,0,0,349213,7.8958,,C
+849,0,2,"Harper, Rev. John",male,28,0,1,248727,33,,S
+850,1,1,"Goldenberg, Mrs. Samuel L (Edwiga Grabowska)",female,,1,0,17453,89.1042,C92,C
+851,0,3,"Andersson, Master. Sigvard Harald Elias",male,4,4,2,347082,31.275,,S
+852,0,3,"Svensson, Mr. Johan",male,74,0,0,347060,7.775,,S
+853,0,3,"Boulos, Miss. Nourelain",female,9,1,1,2678,15.2458,,C
+854,1,1,"Lines, Miss. Mary Conover",female,16,0,1,PC 17592,39.4,D28,S
+855,0,2,"Carter, Mrs. Ernest Courtenay (Lilian Hughes)",female,44,1,0,244252,26,,S
+856,1,3,"Aks, Mrs. Sam (Leah Rosen)",female,18,0,1,392091,9.35,,S
+857,1,1,"Wick, Mrs. George Dennick (Mary Hitchcock)",female,45,1,1,36928,164.8667,,S
+858,1,1,"Daly, Mr. Peter Denis ",male,51,0,0,113055,26.55,E17,S
+859,1,3,"Baclini, Mrs. Solomon (Latifa Qurban)",female,24,0,3,2666,19.2583,,C
+860,0,3,"Razi, Mr. Raihed",male,,0,0,2629,7.2292,,C
+861,0,3,"Hansen, Mr. Claus Peter",male,41,2,0,350026,14.1083,,S
+862,0,2,"Giles, Mr. Frederick Edward",male,21,1,0,28134,11.5,,S
+863,1,1,"Swift, Mrs. Frederick Joel (Margaret Welles Barron)",female,48,0,0,17466,25.9292,D17,S
+864,0,3,"Sage, Miss. Dorothy Edith ""Dolly""",female,,8,2,CA. 2343,69.55,,S
+865,0,2,"Gill, Mr. John William",male,24,0,0,233866,13,,S
+866,1,2,"Bystrom, Mrs. (Karolina)",female,42,0,0,236852,13,,S
+867,1,2,"Duran y More, Miss. Asuncion",female,27,1,0,SC/PARIS 2149,13.8583,,C
+868,0,1,"Roebling, Mr. Washington Augustus II",male,31,0,0,PC 17590,50.4958,A24,S
+869,0,3,"van Melkebeke, Mr. Philemon",male,,0,0,345777,9.5,,S
+870,1,3,"Johnson, Master. Harold Theodor",male,4,1,1,347742,11.1333,,S
+871,0,3,"Balkic, Mr. Cerin",male,26,0,0,349248,7.8958,,S
+872,1,1,"Beckwith, Mrs. Richard Leonard (Sallie Monypeny)",female,47,1,1,11751,52.5542,D35,S
+873,0,1,"Carlsson, Mr. Frans Olof",male,33,0,0,695,5,B51 B53 B55,S
+874,0,3,"Vander Cruyssen, Mr. Victor",male,47,0,0,345765,9,,S
+875,1,2,"Abelson, Mrs. Samuel (Hannah Wizosky)",female,28,1,0,P/PP 3381,24,,C
+876,1,3,"Najib, Miss. Adele Kiamie ""Jane""",female,15,0,0,2667,7.225,,C
+877,0,3,"Gustafsson, Mr. Alfred Ossian",male,20,0,0,7534,9.8458,,S
+878,0,3,"Petroff, Mr. Nedelio",male,19,0,0,349212,7.8958,,S
+879,0,3,"Laleff, Mr. Kristo",male,,0,0,349217,7.8958,,S
+880,1,1,"Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)",female,56,0,1,11767,83.1583,C50,C
+881,1,2,"Shelley, Mrs. William (Imanita Parrish Hall)",female,25,0,1,230433,26,,S
+882,0,3,"Markun, Mr. Johann",male,33,0,0,349257,7.8958,,S
+883,0,3,"Dahlberg, Miss. Gerda Ulrika",female,22,0,0,7552,10.5167,,S
+884,0,2,"Banfield, Mr. Frederick James",male,28,0,0,C.A./SOTON 34068,10.5,,S
+885,0,3,"Sutehall, Mr. Henry Jr",male,25,0,0,SOTON/OQ 392076,7.05,,S
+886,0,3,"Rice, Mrs. William (Margaret Norton)",female,39,0,5,382652,29.125,,Q
+887,0,2,"Montvila, Rev. Juozas",male,27,0,0,211536,13,,S
+888,1,1,"Graham, Miss. Margaret Edith",female,19,0,0,112053,30,B42,S
+889,0,3,"Johnston, Miss. Catherine Helen ""Carrie""",female,,1,2,W./C. 6607,23.45,,S
+890,1,1,"Behr, Mr. Karl Howell",male,26,0,0,111369,30,C148,C
+891,0,3,"Dooley, Mr. Patrick",male,32,0,0,370376,7.75,,Q
diff --git a/demo/titanic_survival/requirements.txt b/demo/titanic_survival/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2bfe97f7ef9b9d9e5e32aa07ba282bca0c6f5b29
--- /dev/null
+++ b/demo/titanic_survival/requirements.txt
@@ -0,0 +1,3 @@
+scikit-learn
+numpy
+pandas
\ No newline at end of file
diff --git a/demo/titanic_survival/run.ipynb b/demo/titanic_survival/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..598517abfb7656f4df6ed5808ac326624ce25818
--- /dev/null
+++ b/demo/titanic_survival/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: titanic_survival"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio scikit-learn numpy pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/titanic_survival/files/titanic.csv"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "\n", "import pandas as pd\n", "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.model_selection import train_test_split\n", "\n", "import gradio as gr\n", "\n", "current_dir = os.path.dirname(os.path.realpath(__file__))\n", "data = pd.read_csv(os.path.join(current_dir, \"files/titanic.csv\"))\n", "\n", "\n", "def encode_age(df):\n", " df.Age = df.Age.fillna(-0.5)\n", " bins = (-1, 0, 5, 12, 18, 25, 35, 60, 120)\n", " categories = pd.cut(df.Age, bins, labels=False)\n", " df.Age = categories\n", " return df\n", "\n", "\n", "def encode_fare(df):\n", " df.Fare = df.Fare.fillna(-0.5)\n", " bins = (-1, 0, 8, 15, 31, 1000)\n", " categories = pd.cut(df.Fare, bins, labels=False)\n", " df.Fare = categories\n", " return df\n", "\n", "\n", "def encode_df(df):\n", " df = encode_age(df)\n", " df = encode_fare(df)\n", " sex_mapping = {\"male\": 0, \"female\": 1}\n", " df = df.replace({\"Sex\": sex_mapping})\n", " embark_mapping = {\"S\": 1, \"C\": 2, \"Q\": 3}\n", " df = df.replace({\"Embarked\": embark_mapping})\n", " df.Embarked = df.Embarked.fillna(0)\n", " df[\"Company\"] = 0\n", " df.loc[(df[\"SibSp\"] > 0), \"Company\"] = 1\n", " df.loc[(df[\"Parch\"] > 0), \"Company\"] = 2\n", " df.loc[(df[\"SibSp\"] > 0) & (df[\"Parch\"] > 0), \"Company\"] = 3\n", " df = df[\n", " [\n", " \"PassengerId\",\n", " \"Pclass\",\n", " \"Sex\",\n", " \"Age\",\n", " \"Fare\",\n", " \"Embarked\",\n", " \"Company\",\n", " \"Survived\",\n", " ]\n", " ]\n", " return df\n", "\n", "\n", "train = encode_df(data)\n", "\n", "X_all = train.drop([\"Survived\", \"PassengerId\"], axis=1)\n", "y_all = train[\"Survived\"]\n", "\n", "num_test = 0.20\n", "X_train, X_test, y_train, y_test = train_test_split(\n", " X_all, y_all, test_size=num_test, random_state=23\n", ")\n", "\n", "clf = RandomForestClassifier()\n", "clf.fit(X_train, y_train)\n", "predictions = clf.predict(X_test)\n", "\n", "\n", "def predict_survival(passenger_class, is_male, age, company, fare, embark_point):\n", " if passenger_class is None or embark_point is None:\n", " return None\n", " df = pd.DataFrame.from_dict(\n", " {\n", " \"Pclass\": [passenger_class + 1],\n", " \"Sex\": [0 if is_male else 1],\n", " \"Age\": [age],\n", " \"Fare\": [fare],\n", " \"Embarked\": [embark_point + 1],\n", " \"Company\": [\n", " (1 if \"Sibling\" in company else 0) + (2 if \"Child\" in company else 0)\n", " ]\n", " }\n", " )\n", " df = encode_age(df)\n", " df = encode_fare(df)\n", " pred = clf.predict_proba(df)[0]\n", " return {\"Perishes\": float(pred[0]), \"Survives\": float(pred[1])}\n", "\n", "\n", "demo = gr.Interface(\n", " predict_survival,\n", " [\n", " gr.Dropdown([\"first\", \"second\", \"third\"], type=\"index\"),\n", " \"checkbox\",\n", " gr.Slider(0, 80, value=25),\n", " gr.CheckboxGroup([\"Sibling\", \"Child\"], label=\"Travelling with (select all)\"),\n", " gr.Number(value=20),\n", " gr.Radio([\"S\", \"C\", \"Q\"], type=\"index\"),\n", " ],\n", " \"label\",\n", " examples=[\n", " [\"first\", True, 30, [], 50, \"S\"],\n", " [\"second\", False, 40, [\"Sibling\", \"Child\"], 10, \"Q\"],\n", " [\"third\", True, 30, [\"Child\"], 20, \"S\"],\n", " ],\n", " live=True,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/titanic_survival/run.py b/demo/titanic_survival/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..80c2fc54fdff0bfbc9d31e7992946ab3343eb48c
--- /dev/null
+++ b/demo/titanic_survival/run.py
@@ -0,0 +1,112 @@
+import os
+
+import pandas as pd
+from sklearn.ensemble import RandomForestClassifier
+from sklearn.model_selection import train_test_split
+
+import gradio as gr
+
+current_dir = os.path.dirname(os.path.realpath(__file__))
+data = pd.read_csv(os.path.join(current_dir, "files/titanic.csv"))
+
+
+def encode_age(df):
+ df.Age = df.Age.fillna(-0.5)
+ bins = (-1, 0, 5, 12, 18, 25, 35, 60, 120)
+ categories = pd.cut(df.Age, bins, labels=False)
+ df.Age = categories
+ return df
+
+
+def encode_fare(df):
+ df.Fare = df.Fare.fillna(-0.5)
+ bins = (-1, 0, 8, 15, 31, 1000)
+ categories = pd.cut(df.Fare, bins, labels=False)
+ df.Fare = categories
+ return df
+
+
+def encode_df(df):
+ df = encode_age(df)
+ df = encode_fare(df)
+ sex_mapping = {"male": 0, "female": 1}
+ df = df.replace({"Sex": sex_mapping})
+ embark_mapping = {"S": 1, "C": 2, "Q": 3}
+ df = df.replace({"Embarked": embark_mapping})
+ df.Embarked = df.Embarked.fillna(0)
+ df["Company"] = 0
+ df.loc[(df["SibSp"] > 0), "Company"] = 1
+ df.loc[(df["Parch"] > 0), "Company"] = 2
+ df.loc[(df["SibSp"] > 0) & (df["Parch"] > 0), "Company"] = 3
+ df = df[
+ [
+ "PassengerId",
+ "Pclass",
+ "Sex",
+ "Age",
+ "Fare",
+ "Embarked",
+ "Company",
+ "Survived",
+ ]
+ ]
+ return df
+
+
+train = encode_df(data)
+
+X_all = train.drop(["Survived", "PassengerId"], axis=1)
+y_all = train["Survived"]
+
+num_test = 0.20
+X_train, X_test, y_train, y_test = train_test_split(
+ X_all, y_all, test_size=num_test, random_state=23
+)
+
+clf = RandomForestClassifier()
+clf.fit(X_train, y_train)
+predictions = clf.predict(X_test)
+
+
+def predict_survival(passenger_class, is_male, age, company, fare, embark_point):
+ if passenger_class is None or embark_point is None:
+ return None
+ df = pd.DataFrame.from_dict(
+ {
+ "Pclass": [passenger_class + 1],
+ "Sex": [0 if is_male else 1],
+ "Age": [age],
+ "Fare": [fare],
+ "Embarked": [embark_point + 1],
+ "Company": [
+ (1 if "Sibling" in company else 0) + (2 if "Child" in company else 0)
+ ]
+ }
+ )
+ df = encode_age(df)
+ df = encode_fare(df)
+ pred = clf.predict_proba(df)[0]
+ return {"Perishes": float(pred[0]), "Survives": float(pred[1])}
+
+
+demo = gr.Interface(
+ predict_survival,
+ [
+ gr.Dropdown(["first", "second", "third"], type="index"),
+ "checkbox",
+ gr.Slider(0, 80, value=25),
+ gr.CheckboxGroup(["Sibling", "Child"], label="Travelling with (select all)"),
+ gr.Number(value=20),
+ gr.Radio(["S", "C", "Q"], type="index"),
+ ],
+ "label",
+ examples=[
+ ["first", True, 30, [], 50, "S"],
+ ["second", False, 40, ["Sibling", "Child"], 10, "Q"],
+ ["third", True, 30, ["Child"], 20, "S"],
+ ],
+ live=True,
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/titanic_survival/screenshot.png b/demo/titanic_survival/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..20f698d009ede1303bc7410ed232317e954c5fe4
Binary files /dev/null and b/demo/titanic_survival/screenshot.png differ
diff --git a/demo/translation/DESCRIPTION.md b/demo/translation/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..38e29c745a792af4dc0e5cb821340af237823fe8
--- /dev/null
+++ b/demo/translation/DESCRIPTION.md
@@ -0,0 +1 @@
+This translation demo takes in the text, source and target languages, and returns the translation. It uses the Transformers library to set up the model and has a title, description, and example.
\ No newline at end of file
diff --git a/demo/translation/requirements.txt b/demo/translation/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..05ec8d9af8f237f0cfbefc987a2dfbbd8444a16a
--- /dev/null
+++ b/demo/translation/requirements.txt
@@ -0,0 +1,3 @@
+git+https://github.com/huggingface/transformers
+gradio
+torch
\ No newline at end of file
diff --git a/demo/translation/run.ipynb b/demo/translation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1cc852cdf87bb39e0c221159e85fe0bd908b397b
--- /dev/null
+++ b/demo/translation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: translation\n", "### This translation demo takes in the text, source and target languages, and returns the translation. It uses the Transformers library to set up the model and has a title, description, and example.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio git+https://github.com/huggingface/transformers gradio torch"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, pipeline\n", "import torch\n", "\n", "# this model was loaded from https://hf.co/models\n", "model = AutoModelForSeq2SeqLM.from_pretrained(\"facebook/nllb-200-distilled-600M\")\n", "tokenizer = AutoTokenizer.from_pretrained(\"facebook/nllb-200-distilled-600M\")\n", "device = 0 if torch.cuda.is_available() else -1\n", "LANGS = [\"ace_Arab\", \"eng_Latn\", \"fra_Latn\", \"spa_Latn\"]\n", "\n", "def translate(text, src_lang, tgt_lang):\n", " \"\"\"\n", " Translate the text from source lang to target lang\n", " \"\"\"\n", " translation_pipeline = pipeline(\"translation\", model=model, tokenizer=tokenizer, src_lang=src_lang, tgt_lang=tgt_lang, max_length=400, device=device)\n", " result = translation_pipeline(text)\n", " return result[0]['translation_text']\n", "\n", "demo = gr.Interface(\n", " fn=translate,\n", " inputs=[\n", " gr.components.Textbox(label=\"Text\"),\n", " gr.components.Dropdown(label=\"Source Language\", choices=LANGS),\n", " gr.components.Dropdown(label=\"Target Language\", choices=LANGS),\n", " ],\n", " outputs=[\"text\"],\n", " examples=[[\"Building a translation demo with Gradio is so easy!\", \"eng_Latn\", \"spa_Latn\"]],\n", " cache_examples=False,\n", " title=\"Translation Demo\",\n", " description=\"This demo is a simplified version of the original [NLLB-Translator](https://huggingface.co/spaces/Narrativaai/NLLB-Translator) space\"\n", ")\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/translation/run.py b/demo/translation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee792402c9cd5074ab4405a3affdceb3ba0cbef9
--- /dev/null
+++ b/demo/translation/run.py
@@ -0,0 +1,33 @@
+import gradio as gr
+from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, pipeline
+import torch
+
+# this model was loaded from https://hf.co/models
+model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M")
+tokenizer = AutoTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
+device = 0 if torch.cuda.is_available() else -1
+LANGS = ["ace_Arab", "eng_Latn", "fra_Latn", "spa_Latn"]
+
+def translate(text, src_lang, tgt_lang):
+ """
+ Translate the text from source lang to target lang
+ """
+ translation_pipeline = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=src_lang, tgt_lang=tgt_lang, max_length=400, device=device)
+ result = translation_pipeline(text)
+ return result[0]['translation_text']
+
+demo = gr.Interface(
+ fn=translate,
+ inputs=[
+ gr.components.Textbox(label="Text"),
+ gr.components.Dropdown(label="Source Language", choices=LANGS),
+ gr.components.Dropdown(label="Target Language", choices=LANGS),
+ ],
+ outputs=["text"],
+ examples=[["Building a translation demo with Gradio is so easy!", "eng_Latn", "spa_Latn"]],
+ cache_examples=False,
+ title="Translation Demo",
+ description="This demo is a simplified version of the original [NLLB-Translator](https://huggingface.co/spaces/Narrativaai/NLLB-Translator) space"
+)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/unified_demo_text_generation/requirements.txt b/demo/unified_demo_text_generation/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39dab0fdd98d55da5ce06ddf1dacbdbda14b1372
--- /dev/null
+++ b/demo/unified_demo_text_generation/requirements.txt
@@ -0,0 +1,2 @@
+torch
+transformers
\ No newline at end of file
diff --git a/demo/unified_demo_text_generation/run.ipynb b/demo/unified_demo_text_generation/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..4fcd378db070d8798b63114adb1a846dbed05ba1
--- /dev/null
+++ b/demo/unified_demo_text_generation/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: unified_demo_text_generation"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio torch transformers"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from transformers import pipeline\n", "\n", "generator = pipeline('text-generation', model = 'gpt2')\n", "\n", "def generate_text(text_prompt):\n", " response = generator(text_prompt, max_length = 30, num_return_sequences=5)\n", " return response[0]['generated_text']\n", "\n", "textbox = gr.Textbox()\n", "\n", "demo = gr.Interface(generate_text, textbox, textbox)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/unified_demo_text_generation/run.py b/demo/unified_demo_text_generation/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d86520108e36191b3144a541a9e00d414742950a
--- /dev/null
+++ b/demo/unified_demo_text_generation/run.py
@@ -0,0 +1,15 @@
+import gradio as gr
+from transformers import pipeline
+
+generator = pipeline('text-generation', model = 'gpt2')
+
+def generate_text(text_prompt):
+ response = generator(text_prompt, max_length = 30, num_return_sequences=5)
+ return response[0]['generated_text']
+
+textbox = gr.Textbox()
+
+demo = gr.Interface(generate_text, textbox, textbox)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/unispeech-speaker-verification/requirements.txt b/demo/unispeech-speaker-verification/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..baca89850c284e4dc6477356274e433f91c2308b
--- /dev/null
+++ b/demo/unispeech-speaker-verification/requirements.txt
@@ -0,0 +1,2 @@
+git+https://github.com/huggingface/transformers
+torchaudio
diff --git a/demo/unispeech-speaker-verification/run.ipynb b/demo/unispeech-speaker-verification/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..67bffef6529b31dcacdaff36091fb2397ae1d341
--- /dev/null
+++ b/demo/unispeech-speaker-verification/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: unispeech-speaker-verification"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio git+https://github.com/huggingface/transformers torchaudio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('samples')\n", "!wget -q -O samples/cate_blanch.mp3 https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/cate_blanch.mp3\n", "!wget -q -O samples/cate_blanch_2.mp3 https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/cate_blanch_2.mp3\n", "!wget -q -O samples/cate_blanch_3.mp3 https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/cate_blanch_3.mp3\n", "!wget -q -O samples/heath_ledger.mp3 https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/heath_ledger.mp3\n", "!wget -q -O samples/heath_ledger_2.mp3 https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/heath_ledger_2.mp3\n", "!wget -q -O samples/kirsten_dunst.wav https://github.com/gradio-app/gradio/raw/main/demo/unispeech-speaker-verification/samples/kirsten_dunst.wav"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import torch\n", "from torchaudio.sox_effects import apply_effects_file\n", "from transformers import AutoFeatureExtractor, AutoModelForAudioXVector\n", "\n", "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", "\n", "STYLE = \"\"\"\n", "
\n", "\"\"\"\n", "OUTPUT_OK = (\n", " STYLE\n", " + \"\"\"\n", "
\n", "
The speakers are \n", "
{:.1f}% \n", "
similar \n", "
Welcome, human! \n", "
(You must get at least 85% to be considered the same person) \n", "
\n", "\"\"\"\n", ")\n", "OUTPUT_FAIL = (\n", " STYLE\n", " + \"\"\"\n", "
\n", "
The speakers are \n", "
{:.1f}% \n", "
similar \n", "
You shall not pass! \n", "
(You must get at least 85% to be considered the same person) \n", "
\n", "\"\"\"\n", ")\n", "\n", "EFFECTS = [\n", " [\"remix\", \"-\"],\n", " [\"channels\", \"1\"],\n", " [\"rate\", \"16000\"],\n", " [\"gain\", \"-1.0\"],\n", " [\"silence\", \"1\", \"0.1\", \"0.1%\", \"-1\", \"0.1\", \"0.1%\"],\n", " [\"trim\", \"0\", \"10\"],\n", "]\n", "\n", "THRESHOLD = 0.85\n", "\n", "model_name = \"microsoft/unispeech-sat-base-plus-sv\"\n", "feature_extractor = AutoFeatureExtractor.from_pretrained(model_name)\n", "model = AutoModelForAudioXVector.from_pretrained(model_name).to(device)\n", "cosine_sim = torch.nn.CosineSimilarity(dim=-1)\n", "\n", "\n", "def similarity_fn(path1, path2):\n", " if not (path1 and path2):\n", " return '
ERROR: Please record audio for *both* speakers! '\n", " wav1, _ = apply_effects_file(path1, EFFECTS)\n", " wav2, _ = apply_effects_file(path2, EFFECTS)\n", " print(wav1.shape, wav2.shape)\n", "\n", " input1 = feature_extractor(wav1.squeeze(0), return_tensors=\"pt\", sampling_rate=16000).input_values.to(device)\n", " input2 = feature_extractor(wav2.squeeze(0), return_tensors=\"pt\", sampling_rate=16000).input_values.to(device)\n", "\n", " with torch.no_grad():\n", " emb1 = model(input1).embeddings\n", " emb2 = model(input2).embeddings\n", " emb1 = torch.nn.functional.normalize(emb1, dim=-1).cpu()\n", " emb2 = torch.nn.functional.normalize(emb2, dim=-1).cpu()\n", " similarity = cosine_sim(emb1, emb2).numpy()[0]\n", "\n", " if similarity >= THRESHOLD:\n", " output = OUTPUT_OK.format(similarity * 100)\n", " else:\n", " output = OUTPUT_FAIL.format(similarity * 100)\n", "\n", " return output\n", "\n", "\n", "inputs = [\n", " gr.Audio(sources=[\"microphone\"], type=\"filepath\", label=\"Speaker #1\"),\n", " gr.Audio(sources=[\"microphone\"], type=\"filepath\", label=\"Speaker #2\"),\n", "]\n", "output = gr.HTML(label=\"\")\n", "\n", "\n", "description = (\n", " \"This demo will compare two speech samples and determine if they are from the same speaker. \"\n", " \"Try it with your own voice!\"\n", ")\n", "article = (\n", " \"
\"\n", " \"\ud83c\udf99\ufe0f Learn more about UniSpeech-SAT | \"\n", " \"\ud83d\udcda UniSpeech-SAT paper | \"\n", " \"\ud83d\udcda X-Vector paper \"\n", " \"
\"\n", ")\n", "examples = [\n", " [\"samples/cate_blanch.mp3\", \"samples/cate_blanch_2.mp3\"],\n", " [\"samples/cate_blanch.mp3\", \"samples/cate_blanch_3.mp3\"],\n", " [\"samples/cate_blanch_2.mp3\", \"samples/cate_blanch_3.mp3\"],\n", " [\"samples/heath_ledger.mp3\", \"samples/heath_ledger_2.mp3\"],\n", " [\"samples/cate_blanch.mp3\", \"samples/kirsten_dunst.wav\"],\n", "]\n", "\n", "demo = gr.Interface(\n", " fn=similarity_fn,\n", " inputs=inputs,\n", " outputs=output,\n", " title=\"Voice Authentication with UniSpeech-SAT + X-Vectors\",\n", " description=description,\n", " article=article,\n", " allow_flagging=\"never\",\n", " live=False,\n", " examples=examples,\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n", "\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/unispeech-speaker-verification/run.py b/demo/unispeech-speaker-verification/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..206ac25a3dba2d9f2ea400e5b8193633c6332a72
--- /dev/null
+++ b/demo/unispeech-speaker-verification/run.py
@@ -0,0 +1,118 @@
+import gradio as gr
+import torch
+from torchaudio.sox_effects import apply_effects_file
+from transformers import AutoFeatureExtractor, AutoModelForAudioXVector
+
+device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+
+STYLE = """
+
+"""
+OUTPUT_OK = (
+ STYLE
+ + """
+
+
The speakers are
+
{:.1f}%
+
similar
+
Welcome, human!
+
(You must get at least 85% to be considered the same person)
+
+"""
+)
+OUTPUT_FAIL = (
+ STYLE
+ + """
+
+
The speakers are
+
{:.1f}%
+
similar
+
You shall not pass!
+
(You must get at least 85% to be considered the same person)
+
+"""
+)
+
+EFFECTS = [
+ ["remix", "-"],
+ ["channels", "1"],
+ ["rate", "16000"],
+ ["gain", "-1.0"],
+ ["silence", "1", "0.1", "0.1%", "-1", "0.1", "0.1%"],
+ ["trim", "0", "10"],
+]
+
+THRESHOLD = 0.85
+
+model_name = "microsoft/unispeech-sat-base-plus-sv"
+feature_extractor = AutoFeatureExtractor.from_pretrained(model_name)
+model = AutoModelForAudioXVector.from_pretrained(model_name).to(device)
+cosine_sim = torch.nn.CosineSimilarity(dim=-1)
+
+
+def similarity_fn(path1, path2):
+ if not (path1 and path2):
+ return '
ERROR: Please record audio for *both* speakers! '
+ wav1, _ = apply_effects_file(path1, EFFECTS)
+ wav2, _ = apply_effects_file(path2, EFFECTS)
+ print(wav1.shape, wav2.shape)
+
+ input1 = feature_extractor(wav1.squeeze(0), return_tensors="pt", sampling_rate=16000).input_values.to(device)
+ input2 = feature_extractor(wav2.squeeze(0), return_tensors="pt", sampling_rate=16000).input_values.to(device)
+
+ with torch.no_grad():
+ emb1 = model(input1).embeddings
+ emb2 = model(input2).embeddings
+ emb1 = torch.nn.functional.normalize(emb1, dim=-1).cpu()
+ emb2 = torch.nn.functional.normalize(emb2, dim=-1).cpu()
+ similarity = cosine_sim(emb1, emb2).numpy()[0]
+
+ if similarity >= THRESHOLD:
+ output = OUTPUT_OK.format(similarity * 100)
+ else:
+ output = OUTPUT_FAIL.format(similarity * 100)
+
+ return output
+
+
+inputs = [
+ gr.Audio(sources=["microphone"], type="filepath", label="Speaker #1"),
+ gr.Audio(sources=["microphone"], type="filepath", label="Speaker #2"),
+]
+output = gr.HTML(label="")
+
+
+description = (
+ "This demo will compare two speech samples and determine if they are from the same speaker. "
+ "Try it with your own voice!"
+)
+article = (
+ "
"
+ "🎙️ Learn more about UniSpeech-SAT | "
+ "📚 UniSpeech-SAT paper | "
+ "📚 X-Vector paper "
+ "
"
+)
+examples = [
+ ["samples/cate_blanch.mp3", "samples/cate_blanch_2.mp3"],
+ ["samples/cate_blanch.mp3", "samples/cate_blanch_3.mp3"],
+ ["samples/cate_blanch_2.mp3", "samples/cate_blanch_3.mp3"],
+ ["samples/heath_ledger.mp3", "samples/heath_ledger_2.mp3"],
+ ["samples/cate_blanch.mp3", "samples/kirsten_dunst.wav"],
+]
+
+demo = gr.Interface(
+ fn=similarity_fn,
+ inputs=inputs,
+ outputs=output,
+ title="Voice Authentication with UniSpeech-SAT + X-Vectors",
+ description=description,
+ article=article,
+ allow_flagging="never",
+ live=False,
+ examples=examples,
+)
+
+if __name__ == "__main__":
+ demo.launch()
+
diff --git a/demo/unispeech-speaker-verification/samples/cate_blanch.mp3 b/demo/unispeech-speaker-verification/samples/cate_blanch.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..4beee74653732ae01f47089374954d77666d69bc
Binary files /dev/null and b/demo/unispeech-speaker-verification/samples/cate_blanch.mp3 differ
diff --git a/demo/unispeech-speaker-verification/samples/cate_blanch_2.mp3 b/demo/unispeech-speaker-verification/samples/cate_blanch_2.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..1acc2128c9d480adb4a8618578453041c6afaf6b
Binary files /dev/null and b/demo/unispeech-speaker-verification/samples/cate_blanch_2.mp3 differ
diff --git a/demo/unispeech-speaker-verification/samples/cate_blanch_3.mp3 b/demo/unispeech-speaker-verification/samples/cate_blanch_3.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..fa0a9f7663aa26173f43a7b416df38a8cedcb79c
Binary files /dev/null and b/demo/unispeech-speaker-verification/samples/cate_blanch_3.mp3 differ
diff --git a/demo/unispeech-speaker-verification/samples/heath_ledger.mp3 b/demo/unispeech-speaker-verification/samples/heath_ledger.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..eb63071e1b3da9fcd072ec2801eb6165c49b0cb3
Binary files /dev/null and b/demo/unispeech-speaker-verification/samples/heath_ledger.mp3 differ
diff --git a/demo/unispeech-speaker-verification/samples/heath_ledger_2.mp3 b/demo/unispeech-speaker-verification/samples/heath_ledger_2.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..d74f1ec3f08cc168b25184e75eeb65dc0550c1ac
Binary files /dev/null and b/demo/unispeech-speaker-verification/samples/heath_ledger_2.mp3 differ
diff --git a/demo/unispeech-speaker-verification/samples/kirsten_dunst.wav b/demo/unispeech-speaker-verification/samples/kirsten_dunst.wav
new file mode 100644
index 0000000000000000000000000000000000000000..62db17ffcacd2d90a18833ca17f2947cc140b300
--- /dev/null
+++ b/demo/unispeech-speaker-verification/samples/kirsten_dunst.wav
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7ab77b27959f0f43126c94c4de3baa23b3f92c3c2e26ba322af2d6cd688f3233
+size 1287798
diff --git a/demo/upload_button/DESCRIPTION.md b/demo/upload_button/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..a070ed152cb42b3634309c1ab460d2ddc2be321a
--- /dev/null
+++ b/demo/upload_button/DESCRIPTION.md
@@ -0,0 +1 @@
+A simple demo showcasing the upload button used with its `upload` event trigger.
\ No newline at end of file
diff --git a/demo/upload_button/run.ipynb b/demo/upload_button/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d8cdaea6ac8407923d2aa70d4c66460630254f58
--- /dev/null
+++ b/demo/upload_button/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: upload_button\n", "### A simple demo showcasing the upload button used with its `upload` event trigger.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def upload_file(files):\n", " file_paths = [file.name for file in files]\n", " return file_paths\n", "\n", "with gr.Blocks() as demo:\n", " file_output = gr.File()\n", " upload_button = gr.UploadButton(\"Click to Upload a File\", file_types=[\"image\", \"video\"], file_count=\"multiple\")\n", " upload_button.upload(upload_file, upload_button, file_output)\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/upload_button/run.py b/demo/upload_button/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e40d2a64a64ee37b4caf36d8b98133cfb701f25
--- /dev/null
+++ b/demo/upload_button/run.py
@@ -0,0 +1,12 @@
+import gradio as gr
+
+def upload_file(files):
+ file_paths = [file.name for file in files]
+ return file_paths
+
+with gr.Blocks() as demo:
+ file_output = gr.File()
+ upload_button = gr.UploadButton("Click to Upload a File", file_types=["image", "video"], file_count="multiple")
+ upload_button.upload(upload_file, upload_button, file_output)
+
+demo.launch()
diff --git a/demo/upload_button_component_events/run.ipynb b/demo/upload_button_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..dcb30e4abec9780c8f740ad6d2162c220f42bc2b
--- /dev/null
+++ b/demo/upload_button_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: upload_button_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " \n", " with gr.Row():\n", " with gr.Column():\n", " upload_btn = gr.UploadButton(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(label=\"Upload Single File Output\", file_count=\"single\")\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " output_click_1 = gr.Number(label=\"# Click Upload Single File Output\", value=0)\n", " upload_btn.upload(lambda s,n: (s, n + 1), [upload_btn, num_load_btn_1], [output_file_1, num_load_btn_1])\n", " upload_btn.click(lambda n: (n + 1), output_click_1, [output_click_1])\n", " with gr.Row():\n", " with gr.Column():\n", " upload_btn_multiple = gr.UploadButton(label=\"Upload Multiple Files\", file_count=\"multiple\")\n", " with gr.Column():\n", " output_file_2 = gr.File(label=\"Upload Multiple Files Output\", file_count=\"multiple\")\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " output_click_2 = gr.Number(label=\"# Click Upload Multiple Files Output\", value=0)\n", " upload_btn_multiple.upload(lambda s,n: (s, n + 1), [upload_btn_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])\n", " upload_btn_multiple.click(lambda n: (n + 1), output_click_2, [output_click_2])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/upload_button_component_events/run.py b/demo/upload_button_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..063a2e5c2393659458d22724a57e13c68f2e40a9
--- /dev/null
+++ b/demo/upload_button_component_events/run.py
@@ -0,0 +1,26 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+
+ with gr.Row():
+ with gr.Column():
+ upload_btn = gr.UploadButton(label="Upload Single File", file_count="single")
+ with gr.Column():
+ output_file_1 = gr.File(label="Upload Single File Output", file_count="single")
+ num_load_btn_1 = gr.Number(label="# Load Upload Single File", value=0)
+ output_click_1 = gr.Number(label="# Click Upload Single File Output", value=0)
+ upload_btn.upload(lambda s,n: (s, n + 1), [upload_btn, num_load_btn_1], [output_file_1, num_load_btn_1])
+ upload_btn.click(lambda n: (n + 1), output_click_1, [output_click_1])
+ with gr.Row():
+ with gr.Column():
+ upload_btn_multiple = gr.UploadButton(label="Upload Multiple Files", file_count="multiple")
+ with gr.Column():
+ output_file_2 = gr.File(label="Upload Multiple Files Output", file_count="multiple")
+ num_load_btn_2 = gr.Number(label="# Load Upload Multiple Files", value=0)
+ output_click_2 = gr.Number(label="# Click Upload Multiple Files Output", value=0)
+ upload_btn_multiple.upload(lambda s,n: (s, n + 1), [upload_btn_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])
+ upload_btn_multiple.click(lambda n: (n + 1), output_click_2, [output_click_2])
+
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/uploadbutton_component/run.ipynb b/demo/uploadbutton_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..55dee4d996783d943dfc8a1de37315c611016c60
--- /dev/null
+++ b/demo/uploadbutton_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: uploadbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def upload_file(files):\n", " file_paths = [file.name for file in files]\n", " return file_paths\n", "\n", "with gr.Blocks() as demo:\n", " file_output = gr.File()\n", " upload_button = gr.UploadButton(\"Click to Upload an Image or Video File\", file_types=[\"image\", \"video\"], file_count=\"multiple\")\n", " upload_button.upload(upload_file, upload_button, file_output)\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/uploadbutton_component/run.py b/demo/uploadbutton_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..281ef37c013788abf664b2b7abb225da47ad19c3
--- /dev/null
+++ b/demo/uploadbutton_component/run.py
@@ -0,0 +1,12 @@
+import gradio as gr
+
+def upload_file(files):
+ file_paths = [file.name for file in files]
+ return file_paths
+
+with gr.Blocks() as demo:
+ file_output = gr.File()
+ upload_button = gr.UploadButton("Click to Upload an Image or Video File", file_types=["image", "video"], file_count="multiple")
+ upload_button.upload(upload_file, upload_button, file_output)
+
+demo.launch()
\ No newline at end of file
diff --git a/demo/variable_outputs/run.ipynb b/demo/variable_outputs/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..7ebbe92b2ba6a241e8fe0795780788e15df304a9
--- /dev/null
+++ b/demo/variable_outputs/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: variable_outputs"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "max_textboxes = 10\n", "\n", "def variable_outputs(k):\n", " k = int(k)\n", " return [gr.Textbox(visible=True)]*k + [gr.Textbox(visible=False)]*(max_textboxes-k)\n", "\n", "with gr.Blocks() as demo:\n", " s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label=\"How many textboxes to show:\")\n", " textboxes = []\n", " for i in range(max_textboxes):\n", " t = gr.Textbox(f\"Textbox {i}\")\n", " textboxes.append(t)\n", "\n", " s.change(variable_outputs, s, textboxes)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/variable_outputs/run.py b/demo/variable_outputs/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c893faf60aa253c127c28635100021528cf99a72
--- /dev/null
+++ b/demo/variable_outputs/run.py
@@ -0,0 +1,19 @@
+import gradio as gr
+
+max_textboxes = 10
+
+def variable_outputs(k):
+ k = int(k)
+ return [gr.Textbox(visible=True)]*k + [gr.Textbox(visible=False)]*(max_textboxes-k)
+
+with gr.Blocks() as demo:
+ s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label="How many textboxes to show:")
+ textboxes = []
+ for i in range(max_textboxes):
+ t = gr.Textbox(f"Textbox {i}")
+ textboxes.append(t)
+
+ s.change(variable_outputs, s, textboxes)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/video_component/files/a.mp4 b/demo/video_component/files/a.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..95a61f6b4a753497d97f51c6a8f18727cef7d628
Binary files /dev/null and b/demo/video_component/files/a.mp4 differ
diff --git a/demo/video_component/files/b.mp4 b/demo/video_component/files/b.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..7b2d7c723ea53ce763eb49f551bd955858850673
Binary files /dev/null and b/demo/video_component/files/b.mp4 differ
diff --git a/demo/video_component/files/world.mp4 b/demo/video_component/files/world.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..9bce44c33e275d6107240a1101032a7835fd8eed
--- /dev/null
+++ b/demo/video_component/files/world.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:71944d7430c461f0cd6e7fd10cee7eb72786352a3678fc7bc0ae3d410f72aece
+size 1570024
diff --git a/demo/video_component/run.ipynb b/demo/video_component/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..4387ae475020ca1e702948345ee0ebd37d640315
--- /dev/null
+++ b/demo/video_component/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: video_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_component/files/a.mp4\n", "!wget -q -O files/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_component/files/b.mp4\n", "!wget -q -O files/world.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_component/files/world.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "a = os.path.join(os.path.abspath(''), \"files/world.mp4\") # Video\n", "b = os.path.join(os.path.abspath(''), \"files/a.mp4\") # Video\n", "c = os.path.join(os.path.abspath(''), \"files/b.mp4\") # Video\n", "\n", "\n", "demo = gr.Interface(\n", " fn=lambda x: x,\n", " inputs=gr.Video(),\n", " outputs=gr.Video(),\n", " examples=[\n", " [a],\n", " [b],\n", " [c],\n", " ],\n", " cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/video_component/run.py b/demo/video_component/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..d522aa49cdcff3e53341f0b5d8d7122ad90779ba
--- /dev/null
+++ b/demo/video_component/run.py
@@ -0,0 +1,23 @@
+import gradio as gr
+import os
+
+
+a = os.path.join(os.path.dirname(__file__), "files/world.mp4") # Video
+b = os.path.join(os.path.dirname(__file__), "files/a.mp4") # Video
+c = os.path.join(os.path.dirname(__file__), "files/b.mp4") # Video
+
+
+demo = gr.Interface(
+ fn=lambda x: x,
+ inputs=gr.Video(),
+ outputs=gr.Video(),
+ examples=[
+ [a],
+ [b],
+ [c],
+ ],
+ cache_examples=True
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/video_component_events/run.ipynb b/demo/video_component_events/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..86d7a580f73b906ae5ff77dcaf74a7846121f8aa
--- /dev/null
+++ b/demo/video_component_events/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: video_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " input_video = gr.Video(label=\"Input Video\")\n", " with gr.Column():\n", " output_video = gr.Video(label=\"Output Video\")\n", " with gr.Column():\n", " num_change = gr.Number(label=\"# Change Events\", value=0)\n", " num_load = gr.Number(label=\"# Upload Events\", value=0)\n", " num_play = gr.Number(label=\"# Play Events\", value=0)\n", " num_pause = gr.Number(label=\"# Pause Events\", value=0)\n", " input_video.upload(lambda s, n: (s, n + 1), [input_video, num_load], [output_video, num_load])\n", " input_video.change(lambda n: n + 1, num_change, num_change)\n", " input_video.play(lambda n: n + 1, num_play, num_play)\n", " input_video.pause(lambda n: n + 1, num_pause, num_pause)\n", " input_video.change(lambda n: n + 1, num_change, num_change)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/video_component_events/run.py b/demo/video_component_events/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..046a7f4966bf6b6475fe69907b6903490f461e66
--- /dev/null
+++ b/demo/video_component_events/run.py
@@ -0,0 +1,21 @@
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ input_video = gr.Video(label="Input Video")
+ with gr.Column():
+ output_video = gr.Video(label="Output Video")
+ with gr.Column():
+ num_change = gr.Number(label="# Change Events", value=0)
+ num_load = gr.Number(label="# Upload Events", value=0)
+ num_play = gr.Number(label="# Play Events", value=0)
+ num_pause = gr.Number(label="# Pause Events", value=0)
+ input_video.upload(lambda s, n: (s, n + 1), [input_video, num_load], [output_video, num_load])
+ input_video.change(lambda n: n + 1, num_change, num_change)
+ input_video.play(lambda n: n + 1, num_play, num_play)
+ input_video.pause(lambda n: n + 1, num_pause, num_pause)
+ input_video.change(lambda n: n + 1, num_change, num_change)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/video_identity/run.ipynb b/demo/video_identity/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3ed71cc4b12c4fa3335e01a4120a71fcbed97d8f
--- /dev/null
+++ b/demo/video_identity/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: video_identity"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('video')\n", "!wget -q -O video/video_sample.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_identity/video/video_sample.mp4"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def video_identity(video):\n", " return video\n", "\n", "\n", "demo = gr.Interface(video_identity, \n", " gr.Video(), \n", " \"playable_video\", \n", " examples=[\n", " os.path.join(os.path.abspath(''), \n", " \"video/video_sample.mp4\")], \n", " cache_examples=True)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/video_identity/run.py b/demo/video_identity/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..206f47c7c2f6fc19afde9dceda5f67fc8ce0d4df
--- /dev/null
+++ b/demo/video_identity/run.py
@@ -0,0 +1,18 @@
+import gradio as gr
+import os
+
+
+def video_identity(video):
+ return video
+
+
+demo = gr.Interface(video_identity,
+ gr.Video(),
+ "playable_video",
+ examples=[
+ os.path.join(os.path.dirname(__file__),
+ "video/video_sample.mp4")],
+ cache_examples=True)
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/video_identity/screenshot.png b/demo/video_identity/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..443948af088a7f55d2742accf56e86671dde377b
Binary files /dev/null and b/demo/video_identity/screenshot.png differ
diff --git a/demo/video_identity/video/video_sample.mp4 b/demo/video_identity/video/video_sample.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..7b2d7c723ea53ce763eb49f551bd955858850673
Binary files /dev/null and b/demo/video_identity/video/video_sample.mp4 differ
diff --git a/demo/video_identity_2/run.ipynb b/demo/video_identity_2/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..b2333281ba36cb11f46415f6489d13a4195151a7
--- /dev/null
+++ b/demo/video_identity_2/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: video_identity_2"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def video_identity(video):\n", " return video\n", "\n", "\n", "demo = gr.Interface(video_identity, \n", " gr.Video(), \n", " \"playable_video\", \n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/video_identity_2/run.py b/demo/video_identity_2/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..095a1f8eed61a6a8a8d11f1298afe6b255a49a2e
--- /dev/null
+++ b/demo/video_identity_2/run.py
@@ -0,0 +1,13 @@
+import gradio as gr
+
+def video_identity(video):
+ return video
+
+
+demo = gr.Interface(video_identity,
+ gr.Video(),
+ "playable_video",
+ )
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/video_subtitle/files/a.mp4 b/demo/video_subtitle/files/a.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..95a61f6b4a753497d97f51c6a8f18727cef7d628
Binary files /dev/null and b/demo/video_subtitle/files/a.mp4 differ
diff --git a/demo/video_subtitle/files/b.mp4 b/demo/video_subtitle/files/b.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..7b2d7c723ea53ce763eb49f551bd955858850673
Binary files /dev/null and b/demo/video_subtitle/files/b.mp4 differ
diff --git a/demo/video_subtitle/files/s1.srt b/demo/video_subtitle/files/s1.srt
new file mode 100644
index 0000000000000000000000000000000000000000..c9d385451655afd969b6c41652fb4f55cd3b4c3d
--- /dev/null
+++ b/demo/video_subtitle/files/s1.srt
@@ -0,0 +1,29 @@
+0
+0:00:00.000 --> 0:00:00.500
+A
+
+1
+0:00:00.500 --> 0:00:01.000
+B
+
+2
+0:00:01.000 --> 0:00:01.500
+C
+
+3
+0:00:01.500 --> 0:00:02.000
+D
+
+4
+0:00:02.000 --> 0:00:02.500
+E
+
+5
+0:00:02.500 --> 0:00:03.000
+F
+
+6
+0:00:03.000 --> 0:00:10.000
+This is multiple line test.
+Why did the tomato turn red? Because it saw the salad dressing.
+In Africa, every 60 seconds a minute passes
diff --git a/demo/video_subtitle/files/s2.vtt b/demo/video_subtitle/files/s2.vtt
new file mode 100644
index 0000000000000000000000000000000000000000..4fa187828b70acbc737b4e1d23d7cb66d793a0c1
--- /dev/null
+++ b/demo/video_subtitle/files/s2.vtt
@@ -0,0 +1,16 @@
+WEBVTT
+
+0:00:00.000 --> 0:00:00.500
+一
+
+0:00:00.500 --> 0:00:01.000
+二
+
+0:00:01.000 --> 0:00:01.500
+三
+
+0:00:01.500 --> 0:00:02.000
+四
+
+0:00:02.000 --> 0:00:02.500
+中文測試
diff --git a/demo/video_subtitle/run.ipynb b/demo/video_subtitle/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..5c626ab9902477805ef9a948565cc17c74ae0caf
--- /dev/null
+++ b/demo/video_subtitle/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: video_subtitle"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_subtitle/files/a.mp4\n", "!wget -q -O files/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/video_subtitle/files/b.mp4\n", "!wget -q -O files/s1.srt https://github.com/gradio-app/gradio/raw/main/demo/video_subtitle/files/s1.srt\n", "!wget -q -O files/s2.vtt https://github.com/gradio-app/gradio/raw/main/demo/video_subtitle/files/s2.vtt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "a = os.path.join(os.path.abspath(''), \"files/a.mp4\") # Video\n", "b = os.path.join(os.path.abspath(''), \"files/b.mp4\") # Video\n", "s1 = os.path.join(os.path.abspath(''), \"files/s1.srt\") # Subtitle\n", "s2 = os.path.join(os.path.abspath(''), \"files/s2.vtt\") # Subtitle\n", "\n", "\n", "def video_demo(video, subtitle=None):\n", " if subtitle is None:\n", " return video\n", "\n", " return [video, subtitle.name]\n", "\n", "\n", "demo = gr.Interface(\n", " fn=video_demo,\n", " inputs=[\n", " gr.Video(label=\"In\", interactive=True),\n", " gr.File(label=\"Subtitle\", file_types=[\".srt\", \".vtt\"]),\n", " ],\n", " outputs=gr.Video(label=\"Out\"),\n", " examples=[\n", " [a, s1],\n", " [b, s2],\n", " [a, None],\n", " ],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/video_subtitle/run.py b/demo/video_subtitle/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..99e4a522a93ebc24bb2c84a7467bb256c4909c0a
--- /dev/null
+++ b/demo/video_subtitle/run.py
@@ -0,0 +1,32 @@
+import gradio as gr
+import os
+
+a = os.path.join(os.path.dirname(__file__), "files/a.mp4") # Video
+b = os.path.join(os.path.dirname(__file__), "files/b.mp4") # Video
+s1 = os.path.join(os.path.dirname(__file__), "files/s1.srt") # Subtitle
+s2 = os.path.join(os.path.dirname(__file__), "files/s2.vtt") # Subtitle
+
+
+def video_demo(video, subtitle=None):
+ if subtitle is None:
+ return video
+
+ return [video, subtitle.name]
+
+
+demo = gr.Interface(
+ fn=video_demo,
+ inputs=[
+ gr.Video(label="In", interactive=True),
+ gr.File(label="Subtitle", file_types=[".srt", ".vtt"]),
+ ],
+ outputs=gr.Video(label="Out"),
+ examples=[
+ [a, s1],
+ [b, s2],
+ [a, None],
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/waveform/run.ipynb b/demo/waveform/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..123780c6ddaa02b15f0a716fc30d6c296cdb86e3
--- /dev/null
+++ b/demo/waveform/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: waveform"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "\n", "\n", "COLORS = [\n", " [\"#ff0000\", \"#00ff00\"],\n", " [\"#00ff00\", \"#0000ff\"],\n", " [\"#0000ff\", \"#ff0000\"],\n", "] \n", "\n", "def audio_waveform(audio, image):\n", " return (\n", " audio,\n", " gr.make_waveform(audio),\n", " gr.make_waveform(audio, animate=True),\n", " gr.make_waveform(audio, bg_image=image, bars_color=random.choice(COLORS)),\n", " )\n", "\n", "\n", "gr.Interface(\n", " audio_waveform,\n", " inputs=[gr.Audio(), gr.Image(type=\"filepath\")],\n", " outputs=[\n", " gr.Audio(),\n", " gr.Video(),\n", " gr.Video(),\n", " gr.Video(),\n", " ],\n", ").launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/waveform/run.py b/demo/waveform/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..f86ed52d8eb60538b75c9f70f273b2585c9c382a
--- /dev/null
+++ b/demo/waveform/run.py
@@ -0,0 +1,29 @@
+import gradio as gr
+import random
+
+
+COLORS = [
+ ["#ff0000", "#00ff00"],
+ ["#00ff00", "#0000ff"],
+ ["#0000ff", "#ff0000"],
+]
+
+def audio_waveform(audio, image):
+ return (
+ audio,
+ gr.make_waveform(audio),
+ gr.make_waveform(audio, animate=True),
+ gr.make_waveform(audio, bg_image=image, bars_color=random.choice(COLORS)),
+ )
+
+
+gr.Interface(
+ audio_waveform,
+ inputs=[gr.Audio(), gr.Image(type="filepath")],
+ outputs=[
+ gr.Audio(),
+ gr.Video(),
+ gr.Video(),
+ gr.Video(),
+ ],
+).launch()
diff --git a/demo/webcam/run.ipynb b/demo/webcam/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..28fca1a54b4a2dcc2f858ddd6c0021b4bd49bc36
--- /dev/null
+++ b/demo/webcam/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: webcam"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["\n", "import gradio as gr\n", "\n", "\n", "def snap(image, video):\n", " return [image, video]\n", "\n", "\n", "demo = gr.Interface(\n", " snap,\n", " [gr.Image(sources=[\"webcam\"]), gr.Video(sources=[\"webcam\"])],\n", " [\"image\", \"video\"],\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/webcam/run.py b/demo/webcam/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..c12026ee6cdc5b7173003642fcceff1b2e185ef8
--- /dev/null
+++ b/demo/webcam/run.py
@@ -0,0 +1,16 @@
+
+import gradio as gr
+
+
+def snap(image, video):
+ return [image, video]
+
+
+demo = gr.Interface(
+ snap,
+ [gr.Image(sources=["webcam"]), gr.Video(sources=["webcam"])],
+ ["image", "video"],
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/webcam/screenshot.png b/demo/webcam/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..33d74a9afb013c6cc5b336d4c7017bbb67a7559b
Binary files /dev/null and b/demo/webcam/screenshot.png differ
diff --git a/demo/white_noise_vid_not_playable/requirements.txt b/demo/white_noise_vid_not_playable/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1db7aea116e2b2026e2b660df58af81d997599e6
--- /dev/null
+++ b/demo/white_noise_vid_not_playable/requirements.txt
@@ -0,0 +1 @@
+opencv-python
\ No newline at end of file
diff --git a/demo/white_noise_vid_not_playable/run.ipynb b/demo/white_noise_vid_not_playable/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8a76dde6ced72e1b8f778f7a1645fa8d4ce67085
--- /dev/null
+++ b/demo/white_noise_vid_not_playable/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: white_noise_vid_not_playable"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio opencv-python"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import cv2\n", "import gradio as gr\n", "import numpy as np\n", "\n", "\n", "def gif_maker():\n", " img_array = []\n", " height, width = 50, 50\n", " for i in range(30):\n", " img_array.append(np.random.randint(0, 255, size=(height, width, 3)).astype(np.uint8))\n", " output_file = \"test.mp4\"\n", " out = cv2.VideoWriter(output_file, cv2.VideoWriter_fourcc(*'mp4v'), 15, (height, width))\n", " for i in range(len(img_array)):\n", " out.write(img_array[i])\n", " out.release()\n", " return output_file, output_file\n", "\n", "\n", "demo = gr.Interface(gif_maker, inputs=None, outputs=[gr.Video(), gr.File()])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/white_noise_vid_not_playable/run.py b/demo/white_noise_vid_not_playable/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca3dfaa0752e6451c18bcd2b6e97c427d74b2e8a
--- /dev/null
+++ b/demo/white_noise_vid_not_playable/run.py
@@ -0,0 +1,22 @@
+import cv2
+import gradio as gr
+import numpy as np
+
+
+def gif_maker():
+ img_array = []
+ height, width = 50, 50
+ for i in range(30):
+ img_array.append(np.random.randint(0, 255, size=(height, width, 3)).astype(np.uint8))
+ output_file = "test.mp4"
+ out = cv2.VideoWriter(output_file, cv2.VideoWriter_fourcc(*'mp4v'), 15, (height, width))
+ for i in range(len(img_array)):
+ out.write(img_array[i])
+ out.release()
+ return output_file, output_file
+
+
+demo = gr.Interface(gif_maker, inputs=None, outputs=[gr.Video(), gr.File()])
+
+if __name__ == "__main__":
+ demo.launch()
\ No newline at end of file
diff --git a/demo/xgboost-income-prediction-with-explainability/DESCRIPTION.md b/demo/xgboost-income-prediction-with-explainability/DESCRIPTION.md
new file mode 100644
index 0000000000000000000000000000000000000000..cd69ef8e1e3e3ab360b84e76c9cc222a74d4246f
--- /dev/null
+++ b/demo/xgboost-income-prediction-with-explainability/DESCRIPTION.md
@@ -0,0 +1 @@
+This demo takes in 12 inputs from the user in dropdowns and sliders and predicts income. It also has a separate button for explaining the prediction.
\ No newline at end of file
diff --git a/demo/xgboost-income-prediction-with-explainability/requirements.txt b/demo/xgboost-income-prediction-with-explainability/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..049ecfde73576c6691bfdb3e3b7a7a80c10788b5
--- /dev/null
+++ b/demo/xgboost-income-prediction-with-explainability/requirements.txt
@@ -0,0 +1,6 @@
+numpy==1.23.2
+matplotlib
+shap
+xgboost==1.7.6
+pandas
+datasets
\ No newline at end of file
diff --git a/demo/xgboost-income-prediction-with-explainability/run.ipynb b/demo/xgboost-income-prediction-with-explainability/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e1093d6867ec1cc2fd3c615f9c97d52091a1c77a
--- /dev/null
+++ b/demo/xgboost-income-prediction-with-explainability/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: xgboost-income-prediction-with-explainability\n", "### This demo takes in 12 inputs from the user in dropdowns and sliders and predicts income. It also has a separate button for explaining the prediction.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio numpy==1.23.2 matplotlib shap xgboost==1.7.6 pandas datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import random\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "import shap\n", "import xgboost as xgb\n", "from datasets import load_dataset\n", "\n", "\n", "dataset = load_dataset(\"scikit-learn/adult-census-income\")\n", "X_train = dataset[\"train\"].to_pandas()\n", "_ = X_train.pop(\"fnlwgt\")\n", "_ = X_train.pop(\"race\")\n", "y_train = X_train.pop(\"income\")\n", "y_train = (y_train == \">50K\").astype(int)\n", "categorical_columns = [\n", " \"workclass\",\n", " \"education\",\n", " \"marital.status\",\n", " \"occupation\",\n", " \"relationship\",\n", " \"sex\",\n", " \"native.country\",\n", "]\n", "X_train = X_train.astype({col: \"category\" for col in categorical_columns})\n", "data = xgb.DMatrix(X_train, label=y_train, enable_categorical=True)\n", "model = xgb.train(params={\"objective\": \"binary:logistic\"}, dtrain=data)\n", "explainer = shap.TreeExplainer(model)\n", "\n", "def predict(*args):\n", " df = pd.DataFrame([args], columns=X_train.columns)\n", " df = df.astype({col: \"category\" for col in categorical_columns})\n", " pos_pred = model.predict(xgb.DMatrix(df, enable_categorical=True))\n", " return {\">50K\": float(pos_pred[0]), \"<=50K\": 1 - float(pos_pred[0])}\n", "\n", "\n", "def interpret(*args):\n", " df = pd.DataFrame([args], columns=X_train.columns)\n", " df = df.astype({col: \"category\" for col in categorical_columns})\n", " shap_values = explainer.shap_values(xgb.DMatrix(df, enable_categorical=True))\n", " scores_desc = list(zip(shap_values[0], X_train.columns))\n", " scores_desc = sorted(scores_desc)\n", " fig_m = plt.figure(tight_layout=True)\n", " plt.barh([s[1] for s in scores_desc], [s[0] for s in scores_desc])\n", " plt.title(\"Feature Shap Values\")\n", " plt.ylabel(\"Shap Value\")\n", " plt.xlabel(\"Feature\")\n", " plt.tight_layout()\n", " return fig_m\n", "\n", "\n", "unique_class = sorted(X_train[\"workclass\"].unique())\n", "unique_education = sorted(X_train[\"education\"].unique())\n", "unique_marital_status = sorted(X_train[\"marital.status\"].unique())\n", "unique_relationship = sorted(X_train[\"relationship\"].unique())\n", "unique_occupation = sorted(X_train[\"occupation\"].unique())\n", "unique_sex = sorted(X_train[\"sex\"].unique())\n", "unique_country = sorted(X_train[\"native.country\"].unique())\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"\"\"\n", " **Income Classification with XGBoost \ud83d\udcb0**: This demo uses an XGBoost classifier predicts income based on demographic factors, along with Shapley value-based *explanations*. The [source code for this Gradio demo is here](https://huggingface.co/spaces/gradio/xgboost-income-prediction-with-explainability/blob/main/app.py).\n", " \"\"\")\n", " with gr.Row():\n", " with gr.Column():\n", " age = gr.Slider(label=\"Age\", minimum=17, maximum=90, step=1, randomize=True)\n", " work_class = gr.Dropdown(\n", " label=\"Workclass\",\n", " choices=unique_class,\n", " value=lambda: random.choice(unique_class),\n", " )\n", " education = gr.Dropdown(\n", " label=\"Education Level\",\n", " choices=unique_education,\n", " value=lambda: random.choice(unique_education),\n", " )\n", " years = gr.Slider(\n", " label=\"Years of schooling\",\n", " minimum=1,\n", " maximum=16,\n", " step=1,\n", " randomize=True,\n", " )\n", " marital_status = gr.Dropdown(\n", " label=\"Marital Status\",\n", " choices=unique_marital_status,\n", " value=lambda: random.choice(unique_marital_status),\n", " )\n", " occupation = gr.Dropdown(\n", " label=\"Occupation\",\n", " choices=unique_occupation,\n", " value=lambda: random.choice(unique_occupation),\n", " )\n", " relationship = gr.Dropdown(\n", " label=\"Relationship Status\",\n", " choices=unique_relationship,\n", " value=lambda: random.choice(unique_relationship),\n", " )\n", " sex = gr.Dropdown(\n", " label=\"Sex\", choices=unique_sex, value=lambda: random.choice(unique_sex)\n", " )\n", " capital_gain = gr.Slider(\n", " label=\"Capital Gain\",\n", " minimum=0,\n", " maximum=100000,\n", " step=500,\n", " randomize=True,\n", " )\n", " capital_loss = gr.Slider(\n", " label=\"Capital Loss\", minimum=0, maximum=10000, step=500, randomize=True\n", " )\n", " hours_per_week = gr.Slider(\n", " label=\"Hours Per Week Worked\", minimum=1, maximum=99, step=1\n", " )\n", " country = gr.Dropdown(\n", " label=\"Native Country\",\n", " choices=unique_country,\n", " value=lambda: random.choice(unique_country),\n", " )\n", " with gr.Column():\n", " label = gr.Label()\n", " plot = gr.Plot()\n", " with gr.Row():\n", " predict_btn = gr.Button(value=\"Predict\")\n", " interpret_btn = gr.Button(value=\"Explain\")\n", " predict_btn.click(\n", " predict,\n", " inputs=[\n", " age,\n", " work_class,\n", " education,\n", " years,\n", " marital_status,\n", " occupation,\n", " relationship,\n", " sex,\n", " capital_gain,\n", " capital_loss,\n", " hours_per_week,\n", " country,\n", " ],\n", " outputs=[label],\n", " )\n", " interpret_btn.click(\n", " interpret,\n", " inputs=[\n", " age,\n", " work_class,\n", " education,\n", " years,\n", " marital_status,\n", " occupation,\n", " relationship,\n", " sex,\n", " capital_gain,\n", " capital_loss,\n", " hours_per_week,\n", " country,\n", " ],\n", " outputs=[plot],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/xgboost-income-prediction-with-explainability/run.py b/demo/xgboost-income-prediction-with-explainability/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..27ef4a3f1de405ae7ee4e90b84c5cd209d694053
--- /dev/null
+++ b/demo/xgboost-income-prediction-with-explainability/run.py
@@ -0,0 +1,163 @@
+import gradio as gr
+import random
+import matplotlib.pyplot as plt
+import pandas as pd
+import shap
+import xgboost as xgb
+from datasets import load_dataset
+
+
+dataset = load_dataset("scikit-learn/adult-census-income")
+X_train = dataset["train"].to_pandas()
+_ = X_train.pop("fnlwgt")
+_ = X_train.pop("race")
+y_train = X_train.pop("income")
+y_train = (y_train == ">50K").astype(int)
+categorical_columns = [
+ "workclass",
+ "education",
+ "marital.status",
+ "occupation",
+ "relationship",
+ "sex",
+ "native.country",
+]
+X_train = X_train.astype({col: "category" for col in categorical_columns})
+data = xgb.DMatrix(X_train, label=y_train, enable_categorical=True)
+model = xgb.train(params={"objective": "binary:logistic"}, dtrain=data)
+explainer = shap.TreeExplainer(model)
+
+def predict(*args):
+ df = pd.DataFrame([args], columns=X_train.columns)
+ df = df.astype({col: "category" for col in categorical_columns})
+ pos_pred = model.predict(xgb.DMatrix(df, enable_categorical=True))
+ return {">50K": float(pos_pred[0]), "<=50K": 1 - float(pos_pred[0])}
+
+
+def interpret(*args):
+ df = pd.DataFrame([args], columns=X_train.columns)
+ df = df.astype({col: "category" for col in categorical_columns})
+ shap_values = explainer.shap_values(xgb.DMatrix(df, enable_categorical=True))
+ scores_desc = list(zip(shap_values[0], X_train.columns))
+ scores_desc = sorted(scores_desc)
+ fig_m = plt.figure(tight_layout=True)
+ plt.barh([s[1] for s in scores_desc], [s[0] for s in scores_desc])
+ plt.title("Feature Shap Values")
+ plt.ylabel("Shap Value")
+ plt.xlabel("Feature")
+ plt.tight_layout()
+ return fig_m
+
+
+unique_class = sorted(X_train["workclass"].unique())
+unique_education = sorted(X_train["education"].unique())
+unique_marital_status = sorted(X_train["marital.status"].unique())
+unique_relationship = sorted(X_train["relationship"].unique())
+unique_occupation = sorted(X_train["occupation"].unique())
+unique_sex = sorted(X_train["sex"].unique())
+unique_country = sorted(X_train["native.country"].unique())
+
+with gr.Blocks() as demo:
+ gr.Markdown("""
+ **Income Classification with XGBoost 💰**: This demo uses an XGBoost classifier predicts income based on demographic factors, along with Shapley value-based *explanations*. The [source code for this Gradio demo is here](https://huggingface.co/spaces/gradio/xgboost-income-prediction-with-explainability/blob/main/app.py).
+ """)
+ with gr.Row():
+ with gr.Column():
+ age = gr.Slider(label="Age", minimum=17, maximum=90, step=1, randomize=True)
+ work_class = gr.Dropdown(
+ label="Workclass",
+ choices=unique_class,
+ value=lambda: random.choice(unique_class),
+ )
+ education = gr.Dropdown(
+ label="Education Level",
+ choices=unique_education,
+ value=lambda: random.choice(unique_education),
+ )
+ years = gr.Slider(
+ label="Years of schooling",
+ minimum=1,
+ maximum=16,
+ step=1,
+ randomize=True,
+ )
+ marital_status = gr.Dropdown(
+ label="Marital Status",
+ choices=unique_marital_status,
+ value=lambda: random.choice(unique_marital_status),
+ )
+ occupation = gr.Dropdown(
+ label="Occupation",
+ choices=unique_occupation,
+ value=lambda: random.choice(unique_occupation),
+ )
+ relationship = gr.Dropdown(
+ label="Relationship Status",
+ choices=unique_relationship,
+ value=lambda: random.choice(unique_relationship),
+ )
+ sex = gr.Dropdown(
+ label="Sex", choices=unique_sex, value=lambda: random.choice(unique_sex)
+ )
+ capital_gain = gr.Slider(
+ label="Capital Gain",
+ minimum=0,
+ maximum=100000,
+ step=500,
+ randomize=True,
+ )
+ capital_loss = gr.Slider(
+ label="Capital Loss", minimum=0, maximum=10000, step=500, randomize=True
+ )
+ hours_per_week = gr.Slider(
+ label="Hours Per Week Worked", minimum=1, maximum=99, step=1
+ )
+ country = gr.Dropdown(
+ label="Native Country",
+ choices=unique_country,
+ value=lambda: random.choice(unique_country),
+ )
+ with gr.Column():
+ label = gr.Label()
+ plot = gr.Plot()
+ with gr.Row():
+ predict_btn = gr.Button(value="Predict")
+ interpret_btn = gr.Button(value="Explain")
+ predict_btn.click(
+ predict,
+ inputs=[
+ age,
+ work_class,
+ education,
+ years,
+ marital_status,
+ occupation,
+ relationship,
+ sex,
+ capital_gain,
+ capital_loss,
+ hours_per_week,
+ country,
+ ],
+ outputs=[label],
+ )
+ interpret_btn.click(
+ interpret,
+ inputs=[
+ age,
+ work_class,
+ education,
+ years,
+ marital_status,
+ occupation,
+ relationship,
+ sex,
+ capital_gain,
+ capital_loss,
+ hours_per_week,
+ country,
+ ],
+ outputs=[plot],
+ )
+
+demo.launch()
diff --git a/demo/zip_files/.gitignore b/demo/zip_files/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8e9b8f2027a5cfe97c8c9c96709fc2453c0df220
--- /dev/null
+++ b/demo/zip_files/.gitignore
@@ -0,0 +1 @@
+tmp.zip
\ No newline at end of file
diff --git a/demo/zip_files/files/titanic.csv b/demo/zip_files/files/titanic.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5cc466e97cf12f155d19b9f717425214075d0b7a
--- /dev/null
+++ b/demo/zip_files/files/titanic.csv
@@ -0,0 +1,892 @@
+PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
+1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
+2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
+3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
+4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
+5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
+6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
+7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
+8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
+9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
+10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
+11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
+12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
+13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
+14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S
+15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S
+16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S
+17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q
+18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S
+19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S
+20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C
+21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S
+22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S
+23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q
+24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S
+25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S
+26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S
+27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C
+28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S
+29,1,3,"O'Dwyer, Miss. Ellen ""Nellie""",female,,0,0,330959,7.8792,,Q
+30,0,3,"Todoroff, Mr. Lalio",male,,0,0,349216,7.8958,,S
+31,0,1,"Uruchurtu, Don. Manuel E",male,40,0,0,PC 17601,27.7208,,C
+32,1,1,"Spencer, Mrs. William Augustus (Marie Eugenie)",female,,1,0,PC 17569,146.5208,B78,C
+33,1,3,"Glynn, Miss. Mary Agatha",female,,0,0,335677,7.75,,Q
+34,0,2,"Wheadon, Mr. Edward H",male,66,0,0,C.A. 24579,10.5,,S
+35,0,1,"Meyer, Mr. Edgar Joseph",male,28,1,0,PC 17604,82.1708,,C
+36,0,1,"Holverson, Mr. Alexander Oskar",male,42,1,0,113789,52,,S
+37,1,3,"Mamee, Mr. Hanna",male,,0,0,2677,7.2292,,C
+38,0,3,"Cann, Mr. Ernest Charles",male,21,0,0,A./5. 2152,8.05,,S
+39,0,3,"Vander Planke, Miss. Augusta Maria",female,18,2,0,345764,18,,S
+40,1,3,"Nicola-Yarred, Miss. Jamila",female,14,1,0,2651,11.2417,,C
+41,0,3,"Ahlin, Mrs. Johan (Johanna Persdotter Larsson)",female,40,1,0,7546,9.475,,S
+42,0,2,"Turpin, Mrs. William John Robert (Dorothy Ann Wonnacott)",female,27,1,0,11668,21,,S
+43,0,3,"Kraeff, Mr. Theodor",male,,0,0,349253,7.8958,,C
+44,1,2,"Laroche, Miss. Simonne Marie Anne Andree",female,3,1,2,SC/Paris 2123,41.5792,,C
+45,1,3,"Devaney, Miss. Margaret Delia",female,19,0,0,330958,7.8792,,Q
+46,0,3,"Rogers, Mr. William John",male,,0,0,S.C./A.4. 23567,8.05,,S
+47,0,3,"Lennon, Mr. Denis",male,,1,0,370371,15.5,,Q
+48,1,3,"O'Driscoll, Miss. Bridget",female,,0,0,14311,7.75,,Q
+49,0,3,"Samaan, Mr. Youssef",male,,2,0,2662,21.6792,,C
+50,0,3,"Arnold-Franchi, Mrs. Josef (Josefine Franchi)",female,18,1,0,349237,17.8,,S
+51,0,3,"Panula, Master. Juha Niilo",male,7,4,1,3101295,39.6875,,S
+52,0,3,"Nosworthy, Mr. Richard Cater",male,21,0,0,A/4. 39886,7.8,,S
+53,1,1,"Harper, Mrs. Henry Sleeper (Myna Haxtun)",female,49,1,0,PC 17572,76.7292,D33,C
+54,1,2,"Faunthorpe, Mrs. Lizzie (Elizabeth Anne Wilkinson)",female,29,1,0,2926,26,,S
+55,0,1,"Ostby, Mr. Engelhart Cornelius",male,65,0,1,113509,61.9792,B30,C
+56,1,1,"Woolner, Mr. Hugh",male,,0,0,19947,35.5,C52,S
+57,1,2,"Rugg, Miss. Emily",female,21,0,0,C.A. 31026,10.5,,S
+58,0,3,"Novel, Mr. Mansouer",male,28.5,0,0,2697,7.2292,,C
+59,1,2,"West, Miss. Constance Mirium",female,5,1,2,C.A. 34651,27.75,,S
+60,0,3,"Goodwin, Master. William Frederick",male,11,5,2,CA 2144,46.9,,S
+61,0,3,"Sirayanian, Mr. Orsen",male,22,0,0,2669,7.2292,,C
+62,1,1,"Icard, Miss. Amelie",female,38,0,0,113572,80,B28,
+63,0,1,"Harris, Mr. Henry Birkhardt",male,45,1,0,36973,83.475,C83,S
+64,0,3,"Skoog, Master. Harald",male,4,3,2,347088,27.9,,S
+65,0,1,"Stewart, Mr. Albert A",male,,0,0,PC 17605,27.7208,,C
+66,1,3,"Moubarek, Master. Gerios",male,,1,1,2661,15.2458,,C
+67,1,2,"Nye, Mrs. (Elizabeth Ramell)",female,29,0,0,C.A. 29395,10.5,F33,S
+68,0,3,"Crease, Mr. Ernest James",male,19,0,0,S.P. 3464,8.1583,,S
+69,1,3,"Andersson, Miss. Erna Alexandra",female,17,4,2,3101281,7.925,,S
+70,0,3,"Kink, Mr. Vincenz",male,26,2,0,315151,8.6625,,S
+71,0,2,"Jenkin, Mr. Stephen Curnow",male,32,0,0,C.A. 33111,10.5,,S
+72,0,3,"Goodwin, Miss. Lillian Amy",female,16,5,2,CA 2144,46.9,,S
+73,0,2,"Hood, Mr. Ambrose Jr",male,21,0,0,S.O.C. 14879,73.5,,S
+74,0,3,"Chronopoulos, Mr. Apostolos",male,26,1,0,2680,14.4542,,C
+75,1,3,"Bing, Mr. Lee",male,32,0,0,1601,56.4958,,S
+76,0,3,"Moen, Mr. Sigurd Hansen",male,25,0,0,348123,7.65,F G73,S
+77,0,3,"Staneff, Mr. Ivan",male,,0,0,349208,7.8958,,S
+78,0,3,"Moutal, Mr. Rahamin Haim",male,,0,0,374746,8.05,,S
+79,1,2,"Caldwell, Master. Alden Gates",male,0.83,0,2,248738,29,,S
+80,1,3,"Dowdell, Miss. Elizabeth",female,30,0,0,364516,12.475,,S
+81,0,3,"Waelens, Mr. Achille",male,22,0,0,345767,9,,S
+82,1,3,"Sheerlinck, Mr. Jan Baptist",male,29,0,0,345779,9.5,,S
+83,1,3,"McDermott, Miss. Brigdet Delia",female,,0,0,330932,7.7875,,Q
+84,0,1,"Carrau, Mr. Francisco M",male,28,0,0,113059,47.1,,S
+85,1,2,"Ilett, Miss. Bertha",female,17,0,0,SO/C 14885,10.5,,S
+86,1,3,"Backstrom, Mrs. Karl Alfred (Maria Mathilda Gustafsson)",female,33,3,0,3101278,15.85,,S
+87,0,3,"Ford, Mr. William Neal",male,16,1,3,W./C. 6608,34.375,,S
+88,0,3,"Slocovski, Mr. Selman Francis",male,,0,0,SOTON/OQ 392086,8.05,,S
+89,1,1,"Fortune, Miss. Mabel Helen",female,23,3,2,19950,263,C23 C25 C27,S
+90,0,3,"Celotti, Mr. Francesco",male,24,0,0,343275,8.05,,S
+91,0,3,"Christmann, Mr. Emil",male,29,0,0,343276,8.05,,S
+92,0,3,"Andreasson, Mr. Paul Edvin",male,20,0,0,347466,7.8542,,S
+93,0,1,"Chaffee, Mr. Herbert Fuller",male,46,1,0,W.E.P. 5734,61.175,E31,S
+94,0,3,"Dean, Mr. Bertram Frank",male,26,1,2,C.A. 2315,20.575,,S
+95,0,3,"Coxon, Mr. Daniel",male,59,0,0,364500,7.25,,S
+96,0,3,"Shorney, Mr. Charles Joseph",male,,0,0,374910,8.05,,S
+97,0,1,"Goldschmidt, Mr. George B",male,71,0,0,PC 17754,34.6542,A5,C
+98,1,1,"Greenfield, Mr. William Bertram",male,23,0,1,PC 17759,63.3583,D10 D12,C
+99,1,2,"Doling, Mrs. John T (Ada Julia Bone)",female,34,0,1,231919,23,,S
+100,0,2,"Kantor, Mr. Sinai",male,34,1,0,244367,26,,S
+101,0,3,"Petranec, Miss. Matilda",female,28,0,0,349245,7.8958,,S
+102,0,3,"Petroff, Mr. Pastcho (""Pentcho"")",male,,0,0,349215,7.8958,,S
+103,0,1,"White, Mr. Richard Frasar",male,21,0,1,35281,77.2875,D26,S
+104,0,3,"Johansson, Mr. Gustaf Joel",male,33,0,0,7540,8.6542,,S
+105,0,3,"Gustafsson, Mr. Anders Vilhelm",male,37,2,0,3101276,7.925,,S
+106,0,3,"Mionoff, Mr. Stoytcho",male,28,0,0,349207,7.8958,,S
+107,1,3,"Salkjelsvik, Miss. Anna Kristine",female,21,0,0,343120,7.65,,S
+108,1,3,"Moss, Mr. Albert Johan",male,,0,0,312991,7.775,,S
+109,0,3,"Rekic, Mr. Tido",male,38,0,0,349249,7.8958,,S
+110,1,3,"Moran, Miss. Bertha",female,,1,0,371110,24.15,,Q
+111,0,1,"Porter, Mr. Walter Chamberlain",male,47,0,0,110465,52,C110,S
+112,0,3,"Zabour, Miss. Hileni",female,14.5,1,0,2665,14.4542,,C
+113,0,3,"Barton, Mr. David John",male,22,0,0,324669,8.05,,S
+114,0,3,"Jussila, Miss. Katriina",female,20,1,0,4136,9.825,,S
+115,0,3,"Attalah, Miss. Malake",female,17,0,0,2627,14.4583,,C
+116,0,3,"Pekoniemi, Mr. Edvard",male,21,0,0,STON/O 2. 3101294,7.925,,S
+117,0,3,"Connors, Mr. Patrick",male,70.5,0,0,370369,7.75,,Q
+118,0,2,"Turpin, Mr. William John Robert",male,29,1,0,11668,21,,S
+119,0,1,"Baxter, Mr. Quigg Edmond",male,24,0,1,PC 17558,247.5208,B58 B60,C
+120,0,3,"Andersson, Miss. Ellis Anna Maria",female,2,4,2,347082,31.275,,S
+121,0,2,"Hickman, Mr. Stanley George",male,21,2,0,S.O.C. 14879,73.5,,S
+122,0,3,"Moore, Mr. Leonard Charles",male,,0,0,A4. 54510,8.05,,S
+123,0,2,"Nasser, Mr. Nicholas",male,32.5,1,0,237736,30.0708,,C
+124,1,2,"Webber, Miss. Susan",female,32.5,0,0,27267,13,E101,S
+125,0,1,"White, Mr. Percival Wayland",male,54,0,1,35281,77.2875,D26,S
+126,1,3,"Nicola-Yarred, Master. Elias",male,12,1,0,2651,11.2417,,C
+127,0,3,"McMahon, Mr. Martin",male,,0,0,370372,7.75,,Q
+128,1,3,"Madsen, Mr. Fridtjof Arne",male,24,0,0,C 17369,7.1417,,S
+129,1,3,"Peter, Miss. Anna",female,,1,1,2668,22.3583,F E69,C
+130,0,3,"Ekstrom, Mr. Johan",male,45,0,0,347061,6.975,,S
+131,0,3,"Drazenoic, Mr. Jozef",male,33,0,0,349241,7.8958,,C
+132,0,3,"Coelho, Mr. Domingos Fernandeo",male,20,0,0,SOTON/O.Q. 3101307,7.05,,S
+133,0,3,"Robins, Mrs. Alexander A (Grace Charity Laury)",female,47,1,0,A/5. 3337,14.5,,S
+134,1,2,"Weisz, Mrs. Leopold (Mathilde Francoise Pede)",female,29,1,0,228414,26,,S
+135,0,2,"Sobey, Mr. Samuel James Hayden",male,25,0,0,C.A. 29178,13,,S
+136,0,2,"Richard, Mr. Emile",male,23,0,0,SC/PARIS 2133,15.0458,,C
+137,1,1,"Newsom, Miss. Helen Monypeny",female,19,0,2,11752,26.2833,D47,S
+138,0,1,"Futrelle, Mr. Jacques Heath",male,37,1,0,113803,53.1,C123,S
+139,0,3,"Osen, Mr. Olaf Elon",male,16,0,0,7534,9.2167,,S
+140,0,1,"Giglio, Mr. Victor",male,24,0,0,PC 17593,79.2,B86,C
+141,0,3,"Boulos, Mrs. Joseph (Sultana)",female,,0,2,2678,15.2458,,C
+142,1,3,"Nysten, Miss. Anna Sofia",female,22,0,0,347081,7.75,,S
+143,1,3,"Hakkarainen, Mrs. Pekka Pietari (Elin Matilda Dolck)",female,24,1,0,STON/O2. 3101279,15.85,,S
+144,0,3,"Burke, Mr. Jeremiah",male,19,0,0,365222,6.75,,Q
+145,0,2,"Andrew, Mr. Edgardo Samuel",male,18,0,0,231945,11.5,,S
+146,0,2,"Nicholls, Mr. Joseph Charles",male,19,1,1,C.A. 33112,36.75,,S
+147,1,3,"Andersson, Mr. August Edvard (""Wennerstrom"")",male,27,0,0,350043,7.7958,,S
+148,0,3,"Ford, Miss. Robina Maggie ""Ruby""",female,9,2,2,W./C. 6608,34.375,,S
+149,0,2,"Navratil, Mr. Michel (""Louis M Hoffman"")",male,36.5,0,2,230080,26,F2,S
+150,0,2,"Byles, Rev. Thomas Roussel Davids",male,42,0,0,244310,13,,S
+151,0,2,"Bateman, Rev. Robert James",male,51,0,0,S.O.P. 1166,12.525,,S
+152,1,1,"Pears, Mrs. Thomas (Edith Wearne)",female,22,1,0,113776,66.6,C2,S
+153,0,3,"Meo, Mr. Alfonzo",male,55.5,0,0,A.5. 11206,8.05,,S
+154,0,3,"van Billiard, Mr. Austin Blyler",male,40.5,0,2,A/5. 851,14.5,,S
+155,0,3,"Olsen, Mr. Ole Martin",male,,0,0,Fa 265302,7.3125,,S
+156,0,1,"Williams, Mr. Charles Duane",male,51,0,1,PC 17597,61.3792,,C
+157,1,3,"Gilnagh, Miss. Katherine ""Katie""",female,16,0,0,35851,7.7333,,Q
+158,0,3,"Corn, Mr. Harry",male,30,0,0,SOTON/OQ 392090,8.05,,S
+159,0,3,"Smiljanic, Mr. Mile",male,,0,0,315037,8.6625,,S
+160,0,3,"Sage, Master. Thomas Henry",male,,8,2,CA. 2343,69.55,,S
+161,0,3,"Cribb, Mr. John Hatfield",male,44,0,1,371362,16.1,,S
+162,1,2,"Watt, Mrs. James (Elizabeth ""Bessie"" Inglis Milne)",female,40,0,0,C.A. 33595,15.75,,S
+163,0,3,"Bengtsson, Mr. John Viktor",male,26,0,0,347068,7.775,,S
+164,0,3,"Calic, Mr. Jovo",male,17,0,0,315093,8.6625,,S
+165,0,3,"Panula, Master. Eino Viljami",male,1,4,1,3101295,39.6875,,S
+166,1,3,"Goldsmith, Master. Frank John William ""Frankie""",male,9,0,2,363291,20.525,,S
+167,1,1,"Chibnall, Mrs. (Edith Martha Bowerman)",female,,0,1,113505,55,E33,S
+168,0,3,"Skoog, Mrs. William (Anna Bernhardina Karlsson)",female,45,1,4,347088,27.9,,S
+169,0,1,"Baumann, Mr. John D",male,,0,0,PC 17318,25.925,,S
+170,0,3,"Ling, Mr. Lee",male,28,0,0,1601,56.4958,,S
+171,0,1,"Van der hoef, Mr. Wyckoff",male,61,0,0,111240,33.5,B19,S
+172,0,3,"Rice, Master. Arthur",male,4,4,1,382652,29.125,,Q
+173,1,3,"Johnson, Miss. Eleanor Ileen",female,1,1,1,347742,11.1333,,S
+174,0,3,"Sivola, Mr. Antti Wilhelm",male,21,0,0,STON/O 2. 3101280,7.925,,S
+175,0,1,"Smith, Mr. James Clinch",male,56,0,0,17764,30.6958,A7,C
+176,0,3,"Klasen, Mr. Klas Albin",male,18,1,1,350404,7.8542,,S
+177,0,3,"Lefebre, Master. Henry Forbes",male,,3,1,4133,25.4667,,S
+178,0,1,"Isham, Miss. Ann Elizabeth",female,50,0,0,PC 17595,28.7125,C49,C
+179,0,2,"Hale, Mr. Reginald",male,30,0,0,250653,13,,S
+180,0,3,"Leonard, Mr. Lionel",male,36,0,0,LINE,0,,S
+181,0,3,"Sage, Miss. Constance Gladys",female,,8,2,CA. 2343,69.55,,S
+182,0,2,"Pernot, Mr. Rene",male,,0,0,SC/PARIS 2131,15.05,,C
+183,0,3,"Asplund, Master. Clarence Gustaf Hugo",male,9,4,2,347077,31.3875,,S
+184,1,2,"Becker, Master. Richard F",male,1,2,1,230136,39,F4,S
+185,1,3,"Kink-Heilmann, Miss. Luise Gretchen",female,4,0,2,315153,22.025,,S
+186,0,1,"Rood, Mr. Hugh Roscoe",male,,0,0,113767,50,A32,S
+187,1,3,"O'Brien, Mrs. Thomas (Johanna ""Hannah"" Godfrey)",female,,1,0,370365,15.5,,Q
+188,1,1,"Romaine, Mr. Charles Hallace (""Mr C Rolmane"")",male,45,0,0,111428,26.55,,S
+189,0,3,"Bourke, Mr. John",male,40,1,1,364849,15.5,,Q
+190,0,3,"Turcin, Mr. Stjepan",male,36,0,0,349247,7.8958,,S
+191,1,2,"Pinsky, Mrs. (Rosa)",female,32,0,0,234604,13,,S
+192,0,2,"Carbines, Mr. William",male,19,0,0,28424,13,,S
+193,1,3,"Andersen-Jensen, Miss. Carla Christine Nielsine",female,19,1,0,350046,7.8542,,S
+194,1,2,"Navratil, Master. Michel M",male,3,1,1,230080,26,F2,S
+195,1,1,"Brown, Mrs. James Joseph (Margaret Tobin)",female,44,0,0,PC 17610,27.7208,B4,C
+196,1,1,"Lurette, Miss. Elise",female,58,0,0,PC 17569,146.5208,B80,C
+197,0,3,"Mernagh, Mr. Robert",male,,0,0,368703,7.75,,Q
+198,0,3,"Olsen, Mr. Karl Siegwart Andreas",male,42,0,1,4579,8.4042,,S
+199,1,3,"Madigan, Miss. Margaret ""Maggie""",female,,0,0,370370,7.75,,Q
+200,0,2,"Yrois, Miss. Henriette (""Mrs Harbeck"")",female,24,0,0,248747,13,,S
+201,0,3,"Vande Walle, Mr. Nestor Cyriel",male,28,0,0,345770,9.5,,S
+202,0,3,"Sage, Mr. Frederick",male,,8,2,CA. 2343,69.55,,S
+203,0,3,"Johanson, Mr. Jakob Alfred",male,34,0,0,3101264,6.4958,,S
+204,0,3,"Youseff, Mr. Gerious",male,45.5,0,0,2628,7.225,,C
+205,1,3,"Cohen, Mr. Gurshon ""Gus""",male,18,0,0,A/5 3540,8.05,,S
+206,0,3,"Strom, Miss. Telma Matilda",female,2,0,1,347054,10.4625,G6,S
+207,0,3,"Backstrom, Mr. Karl Alfred",male,32,1,0,3101278,15.85,,S
+208,1,3,"Albimona, Mr. Nassef Cassem",male,26,0,0,2699,18.7875,,C
+209,1,3,"Carr, Miss. Helen ""Ellen""",female,16,0,0,367231,7.75,,Q
+210,1,1,"Blank, Mr. Henry",male,40,0,0,112277,31,A31,C
+211,0,3,"Ali, Mr. Ahmed",male,24,0,0,SOTON/O.Q. 3101311,7.05,,S
+212,1,2,"Cameron, Miss. Clear Annie",female,35,0,0,F.C.C. 13528,21,,S
+213,0,3,"Perkin, Mr. John Henry",male,22,0,0,A/5 21174,7.25,,S
+214,0,2,"Givard, Mr. Hans Kristensen",male,30,0,0,250646,13,,S
+215,0,3,"Kiernan, Mr. Philip",male,,1,0,367229,7.75,,Q
+216,1,1,"Newell, Miss. Madeleine",female,31,1,0,35273,113.275,D36,C
+217,1,3,"Honkanen, Miss. Eliina",female,27,0,0,STON/O2. 3101283,7.925,,S
+218,0,2,"Jacobsohn, Mr. Sidney Samuel",male,42,1,0,243847,27,,S
+219,1,1,"Bazzani, Miss. Albina",female,32,0,0,11813,76.2917,D15,C
+220,0,2,"Harris, Mr. Walter",male,30,0,0,W/C 14208,10.5,,S
+221,1,3,"Sunderland, Mr. Victor Francis",male,16,0,0,SOTON/OQ 392089,8.05,,S
+222,0,2,"Bracken, Mr. James H",male,27,0,0,220367,13,,S
+223,0,3,"Green, Mr. George Henry",male,51,0,0,21440,8.05,,S
+224,0,3,"Nenkoff, Mr. Christo",male,,0,0,349234,7.8958,,S
+225,1,1,"Hoyt, Mr. Frederick Maxfield",male,38,1,0,19943,90,C93,S
+226,0,3,"Berglund, Mr. Karl Ivar Sven",male,22,0,0,PP 4348,9.35,,S
+227,1,2,"Mellors, Mr. William John",male,19,0,0,SW/PP 751,10.5,,S
+228,0,3,"Lovell, Mr. John Hall (""Henry"")",male,20.5,0,0,A/5 21173,7.25,,S
+229,0,2,"Fahlstrom, Mr. Arne Jonas",male,18,0,0,236171,13,,S
+230,0,3,"Lefebre, Miss. Mathilde",female,,3,1,4133,25.4667,,S
+231,1,1,"Harris, Mrs. Henry Birkhardt (Irene Wallach)",female,35,1,0,36973,83.475,C83,S
+232,0,3,"Larsson, Mr. Bengt Edvin",male,29,0,0,347067,7.775,,S
+233,0,2,"Sjostedt, Mr. Ernst Adolf",male,59,0,0,237442,13.5,,S
+234,1,3,"Asplund, Miss. Lillian Gertrud",female,5,4,2,347077,31.3875,,S
+235,0,2,"Leyson, Mr. Robert William Norman",male,24,0,0,C.A. 29566,10.5,,S
+236,0,3,"Harknett, Miss. Alice Phoebe",female,,0,0,W./C. 6609,7.55,,S
+237,0,2,"Hold, Mr. Stephen",male,44,1,0,26707,26,,S
+238,1,2,"Collyer, Miss. Marjorie ""Lottie""",female,8,0,2,C.A. 31921,26.25,,S
+239,0,2,"Pengelly, Mr. Frederick William",male,19,0,0,28665,10.5,,S
+240,0,2,"Hunt, Mr. George Henry",male,33,0,0,SCO/W 1585,12.275,,S
+241,0,3,"Zabour, Miss. Thamine",female,,1,0,2665,14.4542,,C
+242,1,3,"Murphy, Miss. Katherine ""Kate""",female,,1,0,367230,15.5,,Q
+243,0,2,"Coleridge, Mr. Reginald Charles",male,29,0,0,W./C. 14263,10.5,,S
+244,0,3,"Maenpaa, Mr. Matti Alexanteri",male,22,0,0,STON/O 2. 3101275,7.125,,S
+245,0,3,"Attalah, Mr. Sleiman",male,30,0,0,2694,7.225,,C
+246,0,1,"Minahan, Dr. William Edward",male,44,2,0,19928,90,C78,Q
+247,0,3,"Lindahl, Miss. Agda Thorilda Viktoria",female,25,0,0,347071,7.775,,S
+248,1,2,"Hamalainen, Mrs. William (Anna)",female,24,0,2,250649,14.5,,S
+249,1,1,"Beckwith, Mr. Richard Leonard",male,37,1,1,11751,52.5542,D35,S
+250,0,2,"Carter, Rev. Ernest Courtenay",male,54,1,0,244252,26,,S
+251,0,3,"Reed, Mr. James George",male,,0,0,362316,7.25,,S
+252,0,3,"Strom, Mrs. Wilhelm (Elna Matilda Persson)",female,29,1,1,347054,10.4625,G6,S
+253,0,1,"Stead, Mr. William Thomas",male,62,0,0,113514,26.55,C87,S
+254,0,3,"Lobb, Mr. William Arthur",male,30,1,0,A/5. 3336,16.1,,S
+255,0,3,"Rosblom, Mrs. Viktor (Helena Wilhelmina)",female,41,0,2,370129,20.2125,,S
+256,1,3,"Touma, Mrs. Darwis (Hanne Youssef Razi)",female,29,0,2,2650,15.2458,,C
+257,1,1,"Thorne, Mrs. Gertrude Maybelle",female,,0,0,PC 17585,79.2,,C
+258,1,1,"Cherry, Miss. Gladys",female,30,0,0,110152,86.5,B77,S
+259,1,1,"Ward, Miss. Anna",female,35,0,0,PC 17755,512.3292,,C
+260,1,2,"Parrish, Mrs. (Lutie Davis)",female,50,0,1,230433,26,,S
+261,0,3,"Smith, Mr. Thomas",male,,0,0,384461,7.75,,Q
+262,1,3,"Asplund, Master. Edvin Rojj Felix",male,3,4,2,347077,31.3875,,S
+263,0,1,"Taussig, Mr. Emil",male,52,1,1,110413,79.65,E67,S
+264,0,1,"Harrison, Mr. William",male,40,0,0,112059,0,B94,S
+265,0,3,"Henry, Miss. Delia",female,,0,0,382649,7.75,,Q
+266,0,2,"Reeves, Mr. David",male,36,0,0,C.A. 17248,10.5,,S
+267,0,3,"Panula, Mr. Ernesti Arvid",male,16,4,1,3101295,39.6875,,S
+268,1,3,"Persson, Mr. Ernst Ulrik",male,25,1,0,347083,7.775,,S
+269,1,1,"Graham, Mrs. William Thompson (Edith Junkins)",female,58,0,1,PC 17582,153.4625,C125,S
+270,1,1,"Bissette, Miss. Amelia",female,35,0,0,PC 17760,135.6333,C99,S
+271,0,1,"Cairns, Mr. Alexander",male,,0,0,113798,31,,S
+272,1,3,"Tornquist, Mr. William Henry",male,25,0,0,LINE,0,,S
+273,1,2,"Mellinger, Mrs. (Elizabeth Anne Maidment)",female,41,0,1,250644,19.5,,S
+274,0,1,"Natsch, Mr. Charles H",male,37,0,1,PC 17596,29.7,C118,C
+275,1,3,"Healy, Miss. Hanora ""Nora""",female,,0,0,370375,7.75,,Q
+276,1,1,"Andrews, Miss. Kornelia Theodosia",female,63,1,0,13502,77.9583,D7,S
+277,0,3,"Lindblom, Miss. Augusta Charlotta",female,45,0,0,347073,7.75,,S
+278,0,2,"Parkes, Mr. Francis ""Frank""",male,,0,0,239853,0,,S
+279,0,3,"Rice, Master. Eric",male,7,4,1,382652,29.125,,Q
+280,1,3,"Abbott, Mrs. Stanton (Rosa Hunt)",female,35,1,1,C.A. 2673,20.25,,S
+281,0,3,"Duane, Mr. Frank",male,65,0,0,336439,7.75,,Q
+282,0,3,"Olsson, Mr. Nils Johan Goransson",male,28,0,0,347464,7.8542,,S
+283,0,3,"de Pelsmaeker, Mr. Alfons",male,16,0,0,345778,9.5,,S
+284,1,3,"Dorking, Mr. Edward Arthur",male,19,0,0,A/5. 10482,8.05,,S
+285,0,1,"Smith, Mr. Richard William",male,,0,0,113056,26,A19,S
+286,0,3,"Stankovic, Mr. Ivan",male,33,0,0,349239,8.6625,,C
+287,1,3,"de Mulder, Mr. Theodore",male,30,0,0,345774,9.5,,S
+288,0,3,"Naidenoff, Mr. Penko",male,22,0,0,349206,7.8958,,S
+289,1,2,"Hosono, Mr. Masabumi",male,42,0,0,237798,13,,S
+290,1,3,"Connolly, Miss. Kate",female,22,0,0,370373,7.75,,Q
+291,1,1,"Barber, Miss. Ellen ""Nellie""",female,26,0,0,19877,78.85,,S
+292,1,1,"Bishop, Mrs. Dickinson H (Helen Walton)",female,19,1,0,11967,91.0792,B49,C
+293,0,2,"Levy, Mr. Rene Jacques",male,36,0,0,SC/Paris 2163,12.875,D,C
+294,0,3,"Haas, Miss. Aloisia",female,24,0,0,349236,8.85,,S
+295,0,3,"Mineff, Mr. Ivan",male,24,0,0,349233,7.8958,,S
+296,0,1,"Lewy, Mr. Ervin G",male,,0,0,PC 17612,27.7208,,C
+297,0,3,"Hanna, Mr. Mansour",male,23.5,0,0,2693,7.2292,,C
+298,0,1,"Allison, Miss. Helen Loraine",female,2,1,2,113781,151.55,C22 C26,S
+299,1,1,"Saalfeld, Mr. Adolphe",male,,0,0,19988,30.5,C106,S
+300,1,1,"Baxter, Mrs. James (Helene DeLaudeniere Chaput)",female,50,0,1,PC 17558,247.5208,B58 B60,C
+301,1,3,"Kelly, Miss. Anna Katherine ""Annie Kate""",female,,0,0,9234,7.75,,Q
+302,1,3,"McCoy, Mr. Bernard",male,,2,0,367226,23.25,,Q
+303,0,3,"Johnson, Mr. William Cahoone Jr",male,19,0,0,LINE,0,,S
+304,1,2,"Keane, Miss. Nora A",female,,0,0,226593,12.35,E101,Q
+305,0,3,"Williams, Mr. Howard Hugh ""Harry""",male,,0,0,A/5 2466,8.05,,S
+306,1,1,"Allison, Master. Hudson Trevor",male,0.92,1,2,113781,151.55,C22 C26,S
+307,1,1,"Fleming, Miss. Margaret",female,,0,0,17421,110.8833,,C
+308,1,1,"Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)",female,17,1,0,PC 17758,108.9,C65,C
+309,0,2,"Abelson, Mr. Samuel",male,30,1,0,P/PP 3381,24,,C
+310,1,1,"Francatelli, Miss. Laura Mabel",female,30,0,0,PC 17485,56.9292,E36,C
+311,1,1,"Hays, Miss. Margaret Bechstein",female,24,0,0,11767,83.1583,C54,C
+312,1,1,"Ryerson, Miss. Emily Borie",female,18,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+313,0,2,"Lahtinen, Mrs. William (Anna Sylfven)",female,26,1,1,250651,26,,S
+314,0,3,"Hendekovic, Mr. Ignjac",male,28,0,0,349243,7.8958,,S
+315,0,2,"Hart, Mr. Benjamin",male,43,1,1,F.C.C. 13529,26.25,,S
+316,1,3,"Nilsson, Miss. Helmina Josefina",female,26,0,0,347470,7.8542,,S
+317,1,2,"Kantor, Mrs. Sinai (Miriam Sternin)",female,24,1,0,244367,26,,S
+318,0,2,"Moraweck, Dr. Ernest",male,54,0,0,29011,14,,S
+319,1,1,"Wick, Miss. Mary Natalie",female,31,0,2,36928,164.8667,C7,S
+320,1,1,"Spedden, Mrs. Frederic Oakley (Margaretta Corning Stone)",female,40,1,1,16966,134.5,E34,C
+321,0,3,"Dennis, Mr. Samuel",male,22,0,0,A/5 21172,7.25,,S
+322,0,3,"Danoff, Mr. Yoto",male,27,0,0,349219,7.8958,,S
+323,1,2,"Slayter, Miss. Hilda Mary",female,30,0,0,234818,12.35,,Q
+324,1,2,"Caldwell, Mrs. Albert Francis (Sylvia Mae Harbaugh)",female,22,1,1,248738,29,,S
+325,0,3,"Sage, Mr. George John Jr",male,,8,2,CA. 2343,69.55,,S
+326,1,1,"Young, Miss. Marie Grice",female,36,0,0,PC 17760,135.6333,C32,C
+327,0,3,"Nysveen, Mr. Johan Hansen",male,61,0,0,345364,6.2375,,S
+328,1,2,"Ball, Mrs. (Ada E Hall)",female,36,0,0,28551,13,D,S
+329,1,3,"Goldsmith, Mrs. Frank John (Emily Alice Brown)",female,31,1,1,363291,20.525,,S
+330,1,1,"Hippach, Miss. Jean Gertrude",female,16,0,1,111361,57.9792,B18,C
+331,1,3,"McCoy, Miss. Agnes",female,,2,0,367226,23.25,,Q
+332,0,1,"Partner, Mr. Austen",male,45.5,0,0,113043,28.5,C124,S
+333,0,1,"Graham, Mr. George Edward",male,38,0,1,PC 17582,153.4625,C91,S
+334,0,3,"Vander Planke, Mr. Leo Edmondus",male,16,2,0,345764,18,,S
+335,1,1,"Frauenthal, Mrs. Henry William (Clara Heinsheimer)",female,,1,0,PC 17611,133.65,,S
+336,0,3,"Denkoff, Mr. Mitto",male,,0,0,349225,7.8958,,S
+337,0,1,"Pears, Mr. Thomas Clinton",male,29,1,0,113776,66.6,C2,S
+338,1,1,"Burns, Miss. Elizabeth Margaret",female,41,0,0,16966,134.5,E40,C
+339,1,3,"Dahl, Mr. Karl Edwart",male,45,0,0,7598,8.05,,S
+340,0,1,"Blackwell, Mr. Stephen Weart",male,45,0,0,113784,35.5,T,S
+341,1,2,"Navratil, Master. Edmond Roger",male,2,1,1,230080,26,F2,S
+342,1,1,"Fortune, Miss. Alice Elizabeth",female,24,3,2,19950,263,C23 C25 C27,S
+343,0,2,"Collander, Mr. Erik Gustaf",male,28,0,0,248740,13,,S
+344,0,2,"Sedgwick, Mr. Charles Frederick Waddington",male,25,0,0,244361,13,,S
+345,0,2,"Fox, Mr. Stanley Hubert",male,36,0,0,229236,13,,S
+346,1,2,"Brown, Miss. Amelia ""Mildred""",female,24,0,0,248733,13,F33,S
+347,1,2,"Smith, Miss. Marion Elsie",female,40,0,0,31418,13,,S
+348,1,3,"Davison, Mrs. Thomas Henry (Mary E Finck)",female,,1,0,386525,16.1,,S
+349,1,3,"Coutts, Master. William Loch ""William""",male,3,1,1,C.A. 37671,15.9,,S
+350,0,3,"Dimic, Mr. Jovan",male,42,0,0,315088,8.6625,,S
+351,0,3,"Odahl, Mr. Nils Martin",male,23,0,0,7267,9.225,,S
+352,0,1,"Williams-Lambert, Mr. Fletcher Fellows",male,,0,0,113510,35,C128,S
+353,0,3,"Elias, Mr. Tannous",male,15,1,1,2695,7.2292,,C
+354,0,3,"Arnold-Franchi, Mr. Josef",male,25,1,0,349237,17.8,,S
+355,0,3,"Yousif, Mr. Wazli",male,,0,0,2647,7.225,,C
+356,0,3,"Vanden Steen, Mr. Leo Peter",male,28,0,0,345783,9.5,,S
+357,1,1,"Bowerman, Miss. Elsie Edith",female,22,0,1,113505,55,E33,S
+358,0,2,"Funk, Miss. Annie Clemmer",female,38,0,0,237671,13,,S
+359,1,3,"McGovern, Miss. Mary",female,,0,0,330931,7.8792,,Q
+360,1,3,"Mockler, Miss. Helen Mary ""Ellie""",female,,0,0,330980,7.8792,,Q
+361,0,3,"Skoog, Mr. Wilhelm",male,40,1,4,347088,27.9,,S
+362,0,2,"del Carlo, Mr. Sebastiano",male,29,1,0,SC/PARIS 2167,27.7208,,C
+363,0,3,"Barbara, Mrs. (Catherine David)",female,45,0,1,2691,14.4542,,C
+364,0,3,"Asim, Mr. Adola",male,35,0,0,SOTON/O.Q. 3101310,7.05,,S
+365,0,3,"O'Brien, Mr. Thomas",male,,1,0,370365,15.5,,Q
+366,0,3,"Adahl, Mr. Mauritz Nils Martin",male,30,0,0,C 7076,7.25,,S
+367,1,1,"Warren, Mrs. Frank Manley (Anna Sophia Atkinson)",female,60,1,0,110813,75.25,D37,C
+368,1,3,"Moussa, Mrs. (Mantoura Boulos)",female,,0,0,2626,7.2292,,C
+369,1,3,"Jermyn, Miss. Annie",female,,0,0,14313,7.75,,Q
+370,1,1,"Aubart, Mme. Leontine Pauline",female,24,0,0,PC 17477,69.3,B35,C
+371,1,1,"Harder, Mr. George Achilles",male,25,1,0,11765,55.4417,E50,C
+372,0,3,"Wiklund, Mr. Jakob Alfred",male,18,1,0,3101267,6.4958,,S
+373,0,3,"Beavan, Mr. William Thomas",male,19,0,0,323951,8.05,,S
+374,0,1,"Ringhini, Mr. Sante",male,22,0,0,PC 17760,135.6333,,C
+375,0,3,"Palsson, Miss. Stina Viola",female,3,3,1,349909,21.075,,S
+376,1,1,"Meyer, Mrs. Edgar Joseph (Leila Saks)",female,,1,0,PC 17604,82.1708,,C
+377,1,3,"Landergren, Miss. Aurora Adelia",female,22,0,0,C 7077,7.25,,S
+378,0,1,"Widener, Mr. Harry Elkins",male,27,0,2,113503,211.5,C82,C
+379,0,3,"Betros, Mr. Tannous",male,20,0,0,2648,4.0125,,C
+380,0,3,"Gustafsson, Mr. Karl Gideon",male,19,0,0,347069,7.775,,S
+381,1,1,"Bidois, Miss. Rosalie",female,42,0,0,PC 17757,227.525,,C
+382,1,3,"Nakid, Miss. Maria (""Mary"")",female,1,0,2,2653,15.7417,,C
+383,0,3,"Tikkanen, Mr. Juho",male,32,0,0,STON/O 2. 3101293,7.925,,S
+384,1,1,"Holverson, Mrs. Alexander Oskar (Mary Aline Towner)",female,35,1,0,113789,52,,S
+385,0,3,"Plotcharsky, Mr. Vasil",male,,0,0,349227,7.8958,,S
+386,0,2,"Davies, Mr. Charles Henry",male,18,0,0,S.O.C. 14879,73.5,,S
+387,0,3,"Goodwin, Master. Sidney Leonard",male,1,5,2,CA 2144,46.9,,S
+388,1,2,"Buss, Miss. Kate",female,36,0,0,27849,13,,S
+389,0,3,"Sadlier, Mr. Matthew",male,,0,0,367655,7.7292,,Q
+390,1,2,"Lehmann, Miss. Bertha",female,17,0,0,SC 1748,12,,C
+391,1,1,"Carter, Mr. William Ernest",male,36,1,2,113760,120,B96 B98,S
+392,1,3,"Jansson, Mr. Carl Olof",male,21,0,0,350034,7.7958,,S
+393,0,3,"Gustafsson, Mr. Johan Birger",male,28,2,0,3101277,7.925,,S
+394,1,1,"Newell, Miss. Marjorie",female,23,1,0,35273,113.275,D36,C
+395,1,3,"Sandstrom, Mrs. Hjalmar (Agnes Charlotta Bengtsson)",female,24,0,2,PP 9549,16.7,G6,S
+396,0,3,"Johansson, Mr. Erik",male,22,0,0,350052,7.7958,,S
+397,0,3,"Olsson, Miss. Elina",female,31,0,0,350407,7.8542,,S
+398,0,2,"McKane, Mr. Peter David",male,46,0,0,28403,26,,S
+399,0,2,"Pain, Dr. Alfred",male,23,0,0,244278,10.5,,S
+400,1,2,"Trout, Mrs. William H (Jessie L)",female,28,0,0,240929,12.65,,S
+401,1,3,"Niskanen, Mr. Juha",male,39,0,0,STON/O 2. 3101289,7.925,,S
+402,0,3,"Adams, Mr. John",male,26,0,0,341826,8.05,,S
+403,0,3,"Jussila, Miss. Mari Aina",female,21,1,0,4137,9.825,,S
+404,0,3,"Hakkarainen, Mr. Pekka Pietari",male,28,1,0,STON/O2. 3101279,15.85,,S
+405,0,3,"Oreskovic, Miss. Marija",female,20,0,0,315096,8.6625,,S
+406,0,2,"Gale, Mr. Shadrach",male,34,1,0,28664,21,,S
+407,0,3,"Widegren, Mr. Carl/Charles Peter",male,51,0,0,347064,7.75,,S
+408,1,2,"Richards, Master. William Rowe",male,3,1,1,29106,18.75,,S
+409,0,3,"Birkeland, Mr. Hans Martin Monsen",male,21,0,0,312992,7.775,,S
+410,0,3,"Lefebre, Miss. Ida",female,,3,1,4133,25.4667,,S
+411,0,3,"Sdycoff, Mr. Todor",male,,0,0,349222,7.8958,,S
+412,0,3,"Hart, Mr. Henry",male,,0,0,394140,6.8583,,Q
+413,1,1,"Minahan, Miss. Daisy E",female,33,1,0,19928,90,C78,Q
+414,0,2,"Cunningham, Mr. Alfred Fleming",male,,0,0,239853,0,,S
+415,1,3,"Sundman, Mr. Johan Julian",male,44,0,0,STON/O 2. 3101269,7.925,,S
+416,0,3,"Meek, Mrs. Thomas (Annie Louise Rowley)",female,,0,0,343095,8.05,,S
+417,1,2,"Drew, Mrs. James Vivian (Lulu Thorne Christian)",female,34,1,1,28220,32.5,,S
+418,1,2,"Silven, Miss. Lyyli Karoliina",female,18,0,2,250652,13,,S
+419,0,2,"Matthews, Mr. William John",male,30,0,0,28228,13,,S
+420,0,3,"Van Impe, Miss. Catharina",female,10,0,2,345773,24.15,,S
+421,0,3,"Gheorgheff, Mr. Stanio",male,,0,0,349254,7.8958,,C
+422,0,3,"Charters, Mr. David",male,21,0,0,A/5. 13032,7.7333,,Q
+423,0,3,"Zimmerman, Mr. Leo",male,29,0,0,315082,7.875,,S
+424,0,3,"Danbom, Mrs. Ernst Gilbert (Anna Sigrid Maria Brogren)",female,28,1,1,347080,14.4,,S
+425,0,3,"Rosblom, Mr. Viktor Richard",male,18,1,1,370129,20.2125,,S
+426,0,3,"Wiseman, Mr. Phillippe",male,,0,0,A/4. 34244,7.25,,S
+427,1,2,"Clarke, Mrs. Charles V (Ada Maria Winfield)",female,28,1,0,2003,26,,S
+428,1,2,"Phillips, Miss. Kate Florence (""Mrs Kate Louise Phillips Marshall"")",female,19,0,0,250655,26,,S
+429,0,3,"Flynn, Mr. James",male,,0,0,364851,7.75,,Q
+430,1,3,"Pickard, Mr. Berk (Berk Trembisky)",male,32,0,0,SOTON/O.Q. 392078,8.05,E10,S
+431,1,1,"Bjornstrom-Steffansson, Mr. Mauritz Hakan",male,28,0,0,110564,26.55,C52,S
+432,1,3,"Thorneycroft, Mrs. Percival (Florence Kate White)",female,,1,0,376564,16.1,,S
+433,1,2,"Louch, Mrs. Charles Alexander (Alice Adelaide Slow)",female,42,1,0,SC/AH 3085,26,,S
+434,0,3,"Kallio, Mr. Nikolai Erland",male,17,0,0,STON/O 2. 3101274,7.125,,S
+435,0,1,"Silvey, Mr. William Baird",male,50,1,0,13507,55.9,E44,S
+436,1,1,"Carter, Miss. Lucile Polk",female,14,1,2,113760,120,B96 B98,S
+437,0,3,"Ford, Miss. Doolina Margaret ""Daisy""",female,21,2,2,W./C. 6608,34.375,,S
+438,1,2,"Richards, Mrs. Sidney (Emily Hocking)",female,24,2,3,29106,18.75,,S
+439,0,1,"Fortune, Mr. Mark",male,64,1,4,19950,263,C23 C25 C27,S
+440,0,2,"Kvillner, Mr. Johan Henrik Johannesson",male,31,0,0,C.A. 18723,10.5,,S
+441,1,2,"Hart, Mrs. Benjamin (Esther Ada Bloomfield)",female,45,1,1,F.C.C. 13529,26.25,,S
+442,0,3,"Hampe, Mr. Leon",male,20,0,0,345769,9.5,,S
+443,0,3,"Petterson, Mr. Johan Emil",male,25,1,0,347076,7.775,,S
+444,1,2,"Reynaldo, Ms. Encarnacion",female,28,0,0,230434,13,,S
+445,1,3,"Johannesen-Bratthammer, Mr. Bernt",male,,0,0,65306,8.1125,,S
+446,1,1,"Dodge, Master. Washington",male,4,0,2,33638,81.8583,A34,S
+447,1,2,"Mellinger, Miss. Madeleine Violet",female,13,0,1,250644,19.5,,S
+448,1,1,"Seward, Mr. Frederic Kimber",male,34,0,0,113794,26.55,,S
+449,1,3,"Baclini, Miss. Marie Catherine",female,5,2,1,2666,19.2583,,C
+450,1,1,"Peuchen, Major. Arthur Godfrey",male,52,0,0,113786,30.5,C104,S
+451,0,2,"West, Mr. Edwy Arthur",male,36,1,2,C.A. 34651,27.75,,S
+452,0,3,"Hagland, Mr. Ingvald Olai Olsen",male,,1,0,65303,19.9667,,S
+453,0,1,"Foreman, Mr. Benjamin Laventall",male,30,0,0,113051,27.75,C111,C
+454,1,1,"Goldenberg, Mr. Samuel L",male,49,1,0,17453,89.1042,C92,C
+455,0,3,"Peduzzi, Mr. Joseph",male,,0,0,A/5 2817,8.05,,S
+456,1,3,"Jalsevac, Mr. Ivan",male,29,0,0,349240,7.8958,,C
+457,0,1,"Millet, Mr. Francis Davis",male,65,0,0,13509,26.55,E38,S
+458,1,1,"Kenyon, Mrs. Frederick R (Marion)",female,,1,0,17464,51.8625,D21,S
+459,1,2,"Toomey, Miss. Ellen",female,50,0,0,F.C.C. 13531,10.5,,S
+460,0,3,"O'Connor, Mr. Maurice",male,,0,0,371060,7.75,,Q
+461,1,1,"Anderson, Mr. Harry",male,48,0,0,19952,26.55,E12,S
+462,0,3,"Morley, Mr. William",male,34,0,0,364506,8.05,,S
+463,0,1,"Gee, Mr. Arthur H",male,47,0,0,111320,38.5,E63,S
+464,0,2,"Milling, Mr. Jacob Christian",male,48,0,0,234360,13,,S
+465,0,3,"Maisner, Mr. Simon",male,,0,0,A/S 2816,8.05,,S
+466,0,3,"Goncalves, Mr. Manuel Estanslas",male,38,0,0,SOTON/O.Q. 3101306,7.05,,S
+467,0,2,"Campbell, Mr. William",male,,0,0,239853,0,,S
+468,0,1,"Smart, Mr. John Montgomery",male,56,0,0,113792,26.55,,S
+469,0,3,"Scanlan, Mr. James",male,,0,0,36209,7.725,,Q
+470,1,3,"Baclini, Miss. Helene Barbara",female,0.75,2,1,2666,19.2583,,C
+471,0,3,"Keefe, Mr. Arthur",male,,0,0,323592,7.25,,S
+472,0,3,"Cacic, Mr. Luka",male,38,0,0,315089,8.6625,,S
+473,1,2,"West, Mrs. Edwy Arthur (Ada Mary Worth)",female,33,1,2,C.A. 34651,27.75,,S
+474,1,2,"Jerwan, Mrs. Amin S (Marie Marthe Thuillard)",female,23,0,0,SC/AH Basle 541,13.7917,D,C
+475,0,3,"Strandberg, Miss. Ida Sofia",female,22,0,0,7553,9.8375,,S
+476,0,1,"Clifford, Mr. George Quincy",male,,0,0,110465,52,A14,S
+477,0,2,"Renouf, Mr. Peter Henry",male,34,1,0,31027,21,,S
+478,0,3,"Braund, Mr. Lewis Richard",male,29,1,0,3460,7.0458,,S
+479,0,3,"Karlsson, Mr. Nils August",male,22,0,0,350060,7.5208,,S
+480,1,3,"Hirvonen, Miss. Hildur E",female,2,0,1,3101298,12.2875,,S
+481,0,3,"Goodwin, Master. Harold Victor",male,9,5,2,CA 2144,46.9,,S
+482,0,2,"Frost, Mr. Anthony Wood ""Archie""",male,,0,0,239854,0,,S
+483,0,3,"Rouse, Mr. Richard Henry",male,50,0,0,A/5 3594,8.05,,S
+484,1,3,"Turkula, Mrs. (Hedwig)",female,63,0,0,4134,9.5875,,S
+485,1,1,"Bishop, Mr. Dickinson H",male,25,1,0,11967,91.0792,B49,C
+486,0,3,"Lefebre, Miss. Jeannie",female,,3,1,4133,25.4667,,S
+487,1,1,"Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby)",female,35,1,0,19943,90,C93,S
+488,0,1,"Kent, Mr. Edward Austin",male,58,0,0,11771,29.7,B37,C
+489,0,3,"Somerton, Mr. Francis William",male,30,0,0,A.5. 18509,8.05,,S
+490,1,3,"Coutts, Master. Eden Leslie ""Neville""",male,9,1,1,C.A. 37671,15.9,,S
+491,0,3,"Hagland, Mr. Konrad Mathias Reiersen",male,,1,0,65304,19.9667,,S
+492,0,3,"Windelov, Mr. Einar",male,21,0,0,SOTON/OQ 3101317,7.25,,S
+493,0,1,"Molson, Mr. Harry Markland",male,55,0,0,113787,30.5,C30,S
+494,0,1,"Artagaveytia, Mr. Ramon",male,71,0,0,PC 17609,49.5042,,C
+495,0,3,"Stanley, Mr. Edward Roland",male,21,0,0,A/4 45380,8.05,,S
+496,0,3,"Yousseff, Mr. Gerious",male,,0,0,2627,14.4583,,C
+497,1,1,"Eustis, Miss. Elizabeth Mussey",female,54,1,0,36947,78.2667,D20,C
+498,0,3,"Shellard, Mr. Frederick William",male,,0,0,C.A. 6212,15.1,,S
+499,0,1,"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)",female,25,1,2,113781,151.55,C22 C26,S
+500,0,3,"Svensson, Mr. Olof",male,24,0,0,350035,7.7958,,S
+501,0,3,"Calic, Mr. Petar",male,17,0,0,315086,8.6625,,S
+502,0,3,"Canavan, Miss. Mary",female,21,0,0,364846,7.75,,Q
+503,0,3,"O'Sullivan, Miss. Bridget Mary",female,,0,0,330909,7.6292,,Q
+504,0,3,"Laitinen, Miss. Kristina Sofia",female,37,0,0,4135,9.5875,,S
+505,1,1,"Maioni, Miss. Roberta",female,16,0,0,110152,86.5,B79,S
+506,0,1,"Penasco y Castellana, Mr. Victor de Satode",male,18,1,0,PC 17758,108.9,C65,C
+507,1,2,"Quick, Mrs. Frederick Charles (Jane Richards)",female,33,0,2,26360,26,,S
+508,1,1,"Bradley, Mr. George (""George Arthur Brayton"")",male,,0,0,111427,26.55,,S
+509,0,3,"Olsen, Mr. Henry Margido",male,28,0,0,C 4001,22.525,,S
+510,1,3,"Lang, Mr. Fang",male,26,0,0,1601,56.4958,,S
+511,1,3,"Daly, Mr. Eugene Patrick",male,29,0,0,382651,7.75,,Q
+512,0,3,"Webber, Mr. James",male,,0,0,SOTON/OQ 3101316,8.05,,S
+513,1,1,"McGough, Mr. James Robert",male,36,0,0,PC 17473,26.2875,E25,S
+514,1,1,"Rothschild, Mrs. Martin (Elizabeth L. Barrett)",female,54,1,0,PC 17603,59.4,,C
+515,0,3,"Coleff, Mr. Satio",male,24,0,0,349209,7.4958,,S
+516,0,1,"Walker, Mr. William Anderson",male,47,0,0,36967,34.0208,D46,S
+517,1,2,"Lemore, Mrs. (Amelia Milley)",female,34,0,0,C.A. 34260,10.5,F33,S
+518,0,3,"Ryan, Mr. Patrick",male,,0,0,371110,24.15,,Q
+519,1,2,"Angle, Mrs. William A (Florence ""Mary"" Agnes Hughes)",female,36,1,0,226875,26,,S
+520,0,3,"Pavlovic, Mr. Stefo",male,32,0,0,349242,7.8958,,S
+521,1,1,"Perreault, Miss. Anne",female,30,0,0,12749,93.5,B73,S
+522,0,3,"Vovk, Mr. Janko",male,22,0,0,349252,7.8958,,S
+523,0,3,"Lahoud, Mr. Sarkis",male,,0,0,2624,7.225,,C
+524,1,1,"Hippach, Mrs. Louis Albert (Ida Sophia Fischer)",female,44,0,1,111361,57.9792,B18,C
+525,0,3,"Kassem, Mr. Fared",male,,0,0,2700,7.2292,,C
+526,0,3,"Farrell, Mr. James",male,40.5,0,0,367232,7.75,,Q
+527,1,2,"Ridsdale, Miss. Lucy",female,50,0,0,W./C. 14258,10.5,,S
+528,0,1,"Farthing, Mr. John",male,,0,0,PC 17483,221.7792,C95,S
+529,0,3,"Salonen, Mr. Johan Werner",male,39,0,0,3101296,7.925,,S
+530,0,2,"Hocking, Mr. Richard George",male,23,2,1,29104,11.5,,S
+531,1,2,"Quick, Miss. Phyllis May",female,2,1,1,26360,26,,S
+532,0,3,"Toufik, Mr. Nakli",male,,0,0,2641,7.2292,,C
+533,0,3,"Elias, Mr. Joseph Jr",male,17,1,1,2690,7.2292,,C
+534,1,3,"Peter, Mrs. Catherine (Catherine Rizk)",female,,0,2,2668,22.3583,,C
+535,0,3,"Cacic, Miss. Marija",female,30,0,0,315084,8.6625,,S
+536,1,2,"Hart, Miss. Eva Miriam",female,7,0,2,F.C.C. 13529,26.25,,S
+537,0,1,"Butt, Major. Archibald Willingham",male,45,0,0,113050,26.55,B38,S
+538,1,1,"LeRoy, Miss. Bertha",female,30,0,0,PC 17761,106.425,,C
+539,0,3,"Risien, Mr. Samuel Beard",male,,0,0,364498,14.5,,S
+540,1,1,"Frolicher, Miss. Hedwig Margaritha",female,22,0,2,13568,49.5,B39,C
+541,1,1,"Crosby, Miss. Harriet R",female,36,0,2,WE/P 5735,71,B22,S
+542,0,3,"Andersson, Miss. Ingeborg Constanzia",female,9,4,2,347082,31.275,,S
+543,0,3,"Andersson, Miss. Sigrid Elisabeth",female,11,4,2,347082,31.275,,S
+544,1,2,"Beane, Mr. Edward",male,32,1,0,2908,26,,S
+545,0,1,"Douglas, Mr. Walter Donald",male,50,1,0,PC 17761,106.425,C86,C
+546,0,1,"Nicholson, Mr. Arthur Ernest",male,64,0,0,693,26,,S
+547,1,2,"Beane, Mrs. Edward (Ethel Clarke)",female,19,1,0,2908,26,,S
+548,1,2,"Padro y Manent, Mr. Julian",male,,0,0,SC/PARIS 2146,13.8625,,C
+549,0,3,"Goldsmith, Mr. Frank John",male,33,1,1,363291,20.525,,S
+550,1,2,"Davies, Master. John Morgan Jr",male,8,1,1,C.A. 33112,36.75,,S
+551,1,1,"Thayer, Mr. John Borland Jr",male,17,0,2,17421,110.8833,C70,C
+552,0,2,"Sharp, Mr. Percival James R",male,27,0,0,244358,26,,S
+553,0,3,"O'Brien, Mr. Timothy",male,,0,0,330979,7.8292,,Q
+554,1,3,"Leeni, Mr. Fahim (""Philip Zenni"")",male,22,0,0,2620,7.225,,C
+555,1,3,"Ohman, Miss. Velin",female,22,0,0,347085,7.775,,S
+556,0,1,"Wright, Mr. George",male,62,0,0,113807,26.55,,S
+557,1,1,"Duff Gordon, Lady. (Lucille Christiana Sutherland) (""Mrs Morgan"")",female,48,1,0,11755,39.6,A16,C
+558,0,1,"Robbins, Mr. Victor",male,,0,0,PC 17757,227.525,,C
+559,1,1,"Taussig, Mrs. Emil (Tillie Mandelbaum)",female,39,1,1,110413,79.65,E67,S
+560,1,3,"de Messemaeker, Mrs. Guillaume Joseph (Emma)",female,36,1,0,345572,17.4,,S
+561,0,3,"Morrow, Mr. Thomas Rowan",male,,0,0,372622,7.75,,Q
+562,0,3,"Sivic, Mr. Husein",male,40,0,0,349251,7.8958,,S
+563,0,2,"Norman, Mr. Robert Douglas",male,28,0,0,218629,13.5,,S
+564,0,3,"Simmons, Mr. John",male,,0,0,SOTON/OQ 392082,8.05,,S
+565,0,3,"Meanwell, Miss. (Marion Ogden)",female,,0,0,SOTON/O.Q. 392087,8.05,,S
+566,0,3,"Davies, Mr. Alfred J",male,24,2,0,A/4 48871,24.15,,S
+567,0,3,"Stoytcheff, Mr. Ilia",male,19,0,0,349205,7.8958,,S
+568,0,3,"Palsson, Mrs. Nils (Alma Cornelia Berglund)",female,29,0,4,349909,21.075,,S
+569,0,3,"Doharr, Mr. Tannous",male,,0,0,2686,7.2292,,C
+570,1,3,"Jonsson, Mr. Carl",male,32,0,0,350417,7.8542,,S
+571,1,2,"Harris, Mr. George",male,62,0,0,S.W./PP 752,10.5,,S
+572,1,1,"Appleton, Mrs. Edward Dale (Charlotte Lamson)",female,53,2,0,11769,51.4792,C101,S
+573,1,1,"Flynn, Mr. John Irwin (""Irving"")",male,36,0,0,PC 17474,26.3875,E25,S
+574,1,3,"Kelly, Miss. Mary",female,,0,0,14312,7.75,,Q
+575,0,3,"Rush, Mr. Alfred George John",male,16,0,0,A/4. 20589,8.05,,S
+576,0,3,"Patchett, Mr. George",male,19,0,0,358585,14.5,,S
+577,1,2,"Garside, Miss. Ethel",female,34,0,0,243880,13,,S
+578,1,1,"Silvey, Mrs. William Baird (Alice Munger)",female,39,1,0,13507,55.9,E44,S
+579,0,3,"Caram, Mrs. Joseph (Maria Elias)",female,,1,0,2689,14.4583,,C
+580,1,3,"Jussila, Mr. Eiriik",male,32,0,0,STON/O 2. 3101286,7.925,,S
+581,1,2,"Christy, Miss. Julie Rachel",female,25,1,1,237789,30,,S
+582,1,1,"Thayer, Mrs. John Borland (Marian Longstreth Morris)",female,39,1,1,17421,110.8833,C68,C
+583,0,2,"Downton, Mr. William James",male,54,0,0,28403,26,,S
+584,0,1,"Ross, Mr. John Hugo",male,36,0,0,13049,40.125,A10,C
+585,0,3,"Paulner, Mr. Uscher",male,,0,0,3411,8.7125,,C
+586,1,1,"Taussig, Miss. Ruth",female,18,0,2,110413,79.65,E68,S
+587,0,2,"Jarvis, Mr. John Denzil",male,47,0,0,237565,15,,S
+588,1,1,"Frolicher-Stehli, Mr. Maxmillian",male,60,1,1,13567,79.2,B41,C
+589,0,3,"Gilinski, Mr. Eliezer",male,22,0,0,14973,8.05,,S
+590,0,3,"Murdlin, Mr. Joseph",male,,0,0,A./5. 3235,8.05,,S
+591,0,3,"Rintamaki, Mr. Matti",male,35,0,0,STON/O 2. 3101273,7.125,,S
+592,1,1,"Stephenson, Mrs. Walter Bertram (Martha Eustis)",female,52,1,0,36947,78.2667,D20,C
+593,0,3,"Elsbury, Mr. William James",male,47,0,0,A/5 3902,7.25,,S
+594,0,3,"Bourke, Miss. Mary",female,,0,2,364848,7.75,,Q
+595,0,2,"Chapman, Mr. John Henry",male,37,1,0,SC/AH 29037,26,,S
+596,0,3,"Van Impe, Mr. Jean Baptiste",male,36,1,1,345773,24.15,,S
+597,1,2,"Leitch, Miss. Jessie Wills",female,,0,0,248727,33,,S
+598,0,3,"Johnson, Mr. Alfred",male,49,0,0,LINE,0,,S
+599,0,3,"Boulos, Mr. Hanna",male,,0,0,2664,7.225,,C
+600,1,1,"Duff Gordon, Sir. Cosmo Edmund (""Mr Morgan"")",male,49,1,0,PC 17485,56.9292,A20,C
+601,1,2,"Jacobsohn, Mrs. Sidney Samuel (Amy Frances Christy)",female,24,2,1,243847,27,,S
+602,0,3,"Slabenoff, Mr. Petco",male,,0,0,349214,7.8958,,S
+603,0,1,"Harrington, Mr. Charles H",male,,0,0,113796,42.4,,S
+604,0,3,"Torber, Mr. Ernst William",male,44,0,0,364511,8.05,,S
+605,1,1,"Homer, Mr. Harry (""Mr E Haven"")",male,35,0,0,111426,26.55,,C
+606,0,3,"Lindell, Mr. Edvard Bengtsson",male,36,1,0,349910,15.55,,S
+607,0,3,"Karaic, Mr. Milan",male,30,0,0,349246,7.8958,,S
+608,1,1,"Daniel, Mr. Robert Williams",male,27,0,0,113804,30.5,,S
+609,1,2,"Laroche, Mrs. Joseph (Juliette Marie Louise Lafargue)",female,22,1,2,SC/Paris 2123,41.5792,,C
+610,1,1,"Shutes, Miss. Elizabeth W",female,40,0,0,PC 17582,153.4625,C125,S
+611,0,3,"Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren)",female,39,1,5,347082,31.275,,S
+612,0,3,"Jardin, Mr. Jose Neto",male,,0,0,SOTON/O.Q. 3101305,7.05,,S
+613,1,3,"Murphy, Miss. Margaret Jane",female,,1,0,367230,15.5,,Q
+614,0,3,"Horgan, Mr. John",male,,0,0,370377,7.75,,Q
+615,0,3,"Brocklebank, Mr. William Alfred",male,35,0,0,364512,8.05,,S
+616,1,2,"Herman, Miss. Alice",female,24,1,2,220845,65,,S
+617,0,3,"Danbom, Mr. Ernst Gilbert",male,34,1,1,347080,14.4,,S
+618,0,3,"Lobb, Mrs. William Arthur (Cordelia K Stanlick)",female,26,1,0,A/5. 3336,16.1,,S
+619,1,2,"Becker, Miss. Marion Louise",female,4,2,1,230136,39,F4,S
+620,0,2,"Gavey, Mr. Lawrence",male,26,0,0,31028,10.5,,S
+621,0,3,"Yasbeck, Mr. Antoni",male,27,1,0,2659,14.4542,,C
+622,1,1,"Kimball, Mr. Edwin Nelson Jr",male,42,1,0,11753,52.5542,D19,S
+623,1,3,"Nakid, Mr. Sahid",male,20,1,1,2653,15.7417,,C
+624,0,3,"Hansen, Mr. Henry Damsgaard",male,21,0,0,350029,7.8542,,S
+625,0,3,"Bowen, Mr. David John ""Dai""",male,21,0,0,54636,16.1,,S
+626,0,1,"Sutton, Mr. Frederick",male,61,0,0,36963,32.3208,D50,S
+627,0,2,"Kirkland, Rev. Charles Leonard",male,57,0,0,219533,12.35,,Q
+628,1,1,"Longley, Miss. Gretchen Fiske",female,21,0,0,13502,77.9583,D9,S
+629,0,3,"Bostandyeff, Mr. Guentcho",male,26,0,0,349224,7.8958,,S
+630,0,3,"O'Connell, Mr. Patrick D",male,,0,0,334912,7.7333,,Q
+631,1,1,"Barkworth, Mr. Algernon Henry Wilson",male,80,0,0,27042,30,A23,S
+632,0,3,"Lundahl, Mr. Johan Svensson",male,51,0,0,347743,7.0542,,S
+633,1,1,"Stahelin-Maeglin, Dr. Max",male,32,0,0,13214,30.5,B50,C
+634,0,1,"Parr, Mr. William Henry Marsh",male,,0,0,112052,0,,S
+635,0,3,"Skoog, Miss. Mabel",female,9,3,2,347088,27.9,,S
+636,1,2,"Davis, Miss. Mary",female,28,0,0,237668,13,,S
+637,0,3,"Leinonen, Mr. Antti Gustaf",male,32,0,0,STON/O 2. 3101292,7.925,,S
+638,0,2,"Collyer, Mr. Harvey",male,31,1,1,C.A. 31921,26.25,,S
+639,0,3,"Panula, Mrs. Juha (Maria Emilia Ojala)",female,41,0,5,3101295,39.6875,,S
+640,0,3,"Thorneycroft, Mr. Percival",male,,1,0,376564,16.1,,S
+641,0,3,"Jensen, Mr. Hans Peder",male,20,0,0,350050,7.8542,,S
+642,1,1,"Sagesser, Mlle. Emma",female,24,0,0,PC 17477,69.3,B35,C
+643,0,3,"Skoog, Miss. Margit Elizabeth",female,2,3,2,347088,27.9,,S
+644,1,3,"Foo, Mr. Choong",male,,0,0,1601,56.4958,,S
+645,1,3,"Baclini, Miss. Eugenie",female,0.75,2,1,2666,19.2583,,C
+646,1,1,"Harper, Mr. Henry Sleeper",male,48,1,0,PC 17572,76.7292,D33,C
+647,0,3,"Cor, Mr. Liudevit",male,19,0,0,349231,7.8958,,S
+648,1,1,"Simonius-Blumer, Col. Oberst Alfons",male,56,0,0,13213,35.5,A26,C
+649,0,3,"Willey, Mr. Edward",male,,0,0,S.O./P.P. 751,7.55,,S
+650,1,3,"Stanley, Miss. Amy Zillah Elsie",female,23,0,0,CA. 2314,7.55,,S
+651,0,3,"Mitkoff, Mr. Mito",male,,0,0,349221,7.8958,,S
+652,1,2,"Doling, Miss. Elsie",female,18,0,1,231919,23,,S
+653,0,3,"Kalvik, Mr. Johannes Halvorsen",male,21,0,0,8475,8.4333,,S
+654,1,3,"O'Leary, Miss. Hanora ""Norah""",female,,0,0,330919,7.8292,,Q
+655,0,3,"Hegarty, Miss. Hanora ""Nora""",female,18,0,0,365226,6.75,,Q
+656,0,2,"Hickman, Mr. Leonard Mark",male,24,2,0,S.O.C. 14879,73.5,,S
+657,0,3,"Radeff, Mr. Alexander",male,,0,0,349223,7.8958,,S
+658,0,3,"Bourke, Mrs. John (Catherine)",female,32,1,1,364849,15.5,,Q
+659,0,2,"Eitemiller, Mr. George Floyd",male,23,0,0,29751,13,,S
+660,0,1,"Newell, Mr. Arthur Webster",male,58,0,2,35273,113.275,D48,C
+661,1,1,"Frauenthal, Dr. Henry William",male,50,2,0,PC 17611,133.65,,S
+662,0,3,"Badt, Mr. Mohamed",male,40,0,0,2623,7.225,,C
+663,0,1,"Colley, Mr. Edward Pomeroy",male,47,0,0,5727,25.5875,E58,S
+664,0,3,"Coleff, Mr. Peju",male,36,0,0,349210,7.4958,,S
+665,1,3,"Lindqvist, Mr. Eino William",male,20,1,0,STON/O 2. 3101285,7.925,,S
+666,0,2,"Hickman, Mr. Lewis",male,32,2,0,S.O.C. 14879,73.5,,S
+667,0,2,"Butler, Mr. Reginald Fenton",male,25,0,0,234686,13,,S
+668,0,3,"Rommetvedt, Mr. Knud Paust",male,,0,0,312993,7.775,,S
+669,0,3,"Cook, Mr. Jacob",male,43,0,0,A/5 3536,8.05,,S
+670,1,1,"Taylor, Mrs. Elmer Zebley (Juliet Cummins Wright)",female,,1,0,19996,52,C126,S
+671,1,2,"Brown, Mrs. Thomas William Solomon (Elizabeth Catherine Ford)",female,40,1,1,29750,39,,S
+672,0,1,"Davidson, Mr. Thornton",male,31,1,0,F.C. 12750,52,B71,S
+673,0,2,"Mitchell, Mr. Henry Michael",male,70,0,0,C.A. 24580,10.5,,S
+674,1,2,"Wilhelms, Mr. Charles",male,31,0,0,244270,13,,S
+675,0,2,"Watson, Mr. Ennis Hastings",male,,0,0,239856,0,,S
+676,0,3,"Edvardsson, Mr. Gustaf Hjalmar",male,18,0,0,349912,7.775,,S
+677,0,3,"Sawyer, Mr. Frederick Charles",male,24.5,0,0,342826,8.05,,S
+678,1,3,"Turja, Miss. Anna Sofia",female,18,0,0,4138,9.8417,,S
+679,0,3,"Goodwin, Mrs. Frederick (Augusta Tyler)",female,43,1,6,CA 2144,46.9,,S
+680,1,1,"Cardeza, Mr. Thomas Drake Martinez",male,36,0,1,PC 17755,512.3292,B51 B53 B55,C
+681,0,3,"Peters, Miss. Katie",female,,0,0,330935,8.1375,,Q
+682,1,1,"Hassab, Mr. Hammad",male,27,0,0,PC 17572,76.7292,D49,C
+683,0,3,"Olsvigen, Mr. Thor Anderson",male,20,0,0,6563,9.225,,S
+684,0,3,"Goodwin, Mr. Charles Edward",male,14,5,2,CA 2144,46.9,,S
+685,0,2,"Brown, Mr. Thomas William Solomon",male,60,1,1,29750,39,,S
+686,0,2,"Laroche, Mr. Joseph Philippe Lemercier",male,25,1,2,SC/Paris 2123,41.5792,,C
+687,0,3,"Panula, Mr. Jaako Arnold",male,14,4,1,3101295,39.6875,,S
+688,0,3,"Dakic, Mr. Branko",male,19,0,0,349228,10.1708,,S
+689,0,3,"Fischer, Mr. Eberhard Thelander",male,18,0,0,350036,7.7958,,S
+690,1,1,"Madill, Miss. Georgette Alexandra",female,15,0,1,24160,211.3375,B5,S
+691,1,1,"Dick, Mr. Albert Adrian",male,31,1,0,17474,57,B20,S
+692,1,3,"Karun, Miss. Manca",female,4,0,1,349256,13.4167,,C
+693,1,3,"Lam, Mr. Ali",male,,0,0,1601,56.4958,,S
+694,0,3,"Saad, Mr. Khalil",male,25,0,0,2672,7.225,,C
+695,0,1,"Weir, Col. John",male,60,0,0,113800,26.55,,S
+696,0,2,"Chapman, Mr. Charles Henry",male,52,0,0,248731,13.5,,S
+697,0,3,"Kelly, Mr. James",male,44,0,0,363592,8.05,,S
+698,1,3,"Mullens, Miss. Katherine ""Katie""",female,,0,0,35852,7.7333,,Q
+699,0,1,"Thayer, Mr. John Borland",male,49,1,1,17421,110.8833,C68,C
+700,0,3,"Humblen, Mr. Adolf Mathias Nicolai Olsen",male,42,0,0,348121,7.65,F G63,S
+701,1,1,"Astor, Mrs. John Jacob (Madeleine Talmadge Force)",female,18,1,0,PC 17757,227.525,C62 C64,C
+702,1,1,"Silverthorne, Mr. Spencer Victor",male,35,0,0,PC 17475,26.2875,E24,S
+703,0,3,"Barbara, Miss. Saiide",female,18,0,1,2691,14.4542,,C
+704,0,3,"Gallagher, Mr. Martin",male,25,0,0,36864,7.7417,,Q
+705,0,3,"Hansen, Mr. Henrik Juul",male,26,1,0,350025,7.8542,,S
+706,0,2,"Morley, Mr. Henry Samuel (""Mr Henry Marshall"")",male,39,0,0,250655,26,,S
+707,1,2,"Kelly, Mrs. Florence ""Fannie""",female,45,0,0,223596,13.5,,S
+708,1,1,"Calderhead, Mr. Edward Pennington",male,42,0,0,PC 17476,26.2875,E24,S
+709,1,1,"Cleaver, Miss. Alice",female,22,0,0,113781,151.55,,S
+710,1,3,"Moubarek, Master. Halim Gonios (""William George"")",male,,1,1,2661,15.2458,,C
+711,1,1,"Mayne, Mlle. Berthe Antonine (""Mrs de Villiers"")",female,24,0,0,PC 17482,49.5042,C90,C
+712,0,1,"Klaber, Mr. Herman",male,,0,0,113028,26.55,C124,S
+713,1,1,"Taylor, Mr. Elmer Zebley",male,48,1,0,19996,52,C126,S
+714,0,3,"Larsson, Mr. August Viktor",male,29,0,0,7545,9.4833,,S
+715,0,2,"Greenberg, Mr. Samuel",male,52,0,0,250647,13,,S
+716,0,3,"Soholt, Mr. Peter Andreas Lauritz Andersen",male,19,0,0,348124,7.65,F G73,S
+717,1,1,"Endres, Miss. Caroline Louise",female,38,0,0,PC 17757,227.525,C45,C
+718,1,2,"Troutt, Miss. Edwina Celia ""Winnie""",female,27,0,0,34218,10.5,E101,S
+719,0,3,"McEvoy, Mr. Michael",male,,0,0,36568,15.5,,Q
+720,0,3,"Johnson, Mr. Malkolm Joackim",male,33,0,0,347062,7.775,,S
+721,1,2,"Harper, Miss. Annie Jessie ""Nina""",female,6,0,1,248727,33,,S
+722,0,3,"Jensen, Mr. Svend Lauritz",male,17,1,0,350048,7.0542,,S
+723,0,2,"Gillespie, Mr. William Henry",male,34,0,0,12233,13,,S
+724,0,2,"Hodges, Mr. Henry Price",male,50,0,0,250643,13,,S
+725,1,1,"Chambers, Mr. Norman Campbell",male,27,1,0,113806,53.1,E8,S
+726,0,3,"Oreskovic, Mr. Luka",male,20,0,0,315094,8.6625,,S
+727,1,2,"Renouf, Mrs. Peter Henry (Lillian Jefferys)",female,30,3,0,31027,21,,S
+728,1,3,"Mannion, Miss. Margareth",female,,0,0,36866,7.7375,,Q
+729,0,2,"Bryhl, Mr. Kurt Arnold Gottfrid",male,25,1,0,236853,26,,S
+730,0,3,"Ilmakangas, Miss. Pieta Sofia",female,25,1,0,STON/O2. 3101271,7.925,,S
+731,1,1,"Allen, Miss. Elisabeth Walton",female,29,0,0,24160,211.3375,B5,S
+732,0,3,"Hassan, Mr. Houssein G N",male,11,0,0,2699,18.7875,,C
+733,0,2,"Knight, Mr. Robert J",male,,0,0,239855,0,,S
+734,0,2,"Berriman, Mr. William John",male,23,0,0,28425,13,,S
+735,0,2,"Troupiansky, Mr. Moses Aaron",male,23,0,0,233639,13,,S
+736,0,3,"Williams, Mr. Leslie",male,28.5,0,0,54636,16.1,,S
+737,0,3,"Ford, Mrs. Edward (Margaret Ann Watson)",female,48,1,3,W./C. 6608,34.375,,S
+738,1,1,"Lesurer, Mr. Gustave J",male,35,0,0,PC 17755,512.3292,B101,C
+739,0,3,"Ivanoff, Mr. Kanio",male,,0,0,349201,7.8958,,S
+740,0,3,"Nankoff, Mr. Minko",male,,0,0,349218,7.8958,,S
+741,1,1,"Hawksford, Mr. Walter James",male,,0,0,16988,30,D45,S
+742,0,1,"Cavendish, Mr. Tyrell William",male,36,1,0,19877,78.85,C46,S
+743,1,1,"Ryerson, Miss. Susan Parker ""Suzette""",female,21,2,2,PC 17608,262.375,B57 B59 B63 B66,C
+744,0,3,"McNamee, Mr. Neal",male,24,1,0,376566,16.1,,S
+745,1,3,"Stranden, Mr. Juho",male,31,0,0,STON/O 2. 3101288,7.925,,S
+746,0,1,"Crosby, Capt. Edward Gifford",male,70,1,1,WE/P 5735,71,B22,S
+747,0,3,"Abbott, Mr. Rossmore Edward",male,16,1,1,C.A. 2673,20.25,,S
+748,1,2,"Sinkkonen, Miss. Anna",female,30,0,0,250648,13,,S
+749,0,1,"Marvin, Mr. Daniel Warner",male,19,1,0,113773,53.1,D30,S
+750,0,3,"Connaghton, Mr. Michael",male,31,0,0,335097,7.75,,Q
+751,1,2,"Wells, Miss. Joan",female,4,1,1,29103,23,,S
+752,1,3,"Moor, Master. Meier",male,6,0,1,392096,12.475,E121,S
+753,0,3,"Vande Velde, Mr. Johannes Joseph",male,33,0,0,345780,9.5,,S
+754,0,3,"Jonkoff, Mr. Lalio",male,23,0,0,349204,7.8958,,S
+755,1,2,"Herman, Mrs. Samuel (Jane Laver)",female,48,1,2,220845,65,,S
+756,1,2,"Hamalainen, Master. Viljo",male,0.67,1,1,250649,14.5,,S
+757,0,3,"Carlsson, Mr. August Sigfrid",male,28,0,0,350042,7.7958,,S
+758,0,2,"Bailey, Mr. Percy Andrew",male,18,0,0,29108,11.5,,S
+759,0,3,"Theobald, Mr. Thomas Leonard",male,34,0,0,363294,8.05,,S
+760,1,1,"Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)",female,33,0,0,110152,86.5,B77,S
+761,0,3,"Garfirth, Mr. John",male,,0,0,358585,14.5,,S
+762,0,3,"Nirva, Mr. Iisakki Antino Aijo",male,41,0,0,SOTON/O2 3101272,7.125,,S
+763,1,3,"Barah, Mr. Hanna Assi",male,20,0,0,2663,7.2292,,C
+764,1,1,"Carter, Mrs. William Ernest (Lucile Polk)",female,36,1,2,113760,120,B96 B98,S
+765,0,3,"Eklund, Mr. Hans Linus",male,16,0,0,347074,7.775,,S
+766,1,1,"Hogeboom, Mrs. John C (Anna Andrews)",female,51,1,0,13502,77.9583,D11,S
+767,0,1,"Brewe, Dr. Arthur Jackson",male,,0,0,112379,39.6,,C
+768,0,3,"Mangan, Miss. Mary",female,30.5,0,0,364850,7.75,,Q
+769,0,3,"Moran, Mr. Daniel J",male,,1,0,371110,24.15,,Q
+770,0,3,"Gronnestad, Mr. Daniel Danielsen",male,32,0,0,8471,8.3625,,S
+771,0,3,"Lievens, Mr. Rene Aime",male,24,0,0,345781,9.5,,S
+772,0,3,"Jensen, Mr. Niels Peder",male,48,0,0,350047,7.8542,,S
+773,0,2,"Mack, Mrs. (Mary)",female,57,0,0,S.O./P.P. 3,10.5,E77,S
+774,0,3,"Elias, Mr. Dibo",male,,0,0,2674,7.225,,C
+775,1,2,"Hocking, Mrs. Elizabeth (Eliza Needs)",female,54,1,3,29105,23,,S
+776,0,3,"Myhrman, Mr. Pehr Fabian Oliver Malkolm",male,18,0,0,347078,7.75,,S
+777,0,3,"Tobin, Mr. Roger",male,,0,0,383121,7.75,F38,Q
+778,1,3,"Emanuel, Miss. Virginia Ethel",female,5,0,0,364516,12.475,,S
+779,0,3,"Kilgannon, Mr. Thomas J",male,,0,0,36865,7.7375,,Q
+780,1,1,"Robert, Mrs. Edward Scott (Elisabeth Walton McMillan)",female,43,0,1,24160,211.3375,B3,S
+781,1,3,"Ayoub, Miss. Banoura",female,13,0,0,2687,7.2292,,C
+782,1,1,"Dick, Mrs. Albert Adrian (Vera Gillespie)",female,17,1,0,17474,57,B20,S
+783,0,1,"Long, Mr. Milton Clyde",male,29,0,0,113501,30,D6,S
+784,0,3,"Johnston, Mr. Andrew G",male,,1,2,W./C. 6607,23.45,,S
+785,0,3,"Ali, Mr. William",male,25,0,0,SOTON/O.Q. 3101312,7.05,,S
+786,0,3,"Harmer, Mr. Abraham (David Lishin)",male,25,0,0,374887,7.25,,S
+787,1,3,"Sjoblom, Miss. Anna Sofia",female,18,0,0,3101265,7.4958,,S
+788,0,3,"Rice, Master. George Hugh",male,8,4,1,382652,29.125,,Q
+789,1,3,"Dean, Master. Bertram Vere",male,1,1,2,C.A. 2315,20.575,,S
+790,0,1,"Guggenheim, Mr. Benjamin",male,46,0,0,PC 17593,79.2,B82 B84,C
+791,0,3,"Keane, Mr. Andrew ""Andy""",male,,0,0,12460,7.75,,Q
+792,0,2,"Gaskell, Mr. Alfred",male,16,0,0,239865,26,,S
+793,0,3,"Sage, Miss. Stella Anna",female,,8,2,CA. 2343,69.55,,S
+794,0,1,"Hoyt, Mr. William Fisher",male,,0,0,PC 17600,30.6958,,C
+795,0,3,"Dantcheff, Mr. Ristiu",male,25,0,0,349203,7.8958,,S
+796,0,2,"Otter, Mr. Richard",male,39,0,0,28213,13,,S
+797,1,1,"Leader, Dr. Alice (Farnham)",female,49,0,0,17465,25.9292,D17,S
+798,1,3,"Osman, Mrs. Mara",female,31,0,0,349244,8.6833,,S
+799,0,3,"Ibrahim Shawah, Mr. Yousseff",male,30,0,0,2685,7.2292,,C
+800,0,3,"Van Impe, Mrs. Jean Baptiste (Rosalie Paula Govaert)",female,30,1,1,345773,24.15,,S
+801,0,2,"Ponesell, Mr. Martin",male,34,0,0,250647,13,,S
+802,1,2,"Collyer, Mrs. Harvey (Charlotte Annie Tate)",female,31,1,1,C.A. 31921,26.25,,S
+803,1,1,"Carter, Master. William Thornton II",male,11,1,2,113760,120,B96 B98,S
+804,1,3,"Thomas, Master. Assad Alexander",male,0.42,0,1,2625,8.5167,,C
+805,1,3,"Hedman, Mr. Oskar Arvid",male,27,0,0,347089,6.975,,S
+806,0,3,"Johansson, Mr. Karl Johan",male,31,0,0,347063,7.775,,S
+807,0,1,"Andrews, Mr. Thomas Jr",male,39,0,0,112050,0,A36,S
+808,0,3,"Pettersson, Miss. Ellen Natalia",female,18,0,0,347087,7.775,,S
+809,0,2,"Meyer, Mr. August",male,39,0,0,248723,13,,S
+810,1,1,"Chambers, Mrs. Norman Campbell (Bertha Griggs)",female,33,1,0,113806,53.1,E8,S
+811,0,3,"Alexander, Mr. William",male,26,0,0,3474,7.8875,,S
+812,0,3,"Lester, Mr. James",male,39,0,0,A/4 48871,24.15,,S
+813,0,2,"Slemen, Mr. Richard James",male,35,0,0,28206,10.5,,S
+814,0,3,"Andersson, Miss. Ebba Iris Alfrida",female,6,4,2,347082,31.275,,S
+815,0,3,"Tomlin, Mr. Ernest Portage",male,30.5,0,0,364499,8.05,,S
+816,0,1,"Fry, Mr. Richard",male,,0,0,112058,0,B102,S
+817,0,3,"Heininen, Miss. Wendla Maria",female,23,0,0,STON/O2. 3101290,7.925,,S
+818,0,2,"Mallet, Mr. Albert",male,31,1,1,S.C./PARIS 2079,37.0042,,C
+819,0,3,"Holm, Mr. John Fredrik Alexander",male,43,0,0,C 7075,6.45,,S
+820,0,3,"Skoog, Master. Karl Thorsten",male,10,3,2,347088,27.9,,S
+821,1,1,"Hays, Mrs. Charles Melville (Clara Jennings Gregg)",female,52,1,1,12749,93.5,B69,S
+822,1,3,"Lulic, Mr. Nikola",male,27,0,0,315098,8.6625,,S
+823,0,1,"Reuchlin, Jonkheer. John George",male,38,0,0,19972,0,,S
+824,1,3,"Moor, Mrs. (Beila)",female,27,0,1,392096,12.475,E121,S
+825,0,3,"Panula, Master. Urho Abraham",male,2,4,1,3101295,39.6875,,S
+826,0,3,"Flynn, Mr. John",male,,0,0,368323,6.95,,Q
+827,0,3,"Lam, Mr. Len",male,,0,0,1601,56.4958,,S
+828,1,2,"Mallet, Master. Andre",male,1,0,2,S.C./PARIS 2079,37.0042,,C
+829,1,3,"McCormack, Mr. Thomas Joseph",male,,0,0,367228,7.75,,Q
+830,1,1,"Stone, Mrs. George Nelson (Martha Evelyn)",female,62,0,0,113572,80,B28,
+831,1,3,"Yasbeck, Mrs. Antoni (Selini Alexander)",female,15,1,0,2659,14.4542,,C
+832,1,2,"Richards, Master. George Sibley",male,0.83,1,1,29106,18.75,,S
+833,0,3,"Saad, Mr. Amin",male,,0,0,2671,7.2292,,C
+834,0,3,"Augustsson, Mr. Albert",male,23,0,0,347468,7.8542,,S
+835,0,3,"Allum, Mr. Owen George",male,18,0,0,2223,8.3,,S
+836,1,1,"Compton, Miss. Sara Rebecca",female,39,1,1,PC 17756,83.1583,E49,C
+837,0,3,"Pasic, Mr. Jakob",male,21,0,0,315097,8.6625,,S
+838,0,3,"Sirota, Mr. Maurice",male,,0,0,392092,8.05,,S
+839,1,3,"Chip, Mr. Chang",male,32,0,0,1601,56.4958,,S
+840,1,1,"Marechal, Mr. Pierre",male,,0,0,11774,29.7,C47,C
+841,0,3,"Alhomaki, Mr. Ilmari Rudolf",male,20,0,0,SOTON/O2 3101287,7.925,,S
+842,0,2,"Mudd, Mr. Thomas Charles",male,16,0,0,S.O./P.P. 3,10.5,,S
+843,1,1,"Serepeca, Miss. Augusta",female,30,0,0,113798,31,,C
+844,0,3,"Lemberopolous, Mr. Peter L",male,34.5,0,0,2683,6.4375,,C
+845,0,3,"Culumovic, Mr. Jeso",male,17,0,0,315090,8.6625,,S
+846,0,3,"Abbing, Mr. Anthony",male,42,0,0,C.A. 5547,7.55,,S
+847,0,3,"Sage, Mr. Douglas Bullen",male,,8,2,CA. 2343,69.55,,S
+848,0,3,"Markoff, Mr. Marin",male,35,0,0,349213,7.8958,,C
+849,0,2,"Harper, Rev. John",male,28,0,1,248727,33,,S
+850,1,1,"Goldenberg, Mrs. Samuel L (Edwiga Grabowska)",female,,1,0,17453,89.1042,C92,C
+851,0,3,"Andersson, Master. Sigvard Harald Elias",male,4,4,2,347082,31.275,,S
+852,0,3,"Svensson, Mr. Johan",male,74,0,0,347060,7.775,,S
+853,0,3,"Boulos, Miss. Nourelain",female,9,1,1,2678,15.2458,,C
+854,1,1,"Lines, Miss. Mary Conover",female,16,0,1,PC 17592,39.4,D28,S
+855,0,2,"Carter, Mrs. Ernest Courtenay (Lilian Hughes)",female,44,1,0,244252,26,,S
+856,1,3,"Aks, Mrs. Sam (Leah Rosen)",female,18,0,1,392091,9.35,,S
+857,1,1,"Wick, Mrs. George Dennick (Mary Hitchcock)",female,45,1,1,36928,164.8667,,S
+858,1,1,"Daly, Mr. Peter Denis ",male,51,0,0,113055,26.55,E17,S
+859,1,3,"Baclini, Mrs. Solomon (Latifa Qurban)",female,24,0,3,2666,19.2583,,C
+860,0,3,"Razi, Mr. Raihed",male,,0,0,2629,7.2292,,C
+861,0,3,"Hansen, Mr. Claus Peter",male,41,2,0,350026,14.1083,,S
+862,0,2,"Giles, Mr. Frederick Edward",male,21,1,0,28134,11.5,,S
+863,1,1,"Swift, Mrs. Frederick Joel (Margaret Welles Barron)",female,48,0,0,17466,25.9292,D17,S
+864,0,3,"Sage, Miss. Dorothy Edith ""Dolly""",female,,8,2,CA. 2343,69.55,,S
+865,0,2,"Gill, Mr. John William",male,24,0,0,233866,13,,S
+866,1,2,"Bystrom, Mrs. (Karolina)",female,42,0,0,236852,13,,S
+867,1,2,"Duran y More, Miss. Asuncion",female,27,1,0,SC/PARIS 2149,13.8583,,C
+868,0,1,"Roebling, Mr. Washington Augustus II",male,31,0,0,PC 17590,50.4958,A24,S
+869,0,3,"van Melkebeke, Mr. Philemon",male,,0,0,345777,9.5,,S
+870,1,3,"Johnson, Master. Harold Theodor",male,4,1,1,347742,11.1333,,S
+871,0,3,"Balkic, Mr. Cerin",male,26,0,0,349248,7.8958,,S
+872,1,1,"Beckwith, Mrs. Richard Leonard (Sallie Monypeny)",female,47,1,1,11751,52.5542,D35,S
+873,0,1,"Carlsson, Mr. Frans Olof",male,33,0,0,695,5,B51 B53 B55,S
+874,0,3,"Vander Cruyssen, Mr. Victor",male,47,0,0,345765,9,,S
+875,1,2,"Abelson, Mrs. Samuel (Hannah Wizosky)",female,28,1,0,P/PP 3381,24,,C
+876,1,3,"Najib, Miss. Adele Kiamie ""Jane""",female,15,0,0,2667,7.225,,C
+877,0,3,"Gustafsson, Mr. Alfred Ossian",male,20,0,0,7534,9.8458,,S
+878,0,3,"Petroff, Mr. Nedelio",male,19,0,0,349212,7.8958,,S
+879,0,3,"Laleff, Mr. Kristo",male,,0,0,349217,7.8958,,S
+880,1,1,"Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)",female,56,0,1,11767,83.1583,C50,C
+881,1,2,"Shelley, Mrs. William (Imanita Parrish Hall)",female,25,0,1,230433,26,,S
+882,0,3,"Markun, Mr. Johann",male,33,0,0,349257,7.8958,,S
+883,0,3,"Dahlberg, Miss. Gerda Ulrika",female,22,0,0,7552,10.5167,,S
+884,0,2,"Banfield, Mr. Frederick James",male,28,0,0,C.A./SOTON 34068,10.5,,S
+885,0,3,"Sutehall, Mr. Henry Jr",male,25,0,0,SOTON/OQ 392076,7.05,,S
+886,0,3,"Rice, Mrs. William (Margaret Norton)",female,39,0,5,382652,29.125,,Q
+887,0,2,"Montvila, Rev. Juozas",male,27,0,0,211536,13,,S
+888,1,1,"Graham, Miss. Margaret Edith",female,19,0,0,112053,30,B42,S
+889,0,3,"Johnston, Miss. Catherine Helen ""Carrie""",female,,1,2,W./C. 6607,23.45,,S
+890,1,1,"Behr, Mr. Karl Howell",male,26,0,0,111369,30,C148,C
+891,0,3,"Dooley, Mr. Patrick",male,32,0,0,370376,7.75,,Q
diff --git a/demo/zip_files/run.ipynb b/demo/zip_files/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a2732e7f190d2ae4a542cf615a6105d59f904aa9
--- /dev/null
+++ b/demo/zip_files/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: zip_files"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/titanic.csv https://github.com/gradio-app/gradio/raw/main/demo/zip_files/files/titanic.csv"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import os\n", "from zipfile import ZipFile\n", "\n", "import gradio as gr\n", "\n", "\n", "def zip_files(files):\n", " with ZipFile(\"tmp.zip\", \"w\") as zipObj:\n", " for idx, file in enumerate(files):\n", " zipObj.write(file.name, file.name.split(\"/\")[-1])\n", " return \"tmp.zip\"\n", "\n", "demo = gr.Interface(\n", " zip_files,\n", " gr.File(file_count=\"multiple\", file_types=[\"text\", \".json\", \".csv\"]),\n", " \"file\",\n", " examples=[[[os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", " os.path.join(os.path.abspath(''),\"files/titanic.csv\"), \n", " os.path.join(os.path.abspath(''),\"files/titanic.csv\")]]], \n", " cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/zip_files/run.py b/demo/zip_files/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..1ae6436c67542f82a94ca7c6d9675974b2503710
--- /dev/null
+++ b/demo/zip_files/run.py
@@ -0,0 +1,24 @@
+import os
+from zipfile import ZipFile
+
+import gradio as gr
+
+
+def zip_files(files):
+ with ZipFile("tmp.zip", "w") as zipObj:
+ for idx, file in enumerate(files):
+ zipObj.write(file.name, file.name.split("/")[-1])
+ return "tmp.zip"
+
+demo = gr.Interface(
+ zip_files,
+ gr.File(file_count="multiple", file_types=["text", ".json", ".csv"]),
+ "file",
+ examples=[[[os.path.join(os.path.dirname(__file__),"files/titanic.csv"),
+ os.path.join(os.path.dirname(__file__),"files/titanic.csv"),
+ os.path.join(os.path.dirname(__file__),"files/titanic.csv")]]],
+ cache_examples=True
+)
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/zip_files/screenshot.png b/demo/zip_files/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..64591ff8a23e8c77759f60f7caddc61fb84f3324
Binary files /dev/null and b/demo/zip_files/screenshot.png differ
diff --git a/demo/zip_to_json/run.ipynb b/demo/zip_to_json/run.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..02230b11ed8aedea564435abf835c2a83d6a2d04
--- /dev/null
+++ b/demo/zip_to_json/run.ipynb
@@ -0,0 +1 @@
+{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: zip_to_json"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["from zipfile import ZipFile\n", "\n", "import gradio as gr\n", "\n", "\n", "def zip_to_json(file_obj):\n", " files = []\n", " with ZipFile(file_obj.name) as zfile:\n", " for zinfo in zfile.infolist():\n", " files.append(\n", " {\n", " \"name\": zinfo.filename,\n", " \"file_size\": zinfo.file_size,\n", " \"compressed_size\": zinfo.compress_size,\n", " }\n", " )\n", " return files\n", "\n", "\n", "demo = gr.Interface(zip_to_json, \"file\", \"json\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
\ No newline at end of file
diff --git a/demo/zip_to_json/run.py b/demo/zip_to_json/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..2500b409d12175e25cc4062696624e85f5f78124
--- /dev/null
+++ b/demo/zip_to_json/run.py
@@ -0,0 +1,23 @@
+from zipfile import ZipFile
+
+import gradio as gr
+
+
+def zip_to_json(file_obj):
+ files = []
+ with ZipFile(file_obj.name) as zfile:
+ for zinfo in zfile.infolist():
+ files.append(
+ {
+ "name": zinfo.filename,
+ "file_size": zinfo.file_size,
+ "compressed_size": zinfo.compress_size,
+ }
+ )
+ return files
+
+
+demo = gr.Interface(zip_to_json, "file", "json")
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/demo/zip_to_json/screenshot.png b/demo/zip_to_json/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..0620b7885c984d4af6220c785eab51d4ae66a474
Binary files /dev/null and b/demo/zip_to_json/screenshot.png differ
diff --git a/globals.d.ts b/globals.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da2de542a724d45f07dfeaed6162654740f08255
--- /dev/null
+++ b/globals.d.ts
@@ -0,0 +1,35 @@
+declare global {
+ interface Window {
+ __gradio_mode__: "app" | "website";
+ __gradio_space__: string | null;
+ launchGradio: Function;
+ launchGradioFromSpaces: Function;
+ gradio_config: Config;
+ scoped_css_attach: (link: HTMLLinkElement) => void;
+ __is_colab__: boolean;
+ parentIFrame?: {
+ scrollTo: (x: number, y: number) => void;
+ };
+ }
+}
+
+export interface Config {
+ auth_required: boolean | undefined;
+ auth_message: string;
+ components: any[];
+ css: string | null;
+ dependencies: any[];
+ dev_mode: boolean;
+ enable_queue: boolean;
+ layout: any;
+ mode: "blocks" | "interface";
+ root: string;
+ theme: string;
+ title: string;
+ version: string;
+ space_id: string | null;
+ is_colab: boolean;
+ show_api: boolean;
+ stylesheets: string[];
+ path: string;
+}
diff --git a/gradio/.dockerignore b/gradio/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..450a3af270f5d285eb3a59a03593d06078b145eb
--- /dev/null
+++ b/gradio/.dockerignore
@@ -0,0 +1,2 @@
+templates/frontend
+templates/frontend/**/*
diff --git a/gradio/CHANGELOG.md b/gradio/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..4b993d7053b6a09c0974557e458ced890771d62a
--- /dev/null
+++ b/gradio/CHANGELOG.md
@@ -0,0 +1,4904 @@
+# gradio
+
+## 4.16.0
+
+### Features
+
+- [#7124](https://github.com/gradio-app/gradio/pull/7124) [`21a16c6`](https://github.com/gradio-app/gradio/commit/21a16c60e8f34b870bd2aae9af07713eb1307252) - add params to `gr.Interface` and `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7139](https://github.com/gradio-app/gradio/pull/7139) [`6abad53`](https://github.com/gradio-app/gradio/commit/6abad536778517a2ab9f5fc75d52afc576f01218) - Added polars dataframe support with demo. Thanks [@cswamy](https://github.com/cswamy)!
+- [#7084](https://github.com/gradio-app/gradio/pull/7084) [`94aa271`](https://github.com/gradio-app/gradio/commit/94aa271ab11fc3426a7e143ebaa757eb30c9911d) - Improve rapid generation performance via UI throttling. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#7104](https://github.com/gradio-app/gradio/pull/7104) [`bc2cdc1`](https://github.com/gradio-app/gradio/commit/bc2cdc1df95b38025486cf76df4a494b66d98585) - Allow download button for interactive Audio and Video components. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7109](https://github.com/gradio-app/gradio/pull/7109) [`125a832`](https://github.com/gradio-app/gradio/commit/125a832ab7ee2b5affa574e8b32c88f430cc6663) - generate docs when running `gradio cc build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7148](https://github.com/gradio-app/gradio/pull/7148) [`c60ad4d`](https://github.com/gradio-app/gradio/commit/c60ad4d34ab5b56a89bf6796822977e51e7a4a32) - Use Gallery as input component. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7049](https://github.com/gradio-app/gradio/pull/7049) [`1718c4a`](https://github.com/gradio-app/gradio/commit/1718c4aeb23a88ef02b17b30a1d1cb72e413e04a) - add STL 3D model support. Thanks [@Mon-ius](https://github.com/Mon-ius)!
+- [#7159](https://github.com/gradio-app/gradio/pull/7159) [`6ee22dc`](https://github.com/gradio-app/gradio/commit/6ee22dc6a8f6419e127a0f650e58c87a31bc59c9) - Ensure `gradio cc publish` uploads the documentation space, if it exists. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7034](https://github.com/gradio-app/gradio/pull/7034) [`82fe73d`](https://github.com/gradio-app/gradio/commit/82fe73d04297ac4e2c3ef42edc62bab4300bf915) - Redirect with query params after oauth. Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#7063](https://github.com/gradio-app/gradio/pull/7063) [`2cdcf4a`](https://github.com/gradio-app/gradio/commit/2cdcf4a890202a55673588c16f27b327d27915b6) - Single oauth button. Thanks [@Wauplin](https://github.com/Wauplin)!
+
+### Fixes
+
+- [#7126](https://github.com/gradio-app/gradio/pull/7126) [`5727b92`](https://github.com/gradio-app/gradio/commit/5727b92abc8a00a675bfc0a921b38de771af947b) - Allow buttons to take null value. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7112](https://github.com/gradio-app/gradio/pull/7112) [`217bfe3`](https://github.com/gradio-app/gradio/commit/217bfe39ca6a0de885824f16be4a707e7f032d57) - Support audio data in `np.int8` format in the `gr.Audio` component. Thanks [@Ram-Pasupula](https://github.com/Ram-Pasupula)!
+- [#7029](https://github.com/gradio-app/gradio/pull/7029) [`ac73555`](https://github.com/gradio-app/gradio/commit/ac735551bb2ccc288b2bbf10b008b6c3d9e65132) - Run before_fn and after_fn for each generator iteration. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7131](https://github.com/gradio-app/gradio/pull/7131) [`7d53aa1`](https://github.com/gradio-app/gradio/commit/7d53aa13a304d056d1973b8e86c6f89ff84cbd28) - Miscellaneous doc fixes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7138](https://github.com/gradio-app/gradio/pull/7138) [`ca8753b`](https://github.com/gradio-app/gradio/commit/ca8753bb3d829d0077f758ba8d0ddc866ff74d3d) - Fixes: Chatbot crashes when given empty url following http:// or https://. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#7115](https://github.com/gradio-app/gradio/pull/7115) [`cb90b3d`](https://github.com/gradio-app/gradio/commit/cb90b3d5d6a291270e047e10f9173cbc03678e1c) - Programmatically determine max wheel version to push to spaces. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7107](https://github.com/gradio-app/gradio/pull/7107) [`80f8fbf`](https://github.com/gradio-app/gradio/commit/80f8fbf0e8900627b9c2575bbd7c68fad8108544) - Add logic to handle non-interactive or hidden tabs. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7142](https://github.com/gradio-app/gradio/pull/7142) [`b961652`](https://github.com/gradio-app/gradio/commit/b9616528ab099aab0adc7027bce4655111f7366c) - Remove kwargs from template components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7125](https://github.com/gradio-app/gradio/pull/7125) [`45f725f`](https://github.com/gradio-app/gradio/commit/45f725f8d0dc7813b3d2e768ca9582d6ad878d6f) - un-disable output components after exception is raised. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#7081](https://github.com/gradio-app/gradio/pull/7081) [`44c53d9`](https://github.com/gradio-app/gradio/commit/44c53d9bde7cab605b7dbd16331683d13cae029e) - Fix dropdown refocusing due to `
` element. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7130](https://github.com/gradio-app/gradio/pull/7130) [`e7ab406`](https://github.com/gradio-app/gradio/commit/e7ab4063eb2624820b9f1076960e9596791d9427) - Fix ParamViewer css. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7113](https://github.com/gradio-app/gradio/pull/7113) [`28e8a8a`](https://github.com/gradio-app/gradio/commit/28e8a8a3ec8acd653182577273be4244a4817082) - Reduce CPU usage of dev mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7082](https://github.com/gradio-app/gradio/pull/7082) [`c35fac0`](https://github.com/gradio-app/gradio/commit/c35fac049a44b14719509443c68690e7f23ce70d) - Ensure device selection works in Audio when streaming. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7045](https://github.com/gradio-app/gradio/pull/7045) [`13cb6af`](https://github.com/gradio-app/gradio/commit/13cb6af8b23be063d85b2c632f36afa37d874e5d) - Ensure microphone devices list updates. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7150](https://github.com/gradio-app/gradio/pull/7150) [`be56c76`](https://github.com/gradio-app/gradio/commit/be56c76c7b5d2814ea8239c7dbeddc4b1d3701c4) - Lite: Add the `home_dir` to `sys.path`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#7133](https://github.com/gradio-app/gradio/pull/7133) [`8c355a4`](https://github.com/gradio-app/gradio/commit/8c355a47844296e3aab250fe61e2ecc706122e78) - Add ruff mock for Lite. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6826](https://github.com/gradio-app/gradio/pull/6826) [`e8b2d8b`](https://github.com/gradio-app/gradio/commit/e8b2d8b2f81b7c4b2d107765f06eaf09a030f1df) - Add sample rate config option to `gr.Audio()`. Thanks [@tsukumijima](https://github.com/tsukumijima)!
+
+## 4.15.0
+
+### Highlights
+
+#### Custom component documentation generator ([#7030](https://github.com/gradio-app/gradio/pull/7030) [`3a944ed`](https://github.com/gradio-app/gradio/commit/3a944ed9f162a224d26959a9c556346a9d205311))
+
+If your custom component has type hints and docstrings for both parameters and return values, you can now automatically generate a documentation page and README.md with no additional effort. Simply run the following command:
+
+```sh
+gradio cc docs
+```
+
+This will generate a Gradio app that you can upload to spaces providing rich documentation for potential users. The documentation page includes:
+
+- Installation instructions.
+- A live embedded demo and working code snippet, pulled from your demo app.
+- An API reference for initialising the component, with types, default values and descriptions.
+- An explanation of how the component affects the user's predict function inputs and outputs.
+- Any additional interfaces or classes that are necessary to understand the API reference.
+- Optional links to GitHub, PyPi, and Hugging Face Spaces.
+
+A README will also be generated detailing the same information but in a format that is optimised for viewing on GitHub or PyPi!
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+### Features
+
+- [#7075](https://github.com/gradio-app/gradio/pull/7075) [`1fc8a94`](https://github.com/gradio-app/gradio/commit/1fc8a941384775f587a6ef30365960f43353cb0d) - fix lint. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7069](https://github.com/gradio-app/gradio/pull/7069) [`07d520c`](https://github.com/gradio-app/gradio/commit/07d520c7a2590eb5544bd0b17f82ea31ecf43e00) - fix versions. Thanks [@pngwn](https://github.com/pngwn)!
+- [#7058](https://github.com/gradio-app/gradio/pull/7058) [`3642b7a`](https://github.com/gradio-app/gradio/commit/3642b7ac93128793b75b94f8d785457869a4447e) - publish: simplify twine_files code. Thanks [@akx](https://github.com/akx)!
+- [#7054](https://github.com/gradio-app/gradio/pull/7054) [`64c65d8`](https://github.com/gradio-app/gradio/commit/64c65d821983961111297a969946d87e2fc4105d) - Add encoding to open/writing files on the deploy_discord function. Thanks [@WilliamHarer](https://github.com/WilliamHarer)!
+- [#7024](https://github.com/gradio-app/gradio/pull/7024) [`f2d69fc`](https://github.com/gradio-app/gradio/commit/f2d69fc7d0c1c3457112e702b53e38a0255fc1b7) - Fix gallery thumbnail design regression. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7018](https://github.com/gradio-app/gradio/pull/7018) [`ec28b4e`](https://github.com/gradio-app/gradio/commit/ec28b4e7c47a9233d9e3a725cc9fe8f9044dfa94) - Add `visible` and `interactive` params to `gr.Tab()`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#7060](https://github.com/gradio-app/gradio/pull/7060) [`aaecfe5`](https://github.com/gradio-app/gradio/commit/aaecfe54d913c1c4713e23233f32ae1e4239730e) - Themes: fix bogus header image URL. Thanks [@akx](https://github.com/akx)!
+
+### Fixes
+
+- [#7050](https://github.com/gradio-app/gradio/pull/7050) [`a336508`](https://github.com/gradio-app/gradio/commit/a3365086468568db871940fa2807454ac047cadd) - Fix bug preventing layout components to be used as custom components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#7055](https://github.com/gradio-app/gradio/pull/7055) [`3c3cf86`](https://github.com/gradio-app/gradio/commit/3c3cf8618a8cad1ef66a7f96664923d2c9f5e0e2) - Fix UI freeze on rapid generators. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#7046](https://github.com/gradio-app/gradio/pull/7046) [`9201f86`](https://github.com/gradio-app/gradio/commit/9201f86450c377f78a77ac003a5d5ff009a8894c) - Raise error in build step if custom component package is not installed. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6933](https://github.com/gradio-app/gradio/pull/6933) [`9cefd2e`](https://github.com/gradio-app/gradio/commit/9cefd2e90a1d0cc4d3e4e953fc5b9b1a7afb68dd) - Refactor examples so they accept data in the same format as is returned by function, rename `.as_example()` to `.process_example()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6980](https://github.com/gradio-app/gradio/pull/6980) [`523b6bc`](https://github.com/gradio-app/gradio/commit/523b6bc534e221b028a3ea3f274c7466fe242d5a) - `gr.update(value=[])` for `gr.File()` clears it. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#7038](https://github.com/gradio-app/gradio/pull/7038) [`6be3c2c`](https://github.com/gradio-app/gradio/commit/6be3c2c47a616c904c8497d1fbef7a851c54d488) - Fix Chatbot custom component template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6982](https://github.com/gradio-app/gradio/pull/6982) [`3f139c7`](https://github.com/gradio-app/gradio/commit/3f139c7c995f749562bb007d2a567bb167669de9) - Fix File drag and drop for specific file_types. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.14.0
+
+### Features
+
+- [#6994](https://github.com/gradio-app/gradio/pull/6994) [`623bc1a`](https://github.com/gradio-app/gradio/commit/623bc1aeb19945c1f3c68ea66fa669d1169483a3) - Switch default order for sources for `gr.Video` so that upload is the default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6965](https://github.com/gradio-app/gradio/pull/6965) [`5d00dd3`](https://github.com/gradio-app/gradio/commit/5d00dd37ca14bbfef2ceac550b29dbe05ba8cab0) - Make
Wasm-compatible. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6945](https://github.com/gradio-app/gradio/pull/6945) [`ccf317f`](https://github.com/gradio-app/gradio/commit/ccf317fc9797675a748b50118aa59a7e4b129d9d) - Add `additional_inputs`, `additional_inputs_accordion` parameters to `gr.Interface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6963](https://github.com/gradio-app/gradio/pull/6963) [`8dfabee`](https://github.com/gradio-app/gradio/commit/8dfabee00495ccbbd6743da07fa06c75cac3fb5f) - fixed typo. Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+
+### Fixes
+
+- [#6969](https://github.com/gradio-app/gradio/pull/6969) [`793bf8f`](https://github.com/gradio-app/gradio/commit/793bf8f7b1943f265c5d016c1a0c682ee549232a) - Display pending file in `
` while waiting for upload request. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6885](https://github.com/gradio-app/gradio/pull/6885) [`640b7fe`](https://github.com/gradio-app/gradio/commit/640b7fe05276e11720b4341cadf088491395e53d) - Fix issue with Webcam Recording. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6967](https://github.com/gradio-app/gradio/pull/6967) [`5e00162`](https://github.com/gradio-app/gradio/commit/5e0016267f1d683e2daab82ee4a33d2f09513a34) - Make
Wasm-compatible. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6983](https://github.com/gradio-app/gradio/pull/6983) [`6e285be`](https://github.com/gradio-app/gradio/commit/6e285be8edeacf8730bac10b7ecd3fd5e309a950) - Fix the reloader. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6958](https://github.com/gradio-app/gradio/pull/6958) [`0f0498b`](https://github.com/gradio-app/gradio/commit/0f0498bf97a036efe47d01b47c4b26000d8d1df3) - Ensure Chatbot theme text size is set correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.13.0
+
+### Features
+
+- [#6133](https://github.com/gradio-app/gradio/pull/6133) [`f742d0e`](https://github.com/gradio-app/gradio/commit/f742d0e861c8e25c5d77d9102c9d50f94b0d3383) - Lite: Support AnnotatedImage on Wasm. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6778](https://github.com/gradio-app/gradio/pull/6778) [`8a093e2`](https://github.com/gradio-app/gradio/commit/8a093e23d7993a044e5e0ff73f93a74cb75dad56) - Add a dev instruction for lite in SharedWorker mode. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6931](https://github.com/gradio-app/gradio/pull/6931) [`6c863af`](https://github.com/gradio-app/gradio/commit/6c863af92fa9ceb5c638857eb22cc5ddb718d549) - Fix functional tests. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6897](https://github.com/gradio-app/gradio/pull/6897) [`fb9c6ca`](https://github.com/gradio-app/gradio/commit/fb9c6cacd7ca4598c000f1f97d7d39a8c4463519) - Lite: Chatbot. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6900](https://github.com/gradio-app/gradio/pull/6900) [`4511d57`](https://github.com/gradio-app/gradio/commit/4511d57c46bf82c48e8e575040ff7dab528b8d51) - Fix the aria-label attrs in `gr.Chatbot()`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6820](https://github.com/gradio-app/gradio/pull/6820) [`649cd4d`](https://github.com/gradio-app/gradio/commit/649cd4d68041d11fcbe31f8efa455345ac49fc74) - Use `EventSource_factory` in `open_stream()` for Wasm. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6916](https://github.com/gradio-app/gradio/pull/6916) [`02c2442`](https://github.com/gradio-app/gradio/commit/02c24422174065b79bfccb258cdfefc6b2b69dc6) - Fix docstring of deprecated parameter concurrency_count. Thanks [@ronensc](https://github.com/ronensc)!
+- [#6884](https://github.com/gradio-app/gradio/pull/6884) [`24a5836`](https://github.com/gradio-app/gradio/commit/24a583688046867ca8b8b02959c441818bdb34a2) - Component Server fix. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6887](https://github.com/gradio-app/gradio/pull/6887) [`8333db8`](https://github.com/gradio-app/gradio/commit/8333db83ac6e2c8511c104534c48137576d0bcd7) - Fix the Wasm worker to initialize the app directories. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#6932](https://github.com/gradio-app/gradio/pull/6932) [`e671e54`](https://github.com/gradio-app/gradio/commit/e671e5415fecae52328e426ee2e9f3c09f410606) - Allow `gr.ClearButton` and `gr.DuplicateButton` to be made hidden (and otherwise updated). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6942](https://github.com/gradio-app/gradio/pull/6942) [`b1b78c2`](https://github.com/gradio-app/gradio/commit/b1b78c2168e24fb65251a9b9b6cbc9382179a8ca) - Fix `.select` for `gr.Image`, `gr.CheckboxGroup`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6899](https://github.com/gradio-app/gradio/pull/6899) [`bd11d6e`](https://github.com/gradio-app/gradio/commit/bd11d6e570755405eac637f1ef71b8d7be09ff67) - Remove the styles on the audio elements in the Chatbot component. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6871](https://github.com/gradio-app/gradio/pull/6871) [`d361a0f`](https://github.com/gradio-app/gradio/commit/d361a0f179752d9e849ec420fc67c8b4060fc154) - Ensure camera settings only update when necessary in Model3D. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6938](https://github.com/gradio-app/gradio/pull/6938) [`459c5dc`](https://github.com/gradio-app/gradio/commit/459c5dc989849b1f0134467d260710fe891045d6) - replacing distutils.StrictVersion dependency for Python 3.12. Thanks [@velaia](https://github.com/velaia)!
+- [#6956](https://github.com/gradio-app/gradio/pull/6956) [`7bab755`](https://github.com/gradio-app/gradio/commit/7bab755f7c4cf38102c87d825066ff49b518222e) - Fixed (this this). Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+- [#6874](https://github.com/gradio-app/gradio/pull/6874) [`31c2316`](https://github.com/gradio-app/gradio/commit/31c23166f0113ab6506575f345c31c952e57e137) - fix issue 6873: File with file_count='directory' bug. Thanks [@joshwilson-dev](https://github.com/joshwilson-dev)!
+- [#6940](https://github.com/gradio-app/gradio/pull/6940) [`c00da89`](https://github.com/gradio-app/gradio/commit/c00da89c3ec6aa9ce43b25f12fde575d681d6870) - Fix returning copies of a component instance from a prediction function. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.12.0
+
+### Features
+
+- [#6839](https://github.com/gradio-app/gradio/pull/6839) [`e974cf0`](https://github.com/gradio-app/gradio/commit/e974cf045c82ce8d79efdda36b9dbf6ea557baa4) - Custom JS Guide. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6854](https://github.com/gradio-app/gradio/pull/6854) [`e528f98`](https://github.com/gradio-app/gradio/commit/e528f98b88f4322f61d315e1770fce0448ca5e26) - chore(deps): update dependency mrmime to v2. Thanks [@renovate](https://github.com/apps/renovate)!
+
+### Fixes
+
+- [#6863](https://github.com/gradio-app/gradio/pull/6863) [`d406855`](https://github.com/gradio-app/gradio/commit/d4068557953746662235d595ec435c42ceb24414) - Fix JS Client when app is running behind a proxy. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6846](https://github.com/gradio-app/gradio/pull/6846) [`48d6534`](https://github.com/gradio-app/gradio/commit/48d6534b40f80e7e70a4061f97d9f2e23ba77fe1) - Add `show_api` parameter to events, and fix `gr.load()`. Also makes some minor improvements to the "view API" page when running on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6865](https://github.com/gradio-app/gradio/pull/6865) [`15c97c6`](https://github.com/gradio-app/gradio/commit/15c97c6d346c475141d20615b5a865e9c44bdc76) - Fix webcam when `streaming=True`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6767](https://github.com/gradio-app/gradio/pull/6767) [`7bb561a`](https://github.com/gradio-app/gradio/commit/7bb561a294ca41d1044927cb34d8645c4175cae0) - Rewriting parts of the README and getting started guides for 4.0. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.11.0
+
+### Features
+
+- [#6842](https://github.com/gradio-app/gradio/pull/6842) [`846d52d`](https://github.com/gradio-app/gradio/commit/846d52d1c92d429077382ce494eea27fd062d9f6) - Fix md highlight. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6831](https://github.com/gradio-app/gradio/pull/6831) [`f3abde8`](https://github.com/gradio-app/gradio/commit/f3abde80884d96ad69b825020c46486d9dd5cac5) - Add an option to enable header links for markdown. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6814](https://github.com/gradio-app/gradio/pull/6814) [`828fb9e`](https://github.com/gradio-app/gradio/commit/828fb9e6ce15b6ea08318675a2361117596a1b5d) - Refactor queue so that there are separate queues for each concurrency id. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6809](https://github.com/gradio-app/gradio/pull/6809) [`1401d99`](https://github.com/gradio-app/gradio/commit/1401d99ade46d87da75b5f5808a3354c49f1d1ea) - Fix `ImageEditor` interaction story. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6803](https://github.com/gradio-app/gradio/pull/6803) [`77c9003`](https://github.com/gradio-app/gradio/commit/77c900311e2ba37b8f849ce088ceb48aa196af18) - Fixes issue 5781: Enables specifying a caching directory for Examples. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6823](https://github.com/gradio-app/gradio/pull/6823) [`67a2b7f`](https://github.com/gradio-app/gradio/commit/67a2b7f12cb06355fcc41e40d47e8b2ad211d7d1) - Fixed duplicate word ("this this"). Thanks [@Cassini-chris](https://github.com/Cassini-chris)!
+- [#6833](https://github.com/gradio-app/gradio/pull/6833) [`1b9d423`](https://github.com/gradio-app/gradio/commit/1b9d4234d6c25ef250d882c7b90e1f4039ed2d76) - Prevent file traversals. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6829](https://github.com/gradio-app/gradio/pull/6829) [`50496f9`](https://github.com/gradio-app/gradio/commit/50496f967f8209032b753912a4379eb9cea66627) - Adjust rounding logic when precision is `None` in `gr.Number()`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6766](https://github.com/gradio-app/gradio/pull/6766) [`73268ee`](https://github.com/gradio-app/gradio/commit/73268ee2e39f23ebdd1e927cb49b8d79c4b9a144) - Improve source selection UX. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.10.0
+
+### Features
+
+- [#6798](https://github.com/gradio-app/gradio/pull/6798) [`245d58e`](https://github.com/gradio-app/gradio/commit/245d58eff788e8d44a59d37a2d9b26d0f08a62b4) - Improve how server/js client handle unexpected errors. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6794](https://github.com/gradio-app/gradio/pull/6794) [`7ba8c5d`](https://github.com/gradio-app/gradio/commit/7ba8c5da45b004edd12c0460be9222f5b5f5f055) - Fix SSRF vulnerability on `/file=` route. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6799](https://github.com/gradio-app/gradio/pull/6799) [`c352811`](https://github.com/gradio-app/gradio/commit/c352811f76d4126613ece0a584f8c552fdd8d1f6) - Adds docstrings for `gr.WaveformOptions`, `gr.Brush`, and `gr.Eraser`, fixes examples for `ImageEditor`, and allows individual images to be used as the initial `value` for `ImageEditor`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6808](https://github.com/gradio-app/gradio/pull/6808) [`6b130e2`](https://github.com/gradio-app/gradio/commit/6b130e26b9a6061e7984923b355a04a5484a1c96) - Ensure LoginButton `value` text is displayed. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6810](https://github.com/gradio-app/gradio/pull/6810) [`526fb6c`](https://github.com/gradio-app/gradio/commit/526fb6c446468f1567d614c83266bb5f5797ce9c) - Fix `gr.load()` so that it works with the SSE v1 protocol. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.9.1
+
+### Features
+
+- [#6781](https://github.com/gradio-app/gradio/pull/6781) [`a807ede`](https://github.com/gradio-app/gradio/commit/a807ede818e0690949aca41020e75a96f0110ece) - Fix backend tests on Windows. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6525](https://github.com/gradio-app/gradio/pull/6525) [`5d51fbc`](https://github.com/gradio-app/gradio/commit/5d51fbce7826da840a2fd4940feb5d9ad6f1bc5a) - Fixes Drag and Drop for Upload. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6780](https://github.com/gradio-app/gradio/pull/6780) [`51e241a`](https://github.com/gradio-app/gradio/commit/51e241addd20dad9a0cdf3e72f747cab112815d1) - Fix flaky CI tests (again 😓 ). Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6693](https://github.com/gradio-app/gradio/pull/6693) [`34f9431`](https://github.com/gradio-app/gradio/commit/34f943101bf7dd6b8a8974a6131c1ed7c4a0dac0) - Python client properly handles hearbeat and log messages. Also handles responses longer than 65k. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 4.9.0
+
+### Features
+
+- [#6726](https://github.com/gradio-app/gradio/pull/6726) [`21cfb0a`](https://github.com/gradio-app/gradio/commit/21cfb0acc309bb1a392f4d8a8e42f6be864c5978) - Remove the styles from the Image/Video primitive components and Fix the container styles. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6398](https://github.com/gradio-app/gradio/pull/6398) [`67ddd40`](https://github.com/gradio-app/gradio/commit/67ddd40b4b70d3a37cb1637c33620f8d197dbee0) - Lite v4. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6399](https://github.com/gradio-app/gradio/pull/6399) [`053bec9`](https://github.com/gradio-app/gradio/commit/053bec98be1127e083414024e02cf0bebb0b5142) - Improve CSS token documentation in Storybook. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6745](https://github.com/gradio-app/gradio/pull/6745) [`3240d04`](https://github.com/gradio-app/gradio/commit/3240d042e907a3f2f679c2310c0dc6a688d2c07e) - Add `editable` parameter to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6616](https://github.com/gradio-app/gradio/pull/6616) [`9a0bd27`](https://github.com/gradio-app/gradio/commit/9a0bd27502894e2488b4732be081cb2027aa636e) - Add support for OAuth tokens. Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#6738](https://github.com/gradio-app/gradio/pull/6738) [`f3c4d78`](https://github.com/gradio-app/gradio/commit/f3c4d78b710854b94d9a15db78178e504a02c680) - reload on css changes + fix css specificity. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6671](https://github.com/gradio-app/gradio/pull/6671) [`299f5e2`](https://github.com/gradio-app/gradio/commit/299f5e238bb6fb3f51376ef8b73fc44351859bbe) - Update HF token used in CI tests. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6680](https://github.com/gradio-app/gradio/pull/6680) [`cfd5700`](https://github.com/gradio-app/gradio/commit/cfd57005bce715271c3073ecd322890b8d30f594) - Cause `gr.ClearButton` to reset the value of `gr.State`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6603](https://github.com/gradio-app/gradio/pull/6603) [`6b1401c`](https://github.com/gradio-app/gradio/commit/6b1401c514c2ec012b0a50c72a6ec81cb673bf1d) - chore(deps): update dependency marked to v11. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#6666](https://github.com/gradio-app/gradio/pull/6666) [`30c9fbb`](https://github.com/gradio-app/gradio/commit/30c9fbb5c74f0dc879e85dbdb6778c0782aeff38) - Set gradio api server from env. Thanks [@aisensiy](https://github.com/aisensiy)!
+- [#6677](https://github.com/gradio-app/gradio/pull/6677) [`51b54b3`](https://github.com/gradio-app/gradio/commit/51b54b3411934ce46a27e7d525dd90b43c9fc016) - Tweak to our bug issue template. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6598](https://github.com/gradio-app/gradio/pull/6598) [`7cbf96e`](https://github.com/gradio-app/gradio/commit/7cbf96e0bdd12db7ecac7bf99694df0a912e5864) - Issue 5245: consolidate usage of requests and httpx. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6704](https://github.com/gradio-app/gradio/pull/6704) [`24e0481`](https://github.com/gradio-app/gradio/commit/24e048196e8f7bd309ef5c597d4ffc6ca4ed55d0) - Hotfix: update `huggingface_hub` dependency version. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6432](https://github.com/gradio-app/gradio/pull/6432) [`bdf81fe`](https://github.com/gradio-app/gradio/commit/bdf81fead86e1d5a29e6b036f1fff677f6480e6b) - Lite: Set the home dir path per appId at each runtime. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6569](https://github.com/gradio-app/gradio/pull/6569) [`4d1cbbc`](https://github.com/gradio-app/gradio/commit/4d1cbbcf30833ef1de2d2d2710c7492a379a9a00) - Allow passing height and width as string in `Blocks.svelte`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6416](https://github.com/gradio-app/gradio/pull/6416) [`5177132`](https://github.com/gradio-app/gradio/commit/5177132d718c77f6d47869b4334afae6380394cb) - Lite: Fix the `isMessagePort()` type guard in js/wasm/src/worker-proxy.ts. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6543](https://github.com/gradio-app/gradio/pull/6543) [`8a70e83`](https://github.com/gradio-app/gradio/commit/8a70e83db9c7751b46058cdd2514e6bddeef6210) - switch from black to ruff formatter. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+
+### Fixes
+
+- [#6709](https://github.com/gradio-app/gradio/pull/6709) [`6a9151d`](https://github.com/gradio-app/gradio/commit/6a9151d5c9432c724098da7d88a539aaaf5ffe88) - Remove progress animation on streaming. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6660](https://github.com/gradio-app/gradio/pull/6660) [`5238053`](https://github.com/gradio-app/gradio/commit/523805360bbf292d9d82443b1f521528beba68bb) - Fix reload mode warning about not being able to find the app. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6672](https://github.com/gradio-app/gradio/pull/6672) [`1234c37`](https://github.com/gradio-app/gradio/commit/1234c3732b52327a00b917af2ef75821771e2c92) - use gr.Error for audio length errors. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6676](https://github.com/gradio-app/gradio/pull/6676) [`fe40308`](https://github.com/gradio-app/gradio/commit/fe40308894efb2c6ff18e5e328163f6641b7476c) - Rotate Images to Upright Position in preprocess. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6487](https://github.com/gradio-app/gradio/pull/6487) [`9a5811d`](https://github.com/gradio-app/gradio/commit/9a5811df9218b622af59ba243a937a9c36ba00f9) - Fix the download button of the `gr.Gallery()` component to work. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6689](https://github.com/gradio-app/gradio/pull/6689) [`c9673ca`](https://github.com/gradio-app/gradio/commit/c9673cacd6470296ee01d7717e2080986e750572) - Fix directory-only glob for FileExplorer. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6639](https://github.com/gradio-app/gradio/pull/6639) [`9a6ff70`](https://github.com/gradio-app/gradio/commit/9a6ff704cd8429289c5376d3af5e4b8492df4773) - Fix issue with `head` param when adding more than one script tag. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6556](https://github.com/gradio-app/gradio/pull/6556) [`d76bcaa`](https://github.com/gradio-app/gradio/commit/d76bcaaaf0734aaf49a680f94ea9d4d22a602e70) - Fix api event drops. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6754](https://github.com/gradio-app/gradio/pull/6754) [`a1b966e`](https://github.com/gradio-app/gradio/commit/a1b966edf761a20ef30e688b1ea1641a5ef1c860) - Fixed an issue where files could not be filed. Thanks [@duolabmeng6](https://github.com/duolabmeng6)!
+- [#6694](https://github.com/gradio-app/gradio/pull/6694) [`dfc61ec`](https://github.com/gradio-app/gradio/commit/dfc61ec4d09da72ddd6e7ab726820529621dbd38) - Fix dropdown blur bug when values are provided as tuples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6691](https://github.com/gradio-app/gradio/pull/6691) [`128ab5d`](https://github.com/gradio-app/gradio/commit/128ab5d65b51390e706a515a1708fe6c88659209) - Ensure checked files persist after FileExplorer rerenders. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6698](https://github.com/gradio-app/gradio/pull/6698) [`798eca5`](https://github.com/gradio-app/gradio/commit/798eca524d44289c536c47eec7c4fdce9fe81905) - Fit video media within Video component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6759](https://github.com/gradio-app/gradio/pull/6759) [`28a7aa9`](https://github.com/gradio-app/gradio/commit/28a7aa917f6a0d57af2c18261d1c01ff76423030) - Mount on a FastAPI app with lifespan manager. Thanks [@Xmaster6y](https://github.com/Xmaster6y)!
+
+## 4.8.0
+
+### Features
+
+- [#6624](https://github.com/gradio-app/gradio/pull/6624) [`1751f14`](https://github.com/gradio-app/gradio/commit/1751f14c1b26c72c0fcc6ba4c69c060c7a199e5d) - Remove 2 slider demos from docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6622](https://github.com/gradio-app/gradio/pull/6622) [`4396f3f`](https://github.com/gradio-app/gradio/commit/4396f3f8f0984d7fcd7e1b88a793af86c7d4e5bb) - Fix encoding issue #6364 of reload mode. Thanks [@curiousRay](https://github.com/curiousRay)!
+- [#5885](https://github.com/gradio-app/gradio/pull/5885) [`9919b8a`](https://github.com/gradio-app/gradio/commit/9919b8ab43bee3d1d7cc65fd641fc8bc9725e102) - Fix the docstring decoration. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6565](https://github.com/gradio-app/gradio/pull/6565) [`9bf1ad4`](https://github.com/gradio-app/gradio/commit/9bf1ad43eac543c9991e59f37e1910f217f8d739) - Fix uploaded file wasn't moved to custom temp dir at different disks. Thanks [@dodysw](https://github.com/dodysw)!
+- [#6584](https://github.com/gradio-app/gradio/pull/6584) [`9bcb1da`](https://github.com/gradio-app/gradio/commit/9bcb1da189a9738d023ef6daad8c6c827e3f6371) - Feat: make UploadButton accept icon. Thanks [@Justin-Xiang](https://github.com/Justin-Xiang)!
+- [#6512](https://github.com/gradio-app/gradio/pull/6512) [`4f040c7`](https://github.com/gradio-app/gradio/commit/4f040c752bb3b0586a4e16eca25a1e5f596eee48) - Update zh-CN.json. Thanks [@cibimo](https://github.com/cibimo)!
+
+### Fixes
+
+- [#6607](https://github.com/gradio-app/gradio/pull/6607) [`13ace03`](https://github.com/gradio-app/gradio/commit/13ace035ed58f14f8f5ce584d94b81c56f83b5d4) - Update file_explorer.py - Fixing error if nothing selected in file_count=single mode (return None rather). Thanks [@v-chabaux](https://github.com/v-chabaux)!
+- [#6574](https://github.com/gradio-app/gradio/pull/6574) [`2b625ad`](https://github.com/gradio-app/gradio/commit/2b625ad9403c3449b34a8a3da68ae48c4347c2db) - Ensure Chatbot messages are properly aligned when `rtl` is true. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6635](https://github.com/gradio-app/gradio/pull/6635) [`b639e04`](https://github.com/gradio-app/gradio/commit/b639e040741e6c0d9104271c81415d7befbd8cf3) - Quick Image + Text Component Fixes. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6572](https://github.com/gradio-app/gradio/pull/6572) [`206af31`](https://github.com/gradio-app/gradio/commit/206af31d7c1a31013364a44e9b40cf8df304ba50) - Improve like/dislike functionality. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6566](https://github.com/gradio-app/gradio/pull/6566) [`d548202`](https://github.com/gradio-app/gradio/commit/d548202d2b5bd8a99e3ebc5bf56820b0282ce0f5) - Improve video trimming and error handling. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6653](https://github.com/gradio-app/gradio/pull/6653) [`d92c819`](https://github.com/gradio-app/gradio/commit/d92c8194191d0e3530d6780a72d6f5c4c545e175) - Add concurrency_limit to ChatInterface, add IDE support for concurrency_limit. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6551](https://github.com/gradio-app/gradio/pull/6551) [`8fc562a`](https://github.com/gradio-app/gradio/commit/8fc562a8abc0932fc312ac33bcc015f6cf2700f6) - Add `show_recording_waveform` to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6550](https://github.com/gradio-app/gradio/pull/6550) [`3156598`](https://github.com/gradio-app/gradio/commit/315659817e5e67a04a1375d35ea6fa58d20622d2) - Make FileExplorer work on python 3.8 and 3.9. Also make it update on changes to root, glob, or glob_dir. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6602](https://github.com/gradio-app/gradio/pull/6602) [`b8034a1`](https://github.com/gradio-app/gradio/commit/b8034a1e72c3aac649ee0ad9178ffdbaaa60fc61) - Fix: Gradio Client work with private Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.7.1
+
+### Features
+
+- [#6537](https://github.com/gradio-app/gradio/pull/6537) [`6d3fecfa4`](https://github.com/gradio-app/gradio/commit/6d3fecfa42dde1c70a60c397434c88db77289be6) - chore(deps): update all non-major dependencies. Thanks [@renovate](https://github.com/apps/renovate)!
+
+### Fixes
+
+- [#6530](https://github.com/gradio-app/gradio/pull/6530) [`13ef0f0ca`](https://github.com/gradio-app/gradio/commit/13ef0f0caa13e5a1cea70d572684122419419599) - Quick fix: Make component interactive when it is in focus. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.6.0
+
+### Features
+
+- [#6532](https://github.com/gradio-app/gradio/pull/6532) [`96290d304`](https://github.com/gradio-app/gradio/commit/96290d304a61064b52c10a54b2feeb09ca007542) - tweak deps. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6511](https://github.com/gradio-app/gradio/pull/6511) [`71f1a1f99`](https://github.com/gradio-app/gradio/commit/71f1a1f9931489d465c2c1302a5c8d768a3cd23a) - Mark `FileData.orig_name` optional on the frontend aligning the type definition on the Python side. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6520](https://github.com/gradio-app/gradio/pull/6520) [`f94db6b73`](https://github.com/gradio-app/gradio/commit/f94db6b7319be902428887867500311a6a32a165) - File table style with accessible file name texts. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6523](https://github.com/gradio-app/gradio/pull/6523) [`63f466882`](https://github.com/gradio-app/gradio/commit/63f466882104453b56a7f52c6bea5b5d497ec698) - Fix typo in base.py. Thanks [@eltociear](https://github.com/eltociear)!
+- [#6296](https://github.com/gradio-app/gradio/pull/6296) [`46f13f496`](https://github.com/gradio-app/gradio/commit/46f13f4968c8177e318c9d75f2eed1ed55c2c042) - chore(deps): update all non-major dependencies. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#6517](https://github.com/gradio-app/gradio/pull/6517) [`901f3eebd`](https://github.com/gradio-app/gradio/commit/901f3eebda0a67fa8f3050d80f7f7b5800c7f566) - Allow reselecting the original option in `gr.Dropdown` after value has changed programmatically. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6538](https://github.com/gradio-app/gradio/pull/6538) [`147926196`](https://github.com/gradio-app/gradio/commit/147926196a074d3fe62e59b5a80997e133c0f707) - Some tweaks to `ImageEditor`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6518](https://github.com/gradio-app/gradio/pull/6518) [`d4e3a5189`](https://github.com/gradio-app/gradio/commit/d4e3a518905620c184a0315ff3bdfbf5e7945bd6) - Allows setting parameters of `gr.ChatInterface`'s `Accordion`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#6528](https://github.com/gradio-app/gradio/pull/6528) [`f53b01cbf`](https://github.com/gradio-app/gradio/commit/f53b01cbfbfccec66e0cda1d428ef72f05a3dfc0) - Fix Theme Dropdown in deployed theme space. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6546](https://github.com/gradio-app/gradio/pull/6546) [`a424fdbb2`](https://github.com/gradio-app/gradio/commit/a424fdbb2389219661b9a73197f4cc095a08cfe9) - Ensure audio waveform `autoplay` updates. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6536](https://github.com/gradio-app/gradio/pull/6536) [`1bbd6cab3`](https://github.com/gradio-app/gradio/commit/1bbd6cab3f0abe183b514b82061f0937c8480966) - Fix undefined `data` TypeError in Blocks. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6500](https://github.com/gradio-app/gradio/pull/6500) [`830b6c0e6`](https://github.com/gradio-app/gradio/commit/830b6c0e6e52c4fa33fddfa4d3f6162e29801f74) - Process and convert .svg files in `Image`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.5.0
+
+### Highlights
+
+#### New `ImageEditor` component ([#6169](https://github.com/gradio-app/gradio/pull/6169) [`9caddc17b`](https://github.com/gradio-app/gradio/commit/9caddc17b1dea8da1af8ba724c6a5eab04ce0ed8))
+
+A brand new component, completely separate from `Image` that provides simple editing capabilities.
+
+- Set background images from file uploads, webcam, or just paste!
+- Crop images with an improved cropping UI. App authors can event set specific crop size, or crop ratios (`1:1`, etc)
+- Paint on top of any image (or no image) and erase any mistakes!
+- The ImageEditor supports layers, confining draw and erase actions to that layer.
+- More flexible access to data. The image component returns a composite image representing the final state of the canvas as well as providing the background and all layers as individual images.
+- Fully customisable. All features can be enabled and disabled. Even the brush color swatches can be customised.
+
+
+
+```py
+
+def fn(im):
+ im["composite"] # the full canvas
+ im["background"] # the background image
+ im["layers"] # a list of individual layers
+
+
+im = gr.ImageEditor(
+ # decide which sources you'd like to accept
+ sources=["upload", "webcam", "clipboard"],
+ # set a cropsize constraint, can either be a ratio or a concrete [width, height]
+ crop_size="1:1",
+ # enable crop (or disable it)
+ transforms=["crop"],
+ # customise the brush
+ brush=Brush(
+ default_size="25", # or leave it as 'auto'
+ color_mode="fixed", # 'fixed' hides the user swatches and colorpicker, 'defaults' shows it
+ default_color="hotpink", # html names are supported
+ colors=[
+ "rgba(0, 150, 150, 1)", # rgb(a)
+ "#fff", # hex rgb
+ "hsl(360, 120, 120)" # in fact any valid colorstring
+ ]
+ ),
+ brush=Eraser(default_size="25")
+)
+
+```
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+### Fixes
+
+- [#6497](https://github.com/gradio-app/gradio/pull/6497) [`1baed201b`](https://github.com/gradio-app/gradio/commit/1baed201b12ecb5791146aed9a86b576c3595130) - Fix SourceFileReloader to watch the module with a qualified name to avoid importing a module with the same name from a different path. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6502](https://github.com/gradio-app/gradio/pull/6502) [`070f71c93`](https://github.com/gradio-app/gradio/commit/070f71c933d846ce8e2fe11cdd9bc0f3f897f29f) - Ensure image editor crop and draw cursor works as expected when the scroll position changes. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.4.1
+
+### Features
+
+- [#6467](https://github.com/gradio-app/gradio/pull/6467) [`739e3a5a0`](https://github.com/gradio-app/gradio/commit/739e3a5a09771a4a386cab0c6605156cf9fda7f6) - Fix dev mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 4.4.0
+
+### Features
+
+- [#6428](https://github.com/gradio-app/gradio/pull/6428) [`ac4ca59c9`](https://github.com/gradio-app/gradio/commit/ac4ca59c929bbe0bdf92155766883797d4e01ea0) - Extract video filenames correctly from URLs. Thanks [@112292454](https://github.com/112292454)!
+- [#6461](https://github.com/gradio-app/gradio/pull/6461) [`6b53330a5`](https://github.com/gradio-app/gradio/commit/6b53330a5be53579d9128aea4858713082ce302d) - UploadButton tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6439](https://github.com/gradio-app/gradio/pull/6439) [`a1e3c61f4`](https://github.com/gradio-app/gradio/commit/a1e3c61f41b16166656b46254a201b37abcf20a8) - Allow setting a `default_concurrency_limit` other than 1. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6455](https://github.com/gradio-app/gradio/pull/6455) [`179f5bcde`](https://github.com/gradio-app/gradio/commit/179f5bcde16539bb9e828685d95dcd2167d3a215) - Add py.typed to gradio backend. Thanks [@aleneum](https://github.com/aleneum)!
+- [#6436](https://github.com/gradio-app/gradio/pull/6436) [`58e3ca826`](https://github.com/gradio-app/gradio/commit/58e3ca8260a6635e10e7a7f141221c4f746e9386) - Custom Component CLI Improvements. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6462](https://github.com/gradio-app/gradio/pull/6462) [`2761b6d19`](https://github.com/gradio-app/gradio/commit/2761b6d197acc1c6a2fd9534e7633b463bd3f1e0) - Catch ValueError, KeyError when saving PIL Image. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6423](https://github.com/gradio-app/gradio/pull/6423) [`62d35c3d1`](https://github.com/gradio-app/gradio/commit/62d35c3d1b3e9d6e39bddbb32ff6b6cf9f1f7f72) - Issue 2085: Transformers object detection pipeline added. Thanks [@cswamy](https://github.com/cswamy)!
+- [#6456](https://github.com/gradio-app/gradio/pull/6456) [`3953a1467`](https://github.com/gradio-app/gradio/commit/3953a146750b09161b50d972590cae8bf980990c) - Preserve original image extension in backend processing. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6427](https://github.com/gradio-app/gradio/pull/6427) [`e0fc14659`](https://github.com/gradio-app/gradio/commit/e0fc146598ba9b081bc5fa9616d0a41c2aba2427) - Allow google analytics to work on Spaces (and other iframe situations). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6419](https://github.com/gradio-app/gradio/pull/6419) [`1959471a8`](https://github.com/gradio-app/gradio/commit/1959471a8d939275c7b9184913a5a6f92e567604) - Add download tests for audio/video. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6424](https://github.com/gradio-app/gradio/pull/6424) [`2727f45fb`](https://github.com/gradio-app/gradio/commit/2727f45fb0c9c3116a7e1a3f88cb3a401c4c7e93) - Do not show warnings when renaming api_names. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6437](https://github.com/gradio-app/gradio/pull/6437) [`727ae2597`](https://github.com/gradio-app/gradio/commit/727ae2597603f026d74d5acafac8709326300836) - chore: rename api_key to hf_token. Thanks [@NickCrews](https://github.com/NickCrews)!
+
+### Fixes
+
+- [#6441](https://github.com/gradio-app/gradio/pull/6441) [`2f805a7dd`](https://github.com/gradio-app/gradio/commit/2f805a7dd3d2b64b098f659dadd5d01258290521) - Small but important bugfixes for gr.Image: The upload event was not triggering at all. The paste-from-clipboard was not triggering an upload event. The clear button was not triggering a change event. The change event was triggering infinitely. Uploaded images were not preserving their original names. Uploading a new image should clear out the previous image. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6454](https://github.com/gradio-app/gradio/pull/6454) [`2777f326e`](https://github.com/gradio-app/gradio/commit/2777f326e595541fbec8ce14f56340b9e740f1da) - Ensure Audio ouput events are dispatched. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6254](https://github.com/gradio-app/gradio/pull/6254) [`f816136a0`](https://github.com/gradio-app/gradio/commit/f816136a039fa6011be9c4fb14f573e4050a681a) - Add volume control to Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6457](https://github.com/gradio-app/gradio/pull/6457) [`d00fcf89d`](https://github.com/gradio-app/gradio/commit/d00fcf89d1c3ecbc910e81bb1311479ec2b73e4e) - Gradio custom component dev mode now detects changes to Example.svelte file. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6418](https://github.com/gradio-app/gradio/pull/6418) [`bce6ca109`](https://github.com/gradio-app/gradio/commit/bce6ca109feadd6ba94a69843689cefc381dd054) - Send more than one heartbeat message. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6425](https://github.com/gradio-app/gradio/pull/6425) [`b3ba17dd1`](https://github.com/gradio-app/gradio/commit/b3ba17dd1167d254756d93f1fb01e8be071819b6) - Update the selected indices in `Dropdown` when value changes programmatically. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.3.0
+
+### Features
+
+- [#6395](https://github.com/gradio-app/gradio/pull/6395) [`8ef48f852`](https://github.com/gradio-app/gradio/commit/8ef48f85241a0f06f4bcdaa0a2010917b3a536be) - Async functions and async generator functions with the `every` option to work. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6403](https://github.com/gradio-app/gradio/pull/6403) [`9cfeb4f17`](https://github.com/gradio-app/gradio/commit/9cfeb4f17e76efad7772e0cbe53dfb3e8310f565) - Remove websockets dependency. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6406](https://github.com/gradio-app/gradio/pull/6406) [`0401c77f3`](https://github.com/gradio-app/gradio/commit/0401c77f3d35763b79e040dbe876e69083defd36) - Move ffmpeg to `Video` deps. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6099](https://github.com/gradio-app/gradio/pull/6099) [`d84209703`](https://github.com/gradio-app/gradio/commit/d84209703b7a0728cdb49221e543500ddb6a8d33) - Lite: SharedWorker mode. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#6412](https://github.com/gradio-app/gradio/pull/6412) [`649f3ceb6`](https://github.com/gradio-app/gradio/commit/649f3ceb6c784c82fa88bdb7f04535f6419b14dd) - Added docs on gr.Examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6378](https://github.com/gradio-app/gradio/pull/6378) [`d31d8c6ad`](https://github.com/gradio-app/gradio/commit/d31d8c6ad888aa4f094820d07288e9d0e2778521) - Allows `sources` to be a string for `gr.Image`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6382](https://github.com/gradio-app/gradio/pull/6382) [`2090aad73`](https://github.com/gradio-app/gradio/commit/2090aad731b186ef0a3f63ec2b4d1a6e3acb1754) - Move wavesurfer dep to js/audio. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6383](https://github.com/gradio-app/gradio/pull/6383) [`324867f63`](https://github.com/gradio-app/gradio/commit/324867f63c920113d89a565892aa596cf8b1e486) - Fix event target. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6405](https://github.com/gradio-app/gradio/pull/6405) [`03491ef49`](https://github.com/gradio-app/gradio/commit/03491ef49708753fc51566c3dc17df09ae98fb98) - Fix docstrings and default value for `api_name`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6386](https://github.com/gradio-app/gradio/pull/6386) [`e76a9e8fc`](https://github.com/gradio-app/gradio/commit/e76a9e8fcbbfc393298de2aa539f2b152c0d6400) - Fix Chatbot Pending Message Issues. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6414](https://github.com/gradio-app/gradio/pull/6414) [`da1e31832`](https://github.com/gradio-app/gradio/commit/da1e31832f85ec76540e474ae35badfde8a18b6f) - Fix Model3D download button and other issues. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6379](https://github.com/gradio-app/gradio/pull/6379) [`de998b281`](https://github.com/gradio-app/gradio/commit/de998b28127ecef10c403890ff08674f527a3708) - Processes `avatar_images` for `gr.Chatbot` and `icon` for `gr.Button` correctly, so that respective files are moved to cache. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.2.0
+
+### Features
+
+- [#6333](https://github.com/gradio-app/gradio/pull/6333) [`42f76aeeb`](https://github.com/gradio-app/gradio/commit/42f76aeeb7b7263abccc038b699fb7fae7fe2313) - Add AsyncGenerator to the check-list of `dependencies.types.generator`. Thanks [@whitphx](https://github.com/whitphx)!
+- [#6347](https://github.com/gradio-app/gradio/pull/6347) [`d64787b88`](https://github.com/gradio-app/gradio/commit/d64787b885a26ecb6771bfdd20aac33c8a90afe6) - Fix `colorFrom` in theme space readmes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6363](https://github.com/gradio-app/gradio/pull/6363) [`4d3aad33a`](https://github.com/gradio-app/gradio/commit/4d3aad33a0b66639dbbb2928f305a79fb7789b2d) - Fix image upload. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6356](https://github.com/gradio-app/gradio/pull/6356) [`854b482f5`](https://github.com/gradio-app/gradio/commit/854b482f598e0dc47673846631643c079576da9c) - Redesign file upload. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6343](https://github.com/gradio-app/gradio/pull/6343) [`37dd335e5`](https://github.com/gradio-app/gradio/commit/37dd335e5f04a8e689dd7f23ae24ad1934ea08d8) - Fix audio streaming output issues in 4.0. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6307](https://github.com/gradio-app/gradio/pull/6307) [`f1409f95e`](https://github.com/gradio-app/gradio/commit/f1409f95ed39c5565bed6a601e41f94e30196a57) - Provide status updates on file uploads. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#6368](https://github.com/gradio-app/gradio/pull/6368) [`8a3f45c26`](https://github.com/gradio-app/gradio/commit/8a3f45c2612a36112d797465e14cd6f1801ccbd9) - Fix component update bug. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6322](https://github.com/gradio-app/gradio/pull/6322) [`6204ccac5`](https://github.com/gradio-app/gradio/commit/6204ccac5967763e0ebde550d04d12584243a120) - Fixes `gr.load()` so it works properly with Images and Examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6323](https://github.com/gradio-app/gradio/pull/6323) [`55fda81fa`](https://github.com/gradio-app/gradio/commit/55fda81fa5918b48952729232d6e2fc55af9351d) - Textbox and Code Component Blur/Focus Fixes. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 4.1.2
+
+### Features
+
+- [#6318](https://github.com/gradio-app/gradio/pull/6318) [`d3b53a457`](https://github.com/gradio-app/gradio/commit/d3b53a4577ea05cd27e37ce7fec952028c18ed45) - Fix for stylized DataFrame. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6326](https://github.com/gradio-app/gradio/pull/6326) [`ed546f2e1`](https://github.com/gradio-app/gradio/commit/ed546f2e13915849b0306d017c40933b856bb792) - Fix Model3D template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Fixes
+
+- [#6310](https://github.com/gradio-app/gradio/pull/6310) [`dfdaf1092`](https://github.com/gradio-app/gradio/commit/dfdaf109263b7b88c125558028ee9609f817fd10) - Fix data model for `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6316](https://github.com/gradio-app/gradio/pull/6316) [`4b1011bab`](https://github.com/gradio-app/gradio/commit/4b1011bab03c0b6a09329e0beb9c1b17b2189878) - Maintain text selection in `Chatbot` button elements. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6327](https://github.com/gradio-app/gradio/pull/6327) [`bca6c2c80`](https://github.com/gradio-app/gradio/commit/bca6c2c80f7e5062427019de45c282238388af95) - Restore query parameters in request. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6317](https://github.com/gradio-app/gradio/pull/6317) [`19af2806a`](https://github.com/gradio-app/gradio/commit/19af2806a58419cc551d2d1d6d8987df0db91ccb) - Add autoplay to `waveform_settings`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6294](https://github.com/gradio-app/gradio/pull/6294) [`7ab73df48`](https://github.com/gradio-app/gradio/commit/7ab73df48ea9dc876c1eaedfb424fcead6326dc9) - fix regarding callable function error. Thanks [@SrijanSahaySrivastava](https://github.com/SrijanSahaySrivastava)!
+- [#6279](https://github.com/gradio-app/gradio/pull/6279) [`3cdeabc68`](https://github.com/gradio-app/gradio/commit/3cdeabc6843000310e1a9e1d17190ecbf3bbc780) - Ensure source selection does not get hidden in overflow. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6311](https://github.com/gradio-app/gradio/pull/6311) [`176c4d140`](https://github.com/gradio-app/gradio/commit/176c4d140000b1be698b6caf0d0efd26a5c7897d) - Temporary fix to be able to load themes from Hub. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6314](https://github.com/gradio-app/gradio/pull/6314) [`fad92c29d`](https://github.com/gradio-app/gradio/commit/fad92c29dc1f5cd84341aae417c495b33e01245f) - Improve default source behaviour in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6320](https://github.com/gradio-app/gradio/pull/6320) [`570866a3b`](https://github.com/gradio-app/gradio/commit/570866a3bd95a45a197afec38b982bbc6c7cd0a0) - Hide show API link when in gradio lite. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6309](https://github.com/gradio-app/gradio/pull/6309) [`c56128781`](https://github.com/gradio-app/gradio/commit/c561287812797aa1b6b464b0e76419350570ba83) - Fix updating choices in `gr.Dropdown` and updates related to other components. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.1.1
+
+### Fixes
+
+- [#6288](https://github.com/gradio-app/gradio/pull/6288) [`92278729e`](https://github.com/gradio-app/gradio/commit/92278729ee008126af15ffe6be399236211b2f34) - Gallery preview fix and optionally skip download of urls in postprcess. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6289](https://github.com/gradio-app/gradio/pull/6289) [`5668036ee`](https://github.com/gradio-app/gradio/commit/5668036eef89051c1dbc5a74dc20988a3012ccbd) - Fix file upload on windows. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6290](https://github.com/gradio-app/gradio/pull/6290) [`e8216be94`](https://github.com/gradio-app/gradio/commit/e8216be948f76ce064595183d11e9148badf9421) - ensure `gr.Dataframe` updates as expected. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.1.0
+
+### Features
+
+- [#6261](https://github.com/gradio-app/gradio/pull/6261) [`8bbeca0e7`](https://github.com/gradio-app/gradio/commit/8bbeca0e772a5a2853d02a058b35abb2c15ffaf1) - Improve Embed and CDN handling and fix a couple of related bugs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6241](https://github.com/gradio-app/gradio/pull/6241) [`61c155e9b`](https://github.com/gradio-app/gradio/commit/61c155e9ba0f8f7ebd5a2a71687597dafb842219) - Remove session if browser closed on mobile. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6227](https://github.com/gradio-app/gradio/pull/6227) [`4840b4bc2`](https://github.com/gradio-app/gradio/commit/4840b4bc297703d317cad9c0f566e857a20b9375) - Add that api routes are automatically named to CHANGELOG. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6240](https://github.com/gradio-app/gradio/pull/6240) [`dd901c1b0`](https://github.com/gradio-app/gradio/commit/dd901c1b0af73a78fca8b6875b2bb00f84071ac8) - Model3D panning, improved UX. Thanks [@dylanebert](https://github.com/dylanebert)!
+- [#6272](https://github.com/gradio-app/gradio/pull/6272) [`12d8e90a1`](https://github.com/gradio-app/gradio/commit/12d8e90a1646374b46eb8258be7356c868d1cca3) - Fixes input `Image` component with `streaming=True`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6268](https://github.com/gradio-app/gradio/pull/6268) [`de36820ef`](https://github.com/gradio-app/gradio/commit/de36820ef51097b47937b41fb76e4038aaa369cb) - Fix various issues with demos on website. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6232](https://github.com/gradio-app/gradio/pull/6232) [`ac4f2bcde`](https://github.com/gradio-app/gradio/commit/ac4f2bcded61672bfe1d54c279d527de2eabdb7a) - Remove **kwargs from queue. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6255](https://github.com/gradio-app/gradio/pull/6255) [`e3ede2ff7`](https://github.com/gradio-app/gradio/commit/e3ede2ff7d4a36fb21bb0b146b8d5ad239c0e086) - Ensure Model 3D updates when attributes change. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#6266](https://github.com/gradio-app/gradio/pull/6266) [`e32bac894`](https://github.com/gradio-app/gradio/commit/e32bac8944c85e0ec4831963299889d6bbfa0351) - Fix updating interactive prop. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6213](https://github.com/gradio-app/gradio/pull/6213) [`27194a987`](https://github.com/gradio-app/gradio/commit/27194a987fa7ba1234b5fc0ce8bf7fabef7033a9) - Ensure the statustracker for `gr.Image` displays in static mode. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6234](https://github.com/gradio-app/gradio/pull/6234) [`aaa55ce85`](https://github.com/gradio-app/gradio/commit/aaa55ce85e12f95aba9299445e9c5e59824da18e) - Video/Audio fixes. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6236](https://github.com/gradio-app/gradio/pull/6236) [`6bce259c5`](https://github.com/gradio-app/gradio/commit/6bce259c5db7b21b327c2067e74ea20417bc89ec) - Ensure `gr.CheckboxGroup` updates as expected. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6262](https://github.com/gradio-app/gradio/pull/6262) [`afb72bd19`](https://github.com/gradio-app/gradio/commit/afb72bd1970e6c43ddba0638fe9861330bdabb64) - Fix bug where radio.select passes the previous value to the function instead of the selected value. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6231](https://github.com/gradio-app/gradio/pull/6231) [`3e31c1752`](https://github.com/gradio-app/gradio/commit/3e31c1752e0e5bf90339b816f9895529d9368bbd) - Add likeable to config for Chatbot. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6249](https://github.com/gradio-app/gradio/pull/6249) [`2cffcf3c3`](https://github.com/gradio-app/gradio/commit/2cffcf3c39acd782f314f8a406100ae22e0809b7) - ensure radios have different names. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6229](https://github.com/gradio-app/gradio/pull/6229) [`5cddd6588`](https://github.com/gradio-app/gradio/commit/5cddd658809d147fafef5e9502ccfab5bd105aa6) - Fixes: Initial message is overwrtitten in chat interface. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6277](https://github.com/gradio-app/gradio/pull/6277) [`5fe091367`](https://github.com/gradio-app/gradio/commit/5fe091367fbe0eecdd504aa734ca1c70b0621f52) - handle selected_index prop change for gallery. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6211](https://github.com/gradio-app/gradio/pull/6211) [`a4a931dd3`](https://github.com/gradio-app/gradio/commit/a4a931dd39a48bceac50486558b049ca7b874195) - fix`FileExplorer` preprocess. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5876](https://github.com/gradio-app/gradio/pull/5876) [`d7a1a6559`](https://github.com/gradio-app/gradio/commit/d7a1a6559005e6a1e0be03a3bd5212d1bc60d1ee) - Fix file overflow and add keyboard navigation to `FileExplorer`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 4.0.2
+
+### Fixes
+
+- [#6191](https://github.com/gradio-app/gradio/pull/6191) [`b555bc09f`](https://github.com/gradio-app/gradio/commit/b555bc09ffe8e58b10da6227e2f11a0c084aa71d) - fix cdn build. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 4.0.1
+
+### Features
+
+- [#6137](https://github.com/gradio-app/gradio/pull/6137) [`2ba14b284`](https://github.com/gradio-app/gradio/commit/2ba14b284f908aa13859f4337167a157075a68eb) - JS Param. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6181](https://github.com/gradio-app/gradio/pull/6181) [`62ec2075c`](https://github.com/gradio-app/gradio/commit/62ec2075ccad8025a7721a08d0f29eb5a4f87fad) - modify preprocess to use pydantic models. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 4.0.0
+
+### Highlights
+
+4.0 is a big release, so here are the main highlights:
+
+**1. Custom Components**:
+We've introduced the ability to create and publish you own custom `gradio` components. A custom Gradio component is a combination of Python and JavaScript (specifically, Svelte) that you can write to fully customize a Gradio component. A custom component can be used just like a regular Gradio component (with `gr.Interface`, `gr.Blocks`, etc.) and can be published so that other users can use it within their apps. To get started with Custom Components, [read our quickstart guide here](https://www.gradio.app/guides/five-minute-guide).
+
+
+
+**2. Redesigned Media Components and Accessibility**:
+
+We redesigned our media components (`gr.Audio`, `gr.Image`, and `gr.Video`) from scratch and improved accessibilty across the board. All components are now keyboard navigable and include better colors to be usable by a wider audience.
+
+
+
+**3. Server Side Events**:
+
+Gradio's built-in queuing system is now the default for every Gradio app. We now use Server Side Events instead of Websockets for the queue. SSE means everything is served over HTTP and has better device support and better scaling than websockets.
+
+
+
+**4. Custom Share Servers**:
+
+Gradio share links can now run on custom domains. You can now set up your own server to serve Gradio share links. To get started, [read our guide here](https://github.com/huggingface/frp/).
+
+
+
+5. We now support adding arbitrary JS to your apps using the `js` parameter in Blocks, and arbitrary modifications to the of your app using the `head` parameter in Blocks
+
+6. We no longer expose a user's working directory by default when you release a Gradio app. There are some other improvements around security as well.
+
+7. Previously, a Gradio app's API endpoints were exposed, allowing you to bypass the queue. As a Gradio developer, you needed to set `api_open=False` to prevent this misuse. We've now made this the default.
+
+8. You can now control whether a user should be able to trigger the same event multiple times (by using the `trigger_mode` parameter of each event)
+
+9. You now have fine-grained control over how many times each event can be running concurrently in the backend (using the `concurrency_limit` parameter of each event)
+
+10. We no longer serialize images into base64 before sending them to the server or on the way back. This should make any Gradio app that includes `gr.Image` components much faster.
+
+
+### Breaking Changes
+
+Gradio 4.0 is a new major version, and includes breaking changes from 3.x. Here's a list of all the breaking changes, along with migration steps where appropriate.
+
+**Components**:
+
+* Removes `**kwarg` from every component, meaning that components cannot accept arbitrary (unused) parameters. Previously, warnings would be thrown.
+* Removes deprecated parameters. For example, `plain` is no longer an alias for `secondary` for the `variant` argument in the `gr.Button` class
+* Removes the deprecated `Carousel` class and `StatusTracker` class and `Box` layout class
+* Removes the deprecated `Variable` alias for `State`
+* Removes the deprecated `.style()` methods from component classes
+* Removes the deprecated `.update()` method from component classes
+* Removes `get_interpretation_neighbors()` and `get_interpretation_scores()` from component classes
+* Removes `deprecation.py` -- this was designed for internal usage so unlikely to break gradio apps
+* Moves save to cache methods from component methods to standalone functions in processing_utils
+* Renames `source` param in `gr.Audio` and `gr.Video` to `sources`
+* Removes `show_edit_button` param from `gr.Audio`
+* The `tool=` argument in `gr.Image()` has been removed. As of `gradio==4.5.0`, we have a new `gr.ImageEditor` component that takes its place. The `ImageEditor` component is a streamlined component that allows you to do basic manipulation of images. It supports setting a background image (which can be uploaded, pasted, or recorded through a webcam), as well the ability to "edit" the background image by using a brush to create strokes and an eraser to erase strokes in layers on top of the background image. See the **Migrating to Gradio 4.0** section below.
+
+**Other changes related to the `gradio` library**:
+
+* Removes the deprecated `status_tracker` parameter from events
+* Removes the deprecated `HuggingFaceDatasetJSONSaver` class
+* Now `Blocks.load()` can only be use an is instance method to attach an event that runs when the page loads. To use the class method, use `gr.load()` instead
+* Similarly, `Interface.load()` has been removed
+* If you are runnin Gradio 4.x, you can not `gr.load` a Space that is running Gradio 3.x. However, you can still use the client libraries (see changes to the client libraries below).
+* Removes deprecated parameters, such as `enable_queue` from `launch()`
+* Many of the positional arguments in launch() are now keyword only, and show_tips has been removed
+* Changes the format of flagged data to json instead of filepath for media and chatbot
+* Removes `gr.Series` and `gr.Parallel`
+* All API endpoints are named by deafult. If `api_name=None`, the api name is the name of the python function.
+
+
+**Changes related to the Client libraries**:
+
+* When using the gradio Client libraries in 3.x with any component that returned JSON data (including `gr.Chatbot`, `gr.Label`, and `gr.JSON`), the data would get saved to a file and the filepath would be returned. Similarly, you would have to pass input JSON as a filepath. Now, the JSON data is passed and returned directly, making it easier to work with these components using the clients.
+
+### Migrating to Gradio 4.0
+
+Here are some concrete tips to help migrate to Gradio 4.0:
+
+#### **Using `allowed_paths`**
+
+Since the working directory is now not served by default, if you reference local files within your CSS or in a `gr.HTML` component using the `/file=` route, you will need to explicitly allow access to those files (or their parent directories) using the `allowed_paths` parameter in `launch()`
+
+For example, if your code looks like this:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML("
")
+
+demo.launch()
+```
+
+In order for the HTML component to be able to serve `image.png`, you will need to add `image.png` in `allowed_paths` like this:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML("
")
+
+demo.launch(allowed_paths=["image.png"])
+```
+
+or if you want to expose all files in your working directory as was the case in Gradio 3.x (not recommended if you plan to share your app with others), you could do:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.HTML("
")
+
+demo.launch(allowed_paths=["."])
+```
+
+
+#### **Using `concurrency_limit` instead of `concurrency_count`**
+
+Previously, in Gradio 3.x, there was a single global `concurrency_count` parameter that controlled how many threads could execute tasks from the queue simultaneously. By default `concurrency_count` was 1, which meant that only a single event could be executed at a time (to avoid OOM errors when working with prediction functions that utilized a large amount of memory or GPU usage). You could bypass the queue by setting `queue=False`.
+
+In Gradio 4.0, the `concurrency_count` parameter has been removed. You can still control the number of total threads by using the `max_threads` parameter. The default value of this parameter is `40`, but you don't have worry (as much) about OOM errors, because even though there are 40 threads, we use a single-worker-single-event model, which means each worker thread only executes a specific function. So effectively, each function has its own "concurrency count" of 1. If you'd like to change this behavior, you can do so by setting a parameter `concurrency_limit`, which is now a parameter of *each event*, not a global parameter. By default this is `1` for each event, but you can set it to a higher value, or to `None` if you'd like to allow an arbitrary number of executions of this event simultaneously. Events can also be grouped together using the `concurrency_id` parameter so that they share the same limit, and by default, events that call the same function share the same `concurrency_id`.
+
+Lastly, it should be noted that the default value of the `concurrency_limit` of all events in a Blocks (which is normally 1) can be changed using the `default_concurrency_limit` parameter in `Blocks.queue()`. You can set this to a higher integer or to `None`. This in turn sets the `concurrency_limit` of all events that don't have an explicit `conurrency_limit` specified.
+
+To summarize migration:
+
+* For events that execute quickly or don't use much CPU or GPU resources, you should set `concurrency_limit=None` in Gradio 4.0. (Previously you would set `queue=False`.)
+* For events that take significant resources (like the prediction function of your machine learning model), and you only want 1 execution of this function at a time, you don't have to set any parameters.
+* For events that take significant resources (like the prediction function of your machine learning model), and you only want `X` executions of this function at a time, you should set `concurrency_limit=X` parameter in the event trigger.(Previously you would set a global `concurrency_count=X`.)
+
+
+**The new `ImageEditor` component**
+
+In Gradio 4.0, the `tool=` argument in `gr.Image()` was removed. It has been replaced, as of Gradio 4.5.0, with a new `gr.ImageEditor()` component. The `ImageEditor` component is a streamlined component that allows you to do basic manipulation of images. It supports setting a background image (which can be uploaded, pasted, or recorded through a webcam), as well the ability to "edit" the background by using a brush to create strokes and an eraser to erase strokes in layers on top of the background image.
+
+The `ImageEditor` component is much more performant and also offers much more flexibility to customize the component, particularly through the new `brush` and `eraser` arguments, which take `Brush` and `Eraser` objects respectively.
+
+Here are some examples of how you might migrate from `Image(tool=...)` to `gr.ImageEditor()`.
+
+* To create a sketchpad input that supports writing black strokes on a white background, you might have previously written:
+
+```py
+gr.Image(source="canvas", tools="sketch")
+```
+
+Now, you should write:
+
+```py
+gr.ImageEditor(sources=(), brush=gr.Brush(colors=["#000000"]))
+```
+
+Note: you can supply a list of supported stroke colors in `gr.Brush`, as well as control whether users can choose their own colors by setting the `color_mode` parameter of `gr.Brush` to be either `"fixed"` or `"defaults"`.
+
+* If you want to create a sketchpad where users can draw in any color, simply omit the `brush` parameter. In other words, where previously, you would do:
+
+```py
+gr.Image(source="canvas", tools="color-sketch")
+```
+
+Now, you should write:
+
+```py
+gr.ImageEditor(sources=())
+```
+
+
+* If you want to allow users to choose a background image and then draw on the image, previously, you would do:
+
+```py
+gr.Image(source="upload", tools="color-sketch")
+```
+
+Now, this is the default behavior of the `ImageEditor` component, so you should just write:
+
+```py
+gr.ImageEditor()
+```
+
+Unlike the `Image` component, which passes the input image as a single value into the prediction function, the `ImageEditor` passes a dictionary consisting of three key-value pairs:
+
+* the key `"background"`, whose value is the background image
+* the key `"layers"`, which consists of a list of values, with the strokes in each layer corresponding to one list element.
+* the key `"composite"`, whose value is to the complete image consisting of background image and all of the strokes.
+
+The type of each value can be set by the `type` parameter (`"filepath"`, `"pil"`, or `"numpy"`, with the default being `"numpy"`), just like in the `Image` component.
+
+Please see the documentation of the `gr.ImageEditor` component for more details: https://www.gradio.app/docs/imageeditor
+
+### Features
+
+- [#6184](https://github.com/gradio-app/gradio/pull/6184) [`86edc0199`](https://github.com/gradio-app/gradio/commit/86edc01995d9f888bac093c44c3d4535fe6483b3) - Remove gr.mix. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6177](https://github.com/gradio-app/gradio/pull/6177) [`59f5a4e30`](https://github.com/gradio-app/gradio/commit/59f5a4e30ed9da1c6d6f6ab0886285150b3e89ec) - Part I: Remove serializes. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Don't serve files in working directory by default. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Small change to make `api_open=False` by default. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Add json schema unit tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Remove duplicate `elem_ids` from components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6182](https://github.com/gradio-app/gradio/pull/6182) [`911829ac2`](https://github.com/gradio-app/gradio/commit/911829ac278080fc81155d4b75502692e72fd3de) - Allow data at queue join. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Moves `gradio_cached_folder` inside the gradio temp direcotry. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Fix constructor_args. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Remove interpretation for good. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Improve Audio Component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - pass props to example components and to example outputs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Clean root url. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Adds the ability to build the frontend and backend of custom components in preparation for publishing to pypi using `gradio_component build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Fix selectable prop in the backend. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Set api=False for cancel events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Improve Video Component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Try to trigger a major beta release. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6172](https://github.com/gradio-app/gradio/pull/6172) [`79c8156eb`](https://github.com/gradio-app/gradio/commit/79c8156ebbf35369dc9cfb1522f88df3cd49c89c) - Queue concurrency count. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Publish all components to npm. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Open source FRP server and allow `gradio` to connect to custom share servers. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - File upload optimization. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Custom components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Removes deprecated arguments and parameters from v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Use async version of shutil in upload route. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - V4: Set cache dir for some component tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Proposal: sample demo for custom components should be a `gr.Interface`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - fix cc build. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - --overwrite deletes previous content. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6171](https://github.com/gradio-app/gradio/pull/6171) [`28322422c`](https://github.com/gradio-app/gradio/commit/28322422cb9d8d3e471e439ad602959662e79312) - strip dangling svelte imports. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Swap websockets for SSE. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6153](https://github.com/gradio-app/gradio/pull/6153) [`1162ed621`](https://github.com/gradio-app/gradio/commit/1162ed6217fe58d66a1923834c390150599ad81f) - Remove `show_edit_button` param in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6124](https://github.com/gradio-app/gradio/pull/6124) [`a7435ba9e`](https://github.com/gradio-app/gradio/commit/a7435ba9e6f8b88a838e80893eb8fedf60ccda67) - Fix static issues with Lite on v4. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6143](https://github.com/gradio-app/gradio/pull/6143) [`e4f7b4b40`](https://github.com/gradio-app/gradio/commit/e4f7b4b409323b01aa01b39e15ce6139e29aa073) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6136](https://github.com/gradio-app/gradio/pull/6136) [`667802a6c`](https://github.com/gradio-app/gradio/commit/667802a6cdbfb2ce454a3be5a78e0990b194548a) - JS Component Documentation. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6142](https://github.com/gradio-app/gradio/pull/6142) [`103416d17`](https://github.com/gradio-app/gradio/commit/103416d17f021c82f5ff0583dcc2d80906ad279e) - JS READMEs and Storybook on Docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6149](https://github.com/gradio-app/gradio/pull/6149) [`90318b1dd`](https://github.com/gradio-app/gradio/commit/90318b1dd118ae08a695a50e7c556226234ab6dc) - swap `mode` on the frontned to `interactive` to match the backend. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6128](https://github.com/gradio-app/gradio/pull/6128) [`9c3bf3175`](https://github.com/gradio-app/gradio/commit/9c3bf31751a414093d103e5a115772f3ef1a67aa) - Don't serve files in working directory by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6138](https://github.com/gradio-app/gradio/pull/6138) [`d2dfc1b9a`](https://github.com/gradio-app/gradio/commit/d2dfc1b9a9bd4940f70b62066b1aeaa905b9c7a9) - Small change to make `api_open=False` by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6152](https://github.com/gradio-app/gradio/pull/6152) [`982bff2fd`](https://github.com/gradio-app/gradio/commit/982bff2fdd938b798c400fb90d1cf0caf7278894) - Remove duplicate `elem_ids` from components. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6155](https://github.com/gradio-app/gradio/pull/6155) [`f71ea09ae`](https://github.com/gradio-app/gradio/commit/f71ea09ae796b85e9fe35956d426f0a19ee48f85) - Moves `gradio_cached_folder` inside the gradio temp direcotry. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6154](https://github.com/gradio-app/gradio/pull/6154) [`a8ef6d5dc`](https://github.com/gradio-app/gradio/commit/a8ef6d5dc97b35cc1da589d1a653209a3c327d98) - Remove interpretation for good. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6135](https://github.com/gradio-app/gradio/pull/6135) [`bce37ac74`](https://github.com/gradio-app/gradio/commit/bce37ac744496537e71546d2bb889bf248dcf5d3) - Fix selectable prop in the backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6118](https://github.com/gradio-app/gradio/pull/6118) [`88bccfdba`](https://github.com/gradio-app/gradio/commit/88bccfdba3df2df4b2747ea5d649ed528047cf50) - Improve Video Component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6126](https://github.com/gradio-app/gradio/pull/6126) [`865a22d5c`](https://github.com/gradio-app/gradio/commit/865a22d5c60fd97aeca968e55580b403743a23ec) - Refactor `Blocks.load()` so that it is in the same style as the other listeners. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6098](https://github.com/gradio-app/gradio/pull/6098) [`c3bc515bf`](https://github.com/gradio-app/gradio/commit/c3bc515bf7d430427182143f7fb047bb4b9f4e5e) - Gradio custom component publish. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6157](https://github.com/gradio-app/gradio/pull/6157) [`db143bdd1`](https://github.com/gradio-app/gradio/commit/db143bdd13b830f3bfd513bbfbc0cd1403522b84) - Make output components not editable if they are being updated. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6091](https://github.com/gradio-app/gradio/pull/6091) [`d5d29c947`](https://github.com/gradio-app/gradio/commit/d5d29c947467e54a8514790894ffffba1c796772) - Open source FRP server and allow `gradio` to connect to custom share servers. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6129](https://github.com/gradio-app/gradio/pull/6129) [`0d261c6ec`](https://github.com/gradio-app/gradio/commit/0d261c6ec1e783e284336023885f67b2ce04084c) - Fix fallback demo app template code. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6140](https://github.com/gradio-app/gradio/pull/6140) [`71bf2702c`](https://github.com/gradio-app/gradio/commit/71bf2702cd5b810c89e2e53452532650acdcfb87) - Fix video. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6069](https://github.com/gradio-app/gradio/pull/6069) [`bf127e124`](https://github.com/gradio-app/gradio/commit/bf127e1241a41401e144874ea468dff8474eb505) - Swap websockets for SSE. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#6082](https://github.com/gradio-app/gradio/pull/6082) [`037e5af33`](https://github.com/gradio-app/gradio/commit/037e5af3363c5b321b95efc955ee8d6ec0f4504e) - WIP: Fix docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6071](https://github.com/gradio-app/gradio/pull/6071) [`f08da1a6f`](https://github.com/gradio-app/gradio/commit/f08da1a6f288f6ab8ec40534d5a9e2c64bed4b3b) - Fixes markdown rendering in examples. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5970](https://github.com/gradio-app/gradio/pull/5970) [`0c571c044`](https://github.com/gradio-app/gradio/commit/0c571c044035989d6fe33fc01fee63d1780635cb) - Add json schema unit tests. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6016](https://github.com/gradio-app/gradio/pull/6016) [`83e947676`](https://github.com/gradio-app/gradio/commit/83e947676d327ca2ab6ae2a2d710c78961c771a0) - Format js in v4 branch. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6093](https://github.com/gradio-app/gradio/pull/6093) [`fadc057bb`](https://github.com/gradio-app/gradio/commit/fadc057bb7016f90dd94049c79fc10d38150c561) - V4: Fix constructor_args. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5966](https://github.com/gradio-app/gradio/pull/5966) [`9cad2127b`](https://github.com/gradio-app/gradio/commit/9cad2127b965023687470b3abfe620e188a9da6e) - Improve Audio Component. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#6014](https://github.com/gradio-app/gradio/pull/6014) [`cad537aac`](https://github.com/gradio-app/gradio/commit/cad537aac57998560c9f44a37499be734de66349) - pass props to example components and to example outputs. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5955](https://github.com/gradio-app/gradio/pull/5955) [`825c9cddc`](https://github.com/gradio-app/gradio/commit/825c9cddc83a09457d8c85ebeecb4bc705572d82) - Fix dev mode model3D. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6107](https://github.com/gradio-app/gradio/pull/6107) [`9a40de7bf`](https://github.com/gradio-app/gradio/commit/9a40de7bff5844c8a135e73c7d175eb02b63a966) - Fix: Move to cache in init postprocess + Fallback Fixes. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6018](https://github.com/gradio-app/gradio/pull/6018) [`184834d02`](https://github.com/gradio-app/gradio/commit/184834d02d448bff387eeb3aef64d9517962f146) - Add a cli command to list available templates. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6092](https://github.com/gradio-app/gradio/pull/6092) [`11d67ae75`](https://github.com/gradio-app/gradio/commit/11d67ae7529e0838565e4131b185c413489c5aa6) - Add a stand-alone install command and tidy-up the fallback template. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6026](https://github.com/gradio-app/gradio/pull/6026) [`338969af2`](https://github.com/gradio-app/gradio/commit/338969af290de032f9cdc204dab8a50be3bf3cc5) - V4: Single-file implementation of form components. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6114](https://github.com/gradio-app/gradio/pull/6114) [`39227b6fa`](https://github.com/gradio-app/gradio/commit/39227b6fac274d5f5b301bc14039571c1bfe510c) - Try to trigger a major beta release. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6060](https://github.com/gradio-app/gradio/pull/6060) [`447dfe06b`](https://github.com/gradio-app/gradio/commit/447dfe06bf19324d88696eb646fd1c5f1c4e86ed) - Clean up backend of `File` and `UploadButton` and change the return type of `preprocess()` from TemporaryFIle to string filepath. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6073](https://github.com/gradio-app/gradio/pull/6073) [`abff6fb75`](https://github.com/gradio-app/gradio/commit/abff6fb758bd310053a23c938bf1dd8fbdc5d333) - Fix remaining xfail tests in backend. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6089](https://github.com/gradio-app/gradio/pull/6089) [`cd8146ba0`](https://github.com/gradio-app/gradio/commit/cd8146ba053fbcb56cf5052e658e4570d457fb8a) - Update logos for v4. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5961](https://github.com/gradio-app/gradio/pull/5961) [`be2ed5e13`](https://github.com/gradio-app/gradio/commit/be2ed5e13222cbe5013b63b36685987518034a76) - File upload optimization. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5968](https://github.com/gradio-app/gradio/pull/5968) [`6b0bb5e6a`](https://github.com/gradio-app/gradio/commit/6b0bb5e6a252ce8c4ef38455a9f56f1dcda56ab0) - Removes deprecated arguments and parameters from v4. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6027](https://github.com/gradio-app/gradio/pull/6027) [`de18102b8`](https://github.com/gradio-app/gradio/commit/de18102b8ca38c1d6d6edfa8c0571b81089166bb) - V4: Fix component update bug. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5996](https://github.com/gradio-app/gradio/pull/5996) [`9cf40f76f`](https://github.com/gradio-app/gradio/commit/9cf40f76fed1c0f84b5a5336a9b0100f8a9b4ee3) - V4: Simple dropdown. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5990](https://github.com/gradio-app/gradio/pull/5990) [`85056de5c`](https://github.com/gradio-app/gradio/commit/85056de5cd4e90a10cbfcefab74037dbc622b26b) - V4: Simple textbox. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6044](https://github.com/gradio-app/gradio/pull/6044) [`9053c95a1`](https://github.com/gradio-app/gradio/commit/9053c95a10de12aef572018ee37c71106d2da675) - Simplify File Component. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#6077](https://github.com/gradio-app/gradio/pull/6077) [`35a227fbf`](https://github.com/gradio-app/gradio/commit/35a227fbfb0b0eb11806c0382c5f6910dc9777cf) - Proposal: sample demo for custom components should be a `gr.Interface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6079](https://github.com/gradio-app/gradio/pull/6079) [`3b2d9eaa3`](https://github.com/gradio-app/gradio/commit/3b2d9eaa3e84de3e4a0799e4585a94510d665f26) - fix cc build. Thanks [@pngwn](https://github.com/pngwn)!
+
+
+### Fixes
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Pending events behavior. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Reinstate types that were removed in error in #5832. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`287fe6782`](https://github.com/gradio-app/gradio/commit/287fe6782825479513e79a5cf0ba0fbfe51443d7) - Fixes: slider bar are too thin on FireFox. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6146](https://github.com/gradio-app/gradio/pull/6146) [`40a171ea6`](https://github.com/gradio-app/gradio/commit/40a171ea60c74afa9519d6cb159def16ce68e1ca) - Fix image double change bug. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6148](https://github.com/gradio-app/gradio/pull/6148) [`0000a1916`](https://github.com/gradio-app/gradio/commit/0000a191688c5480c977c80acdd0c9023865d57e) - fix dropdown arrow size. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6067](https://github.com/gradio-app/gradio/pull/6067) [`bf38e5f06`](https://github.com/gradio-app/gradio/commit/bf38e5f06a7039be913614901c308794fea83ae0) - remove dupe component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6065](https://github.com/gradio-app/gradio/pull/6065) [`7d07001e8`](https://github.com/gradio-app/gradio/commit/7d07001e8e7ca9cbd2251632667b3a043de49f49) - fix storybook. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5826](https://github.com/gradio-app/gradio/pull/5826) [`ce036c5d4`](https://github.com/gradio-app/gradio/commit/ce036c5d47e741e29812654bcc641ea6be876504) - Pending events behavior. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#6046](https://github.com/gradio-app/gradio/pull/6046) [`dbb7de5e0`](https://github.com/gradio-app/gradio/commit/dbb7de5e02c53fee05889d696d764d212cb96c74) - fix tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#6042](https://github.com/gradio-app/gradio/pull/6042) [`e27997fe6`](https://github.com/gradio-app/gradio/commit/e27997fe6c2bcfebc7015fc26100cee9625eb13a) - Fix `root` when user is unauthenticated so that login page appears correctly. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#6076](https://github.com/gradio-app/gradio/pull/6076) [`f3f98f923`](https://github.com/gradio-app/gradio/commit/f3f98f923c9db506284b8440e18a3ac7ddd8398b) - Lite error handler. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5984](https://github.com/gradio-app/gradio/pull/5984) [`66549d8d2`](https://github.com/gradio-app/gradio/commit/66549d8d256b1845c8c5efa0384695b36cb46eab) - Fixes: slider bar are too thin on FireFox. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+
+## 3.45.0-beta.13
+
+### Features
+
+- [#5964](https://github.com/gradio-app/gradio/pull/5964) [`5fbda0bd2`](https://github.com/gradio-app/gradio/commit/5fbda0bd2b2bbb2282249b8875d54acf87cd7e84) - Wasm release. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.45.0-beta.12
+
+### Features
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Some misc fixes. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5960](https://github.com/gradio-app/gradio/pull/5960) [`319c30f3f`](https://github.com/gradio-app/gradio/commit/319c30f3fccf23bfe1da6c9b132a6a99d59652f7) - rererefactor frontend files. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Add host to dev mode for vite. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`d2314e53b`](https://github.com/gradio-app/gradio/commit/d2314e53bc088ff6f307a122a9a01bafcdcff5c2) - BugFix: Make FileExplorer Component Templateable. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Use tags to identify custom component dirs and ignore uninstalled components. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5956](https://github.com/gradio-app/gradio/pull/5956) [`f769876e0`](https://github.com/gradio-app/gradio/commit/f769876e0fa62336425c4e8ada5e09f38353ff01) - Apply formatter (and small refactoring) to the Lite-related frontend code. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5938](https://github.com/gradio-app/gradio/pull/5938) [`13ed8a485`](https://github.com/gradio-app/gradio/commit/13ed8a485d5e31d7d75af87fe8654b661edcca93) - V4: Use beta release versions for '@gradio' packages. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Adds the ability to build the frontend and backend of custom components in preparation for publishing to pypi using `gradio_component build`. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Fix deployed demos on v4 branch. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Set api=False for cancel events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Use full path to executables in CLI. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5949](https://github.com/gradio-app/gradio/pull/5949) [`1c390f101`](https://github.com/gradio-app/gradio/commit/1c390f10199142a41722ba493a0c86b58245da15) - Merge main again. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Simplify how files are handled in components in 4.0. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Name Endpoints if api_name is None. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5937](https://github.com/gradio-app/gradio/pull/5937) [`dcf13d750`](https://github.com/gradio-app/gradio/commit/dcf13d750b1465f905e062a1368ba754446cc23f) - V4: Update Component pyi file. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Rename gradio_component to gradio component. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Use async version of shutil in upload route. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - V4: Set cache dir for some component tests. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5894](https://github.com/gradio-app/gradio/pull/5894) [`fee3d527e`](https://github.com/gradio-app/gradio/commit/fee3d527e83a615109cf937f6ca0a37662af2bb6) - Adds `column_widths` to `gr.Dataframe` and hide overflowing text when `wrap=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Better logs in dev mode. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5946](https://github.com/gradio-app/gradio/pull/5946) [`d0cc6b136`](https://github.com/gradio-app/gradio/commit/d0cc6b136fd59121f74d0c5a1a4b51740ffaa838) - fixup. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5944](https://github.com/gradio-app/gradio/pull/5944) [`465f58957`](https://github.com/gradio-app/gradio/commit/465f58957f70c7cf3e894beef8a117b28339e3c1) - Show empty JSON icon when `value` is `null`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5498](https://github.com/gradio-app/gradio/pull/5498) [`85ba6de13`](https://github.com/gradio-app/gradio/commit/85ba6de136a45b3e92c74e410bb27e3cbe7138d7) - Reinstate types that were removed in error in #5832. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.48.0
+
+### Features
+
+- [#5627](https://github.com/gradio-app/gradio/pull/5627) [`b67115e8e`](https://github.com/gradio-app/gradio/commit/b67115e8e6e489fffd5271ea830211863241ddc5) - Lite: Make the Examples component display media files using pseudo HTTP requests to the Wasm server. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5821](https://github.com/gradio-app/gradio/pull/5821) [`1aa186220`](https://github.com/gradio-app/gradio/commit/1aa186220dfa8ee3621b818c4cdf4d7b9d690b40) - Lite: Fix Examples.create() to be a normal func so it can be called in the Wasm env. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5886](https://github.com/gradio-app/gradio/pull/5886) [`121f25b2d`](https://github.com/gradio-app/gradio/commit/121f25b2d50a33e1e06721b79e20b4f5651987ba) - Lite: Fix is_self_host() to detect `127.0.0.1` as localhost as well. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5915](https://github.com/gradio-app/gradio/pull/5915) [`e24163e15`](https://github.com/gradio-app/gradio/commit/e24163e15afdfc51ec8cb00a0dc46c2318b245be) - Added dimensionality check to avoid bad array dimensions. Thanks [@THEGAMECHANGER416](https://github.com/THEGAMECHANGER416)!
+- [#5835](https://github.com/gradio-app/gradio/pull/5835) [`46334780d`](https://github.com/gradio-app/gradio/commit/46334780dbbb7e83f31971d45a7047ee156a0578) - Mention that audio is normalized when converting to wav in docs. Thanks [@aileenvl](https://github.com/aileenvl)!
+- [#5877](https://github.com/gradio-app/gradio/pull/5877) [`a55b80942`](https://github.com/gradio-app/gradio/commit/a55b8094231ae462ac53f52bbdb460c1286ffabb) - Add styling (e.g. font colors and background colors) support to `gr.DataFrame` through the `pd.Styler` object. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5819](https://github.com/gradio-app/gradio/pull/5819) [`5f1cbc436`](https://github.com/gradio-app/gradio/commit/5f1cbc4363b09302334e9bc864587f8ef398550d) - Add support for gr.Request to gr.ChatInterface. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5901](https://github.com/gradio-app/gradio/pull/5901) [`c4e3a9274`](https://github.com/gradio-app/gradio/commit/c4e3a92743a3b41edad8b45c5d5b0ccbc2674a30) - Fix curly brackets in docstrings. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5934](https://github.com/gradio-app/gradio/pull/5934) [`8d909624f`](https://github.com/gradio-app/gradio/commit/8d909624f61a49536e3c0f71cb2d9efe91216219) - Fix styling issues with Audio, Image and Video components. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5864](https://github.com/gradio-app/gradio/pull/5864) [`e70805d54`](https://github.com/gradio-app/gradio/commit/e70805d54cc792452545f5d8eccc1aa0212a4695) - Change `BlockLabel` element to use `
`. Thanks [@aileenvl](https://github.com/aileenvl)!
+- [#5862](https://github.com/gradio-app/gradio/pull/5862) [`c07207e0b`](https://github.com/gradio-app/gradio/commit/c07207e0bc98cc32b6db629c432fadf877e451ff) - Remove deprecated `.update()` usage from Interface internals. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5905](https://github.com/gradio-app/gradio/pull/5905) [`b450cef15`](https://github.com/gradio-app/gradio/commit/b450cef15685c934ba7c4e4d57cbed233e925fb1) - Fix type the docstring of the Code component. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5840](https://github.com/gradio-app/gradio/pull/5840) [`4e62b8493`](https://github.com/gradio-app/gradio/commit/4e62b8493dfce50bafafe49f1a5deb929d822103) - Ensure websocket polyfill doesn't load if there is already a `global.Webocket` property set. Thanks [@Jay2theWhy](https://github.com/Jay2theWhy)!
+- [#5839](https://github.com/gradio-app/gradio/pull/5839) [`b83064da0`](https://github.com/gradio-app/gradio/commit/b83064da0005ca055fc15ee478cf064bf91702a4) - Fix error when scrolling dropdown with scrollbar. Thanks [@Kit-p](https://github.com/Kit-p)!
+- [#5822](https://github.com/gradio-app/gradio/pull/5822) [`7b63db271`](https://github.com/gradio-app/gradio/commit/7b63db27161ab538f20cf8523fc04c9c3b604a98) - Convert async methods in the Examples class into normal sync methods. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5904](https://github.com/gradio-app/gradio/pull/5904) [`891d42e9b`](https://github.com/gradio-app/gradio/commit/891d42e9baa7ab85ede2a5eadb56c274b0ed2785) - Define Font.__repr__() to be printed in the doc in a readable format. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5811](https://github.com/gradio-app/gradio/pull/5811) [`1d5b15a2d`](https://github.com/gradio-app/gradio/commit/1d5b15a2d24387154f2cfb40a36de25b331471d3) - Assert refactor in external.py. Thanks [@harry-urek](https://github.com/harry-urek)!
+- [#5827](https://github.com/gradio-app/gradio/pull/5827) [`48e09ee88`](https://github.com/gradio-app/gradio/commit/48e09ee88799efa38a5cc9b1b61e462f72ec6093) - Quick fix: Chatbot change event. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5890](https://github.com/gradio-app/gradio/pull/5890) [`c4ba832b3`](https://github.com/gradio-app/gradio/commit/c4ba832b318dad5e8bf565cfa0daf93ca188498f) - Remove deprecation warning from `gr.update` and clean up associated code. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5897](https://github.com/gradio-app/gradio/pull/5897) [`0592c301d`](https://github.com/gradio-app/gradio/commit/0592c301df9cd949b52159c85b7042f38d113e86) - Fix Dataframe `line_breaks`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5878](https://github.com/gradio-app/gradio/pull/5878) [`fbce277e5`](https://github.com/gradio-app/gradio/commit/fbce277e50c5885371fd49c68adf8565c25c1d39) - Keep Markdown rendered lists within dataframe cells. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5930](https://github.com/gradio-app/gradio/pull/5930) [`361823896`](https://github.com/gradio-app/gradio/commit/3618238960d54df65c34895f4eb69d08acc3f9b6) - Fix dataframe `line_breaks`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 3.47.1
+
+### Fixes
+
+- [#5816](https://github.com/gradio-app/gradio/pull/5816) [`796145e2c`](https://github.com/gradio-app/gradio/commit/796145e2c48c4087bec17f8ec0be4ceee47170cb) - Fix calls to the component server so that `gr.FileExplorer` works on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.47.0
+
+### Highlights
+
+#### new `FileExplorer` component ([#5672](https://github.com/gradio-app/gradio/pull/5672) [`e4a307ed6`](https://github.com/gradio-app/gradio/commit/e4a307ed6cde3bbdf4ff2f17655739addeec941e))
+
+Thanks to a new capability that allows components to communicate directly with the server _without_ passing data via the value, we have created a new `FileExplorer` component.
+
+This component allows you to populate the explorer by passing a glob, but only provides the selected file(s) in your prediction function.
+
+Users can then navigate the virtual filesystem and select files which will be accessible in your predict function. This component will allow developers to build more complex spaces, with more flexible input options.
+
+![output](https://github.com/pngwn/MDsveX/assets/12937446/ef108f0b-0e84-4292-9984-9dc66b3e144d)
+
+For more information check the [`FileExplorer` documentation](https://gradio.app/docs/fileexplorer).
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5780](https://github.com/gradio-app/gradio/pull/5780) [`ed0f9a21b`](https://github.com/gradio-app/gradio/commit/ed0f9a21b04ad6b941b63d2ce45100dbd1abd5c5) - Adds `change()` event to `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5783](https://github.com/gradio-app/gradio/pull/5783) [`4567788bd`](https://github.com/gradio-app/gradio/commit/4567788bd1fc25df9322902ba748012e392b520a) - Adds the ability to set the `selected_index` in a `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5787](https://github.com/gradio-app/gradio/pull/5787) [`caeee8bf7`](https://github.com/gradio-app/gradio/commit/caeee8bf7821fd5fe2f936ed82483bed00f613ec) - ensure the client does not depend on `window` when running in a node environment. Thanks [@gibiee](https://github.com/gibiee)!
+
+### Fixes
+
+- [#5798](https://github.com/gradio-app/gradio/pull/5798) [`a0d3cc45c`](https://github.com/gradio-app/gradio/commit/a0d3cc45c6db48dc0db423c229b8fb285623cdc4) - Fix `gr.SelectData` so that the target attribute is correctly attached, and the filedata is included in the data attribute with `gr.Gallery`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5795](https://github.com/gradio-app/gradio/pull/5795) [`957ba5cfd`](https://github.com/gradio-app/gradio/commit/957ba5cfde18e09caedf31236a2064923cd7b282) - Prevent bokeh from injecting bokeh js multiple times. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5790](https://github.com/gradio-app/gradio/pull/5790) [`37e70842d`](https://github.com/gradio-app/gradio/commit/37e70842d59f5aed6fab0086b1abf4b8d991f1c9) - added try except block in `state.py`. Thanks [@SrijanSahaySrivastava](https://github.com/SrijanSahaySrivastava)!
+- [#5794](https://github.com/gradio-app/gradio/pull/5794) [`f096c3ae1`](https://github.com/gradio-app/gradio/commit/f096c3ae168c0df00f90fe131c1e48c572e0574b) - Throw helpful error when media devices are not found. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5776](https://github.com/gradio-app/gradio/pull/5776) [`c0fef4454`](https://github.com/gradio-app/gradio/commit/c0fef44541bfa61568bdcfcdfc7d7d79869ab1df) - Revert replica proxy logic and instead implement using the `root` variable. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.46.1
+
+### Features
+
+- [#5124](https://github.com/gradio-app/gradio/pull/5124) [`6e56a0d9b`](https://github.com/gradio-app/gradio/commit/6e56a0d9b0c863e76c69e1183d9d40196922b4cd) - Lite: Websocket queueing. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5775](https://github.com/gradio-app/gradio/pull/5775) [`e2874bc3c`](https://github.com/gradio-app/gradio/commit/e2874bc3cb1397574f77dbd7f0408ed4e6792970) - fix pending chatbot message styling and ensure messages with value `None` don't render. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 3.46.0
+
+### Features
+
+- [#5699](https://github.com/gradio-app/gradio/pull/5699) [`8f0fed857`](https://github.com/gradio-app/gradio/commit/8f0fed857d156830626eb48b469d54d211a582d2) - Improve chatbot accessibility and UX. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5569](https://github.com/gradio-app/gradio/pull/5569) [`2a5b9e03b`](https://github.com/gradio-app/gradio/commit/2a5b9e03b15ea324d641fe6982f26d81b1ca7210) - Added support for pandas `Styler` object to `gr.DataFrame` (initially just sets the `display_value`). Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5735](https://github.com/gradio-app/gradio/pull/5735) [`abb5e9df4`](https://github.com/gradio-app/gradio/commit/abb5e9df47989b2c56c2c312d74944678f9f2d4e) - Ensure images with no caption download in gallery. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5754](https://github.com/gradio-app/gradio/pull/5754) [`502054848`](https://github.com/gradio-app/gradio/commit/502054848fdbe39fc03ec42445242b4e49b7affc) - Fix Gallery `columns` and `rows` params. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5755](https://github.com/gradio-app/gradio/pull/5755) [`e842a561a`](https://github.com/gradio-app/gradio/commit/e842a561af4394f8109291ee5725bcf74743e816) - Fix new line issue in chatbot. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5731](https://github.com/gradio-app/gradio/pull/5731) [`c9af4f794`](https://github.com/gradio-app/gradio/commit/c9af4f794060e218193935d7213f0991a374f502) - Added timeout and error handling for frpc tunnel. Thanks [@cansik](https://github.com/cansik)!
+- [#5766](https://github.com/gradio-app/gradio/pull/5766) [`ef96d3512`](https://github.com/gradio-app/gradio/commit/ef96d351229272738fc3c9680f7111f159590341) - Don't raise warnings when returning an updated component in a dictionary. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5767](https://github.com/gradio-app/gradio/pull/5767) [`caf6d9c0e`](https://github.com/gradio-app/gradio/commit/caf6d9c0e1f5b867cc20f2b4f6abb5ef47503a5f) - Set share=True for all Gradio apps in Colab by default. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.45.2
+
+### Features
+
+- [#5722](https://github.com/gradio-app/gradio/pull/5722) [`dba651904`](https://github.com/gradio-app/gradio/commit/dba651904c97dcddcaae2691540ac430d3eefd18) - Fix for deepcopy errors when running the replica-related logic on Spaces. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5721](https://github.com/gradio-app/gradio/pull/5721) [`84e03fe50`](https://github.com/gradio-app/gradio/commit/84e03fe506e08f1f81bac6d504c9fba7924f2d93) - Adds copy buttons to website, and better descriptions to API Docs. Thanks [@aliabd](https://github.com/aliabd)!
+
+### Fixes
+
+- [#5714](https://github.com/gradio-app/gradio/pull/5714) [`a0fc5a296`](https://github.com/gradio-app/gradio/commit/a0fc5a29678baa2d9ba997a2124cadebecfb2c36) - Make Tab and Tabs updatable. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5713](https://github.com/gradio-app/gradio/pull/5713) [`c10dabd6b`](https://github.com/gradio-app/gradio/commit/c10dabd6b18b49259441eb5f956a19046f466339) - Fixes gr.select() Method Issues with Dataframe Cells. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5693](https://github.com/gradio-app/gradio/pull/5693) [`c2b31c396`](https://github.com/gradio-app/gradio/commit/c2b31c396f6d260cdf93377b715aee7ff162df75) - Context-based Progress tracker. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5705](https://github.com/gradio-app/gradio/pull/5705) [`78e7cf516`](https://github.com/gradio-app/gradio/commit/78e7cf5163e8d205e8999428fce4c02dbdece25f) - ensure internal data has updated before dispatching `success` or `then` events. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5668](https://github.com/gradio-app/gradio/pull/5668) [`d626c21e9`](https://github.com/gradio-app/gradio/commit/d626c21e91df026b04fdb3ee5c7dba74a261cfd3) - Fully resolve generated filepaths when running on Hugging Face Spaces with multiple replicas. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5711](https://github.com/gradio-app/gradio/pull/5711) [`aefb556ac`](https://github.com/gradio-app/gradio/commit/aefb556ac6dbadc320c618b11bb48371ef19dd61) - prevent internal log_message error from `/api/predict`. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5726](https://github.com/gradio-app/gradio/pull/5726) [`96c4b97c7`](https://github.com/gradio-app/gradio/commit/96c4b97c742311e90a87d8e8ee562c6ad765e9f0) - Adjust translation. Thanks [@ylhsieh](https://github.com/ylhsieh)!
+- [#5732](https://github.com/gradio-app/gradio/pull/5732) [`3a48490bc`](https://github.com/gradio-app/gradio/commit/3a48490bc5e4136ec9bc0354b0d6fb6c04280505) - Add a bare `Component` type to the acceptable type list of `gr.load()`'s `inputs` and `outputs`. Thanks [@whitphx](https://github.com/whitphx)!
+
+## 3.45.1
+
+### Fixes
+
+- [#5701](https://github.com/gradio-app/gradio/pull/5701) [`ee8eec1e5`](https://github.com/gradio-app/gradio/commit/ee8eec1e5e544a0127e0aa68c2522a7085b8ada5) - Fix for regression in rendering empty Markdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.45.0
+
+### Features
+
+- [#5675](https://github.com/gradio-app/gradio/pull/5675) [`b619e6f6e`](https://github.com/gradio-app/gradio/commit/b619e6f6e4ca55334fb86da53790e45a8f978566) - Reorganize Docs Navbar and Fill in Gaps. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5669](https://github.com/gradio-app/gradio/pull/5669) [`c5e969559`](https://github.com/gradio-app/gradio/commit/c5e969559612f956afcdb0c6f7b22ab8275bc49a) - Fix small issues in docs and guides. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5682](https://github.com/gradio-app/gradio/pull/5682) [`c57f1b75e`](https://github.com/gradio-app/gradio/commit/c57f1b75e272c76b0af4d6bd0c7f44743ff34f26) - Fix functional tests. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5681](https://github.com/gradio-app/gradio/pull/5681) [`40de3d217`](https://github.com/gradio-app/gradio/commit/40de3d2178b61ebe424b6f6228f94c0c6f679bea) - add query parameters to the `gr.Request` object through the `query_params` attribute. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5653](https://github.com/gradio-app/gradio/pull/5653) [`ea0e00b20`](https://github.com/gradio-app/gradio/commit/ea0e00b207b4b90a10e9d054c4202d4e705a29ba) - Prevent Clients from accessing API endpoints that set `api_name=False`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5639](https://github.com/gradio-app/gradio/pull/5639) [`e1874aff8`](https://github.com/gradio-app/gradio/commit/e1874aff814d13b23f3e59ef239cc13e18ad3fa7) - Add `gr.on` listener method. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5652](https://github.com/gradio-app/gradio/pull/5652) [`2e25d4305`](https://github.com/gradio-app/gradio/commit/2e25d430582264945ae3316acd04c4453a25ce38) - Pause autoscrolling if a user scrolls up in a `gr.Textbox` and resume autoscrolling if they go all the way down. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5642](https://github.com/gradio-app/gradio/pull/5642) [`21c7225bd`](https://github.com/gradio-app/gradio/commit/21c7225bda057117a9d3311854323520218720b5) - Improve plot rendering. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5677](https://github.com/gradio-app/gradio/pull/5677) [`9f9af327c`](https://github.com/gradio-app/gradio/commit/9f9af327c9115356433ec837f349d6286730fb97) - [Refactoring] Convert async functions that don't contain `await` statements to normal functions. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5660](https://github.com/gradio-app/gradio/pull/5660) [`d76555a12`](https://github.com/gradio-app/gradio/commit/d76555a122b545f0df7c9e7c1ca7bd2a6e262c86) - Fix secondary hue bug in gr.themes.builder(). Thanks [@hellofreckles](https://github.com/hellofreckles)!
+- [#5697](https://github.com/gradio-app/gradio/pull/5697) [`f4e4f82b5`](https://github.com/gradio-app/gradio/commit/f4e4f82b58a65efca9030a7e8e7c5ace60d8cc10) - Increase Slider clickable area. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5671](https://github.com/gradio-app/gradio/pull/5671) [`6a36c3b78`](https://github.com/gradio-app/gradio/commit/6a36c3b786700600d3826ce1e0629cc5308ddd47) - chore(deps): update dependency @types/prismjs to v1.26.1. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5240](https://github.com/gradio-app/gradio/pull/5240) [`da05e59a5`](https://github.com/gradio-app/gradio/commit/da05e59a53bbad15e5755a47f46685da18e1031e) - Cleanup of .update and .get_config per component. Thanks [@aliabid94](https://github.com/aliabid94)!/n get_config is removed, the config used is simply any attribute that is in the Block that shares a name with one of the constructor paramaters./n update is not removed for backwards compatibility, but deprecated. Instead return the component itself. Created a updateable decorator that simply checks to see if we're in an update, and if so, skips the constructor and wraps the args and kwargs in an update dictionary. easy peasy.
+- [#5635](https://github.com/gradio-app/gradio/pull/5635) [`38fafb9e2`](https://github.com/gradio-app/gradio/commit/38fafb9e2a5509b444942e1d5dd48dffa20066f4) - Fix typos in Gallery docs. Thanks [@atesgoral](https://github.com/atesgoral)!
+- [#5590](https://github.com/gradio-app/gradio/pull/5590) [`d1ad1f671`](https://github.com/gradio-app/gradio/commit/d1ad1f671caef9f226eb3965f39164c256d8615c) - Attach `elem_classes` selectors to layout elements, and an id to the Tab button (for targeting via CSS/JS). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5554](https://github.com/gradio-app/gradio/pull/5554) [`75ddeb390`](https://github.com/gradio-app/gradio/commit/75ddeb390d665d4484667390a97442081b49a423) - Accessibility Improvements. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5598](https://github.com/gradio-app/gradio/pull/5598) [`6b1714386`](https://github.com/gradio-app/gradio/commit/6b17143868bdd2c1400af1199a01c1c0d5c27477) - Upgrade Pyodide to 0.24.0 and install the native orjson package. Thanks [@whitphx](https://github.com/whitphx)!
+
+### Fixes
+
+- [#5625](https://github.com/gradio-app/gradio/pull/5625) [`9ccc4794a`](https://github.com/gradio-app/gradio/commit/9ccc4794a72ce8319417119f6c370e7af3ffca6d) - Use ContextVar instead of threading.local(). Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5602](https://github.com/gradio-app/gradio/pull/5602) [`54d21d3f1`](https://github.com/gradio-app/gradio/commit/54d21d3f18f2ddd4e796d149a0b41461f49c711b) - Ensure `HighlightedText` with `merge_elements` loads without a value. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5636](https://github.com/gradio-app/gradio/pull/5636) [`fb5964fb8`](https://github.com/gradio-app/gradio/commit/fb5964fb88082e7b956853b543c468116811cab9) - Fix bug in example cache loading event. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5633](https://github.com/gradio-app/gradio/pull/5633) [`341402337`](https://github.com/gradio-app/gradio/commit/34140233794c29d4722020e13c2d045da642dfae) - Allow Gradio apps containing `gr.Radio()`, `gr.Checkboxgroup()`, or `gr.Dropdown()` to be loaded with `gr.load()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5616](https://github.com/gradio-app/gradio/pull/5616) [`7c34b434a`](https://github.com/gradio-app/gradio/commit/7c34b434aae0eb85f112a1dc8d66cefc7e2296b2) - Fix width and height issues that would cut off content in `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5604](https://github.com/gradio-app/gradio/pull/5604) [`faad01f8e`](https://github.com/gradio-app/gradio/commit/faad01f8e10ef6d18249b1a4587477c59b74adb2) - Add `render_markdown` parameter to chatbot. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5593](https://github.com/gradio-app/gradio/pull/5593) [`88d43bd12`](https://github.com/gradio-app/gradio/commit/88d43bd124792d216da445adef932a2b02f5f416) - Fixes avatar image in chatbot being squashed. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5690](https://github.com/gradio-app/gradio/pull/5690) [`6b8c8afd9`](https://github.com/gradio-app/gradio/commit/6b8c8afd981fea984da568e9a0bd8bfc2a9c06c4) - Fix incorrect behavior of `gr.load()` with `gr.Examples`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5696](https://github.com/gradio-app/gradio/pull/5696) [`e51fcd5d5`](https://github.com/gradio-app/gradio/commit/e51fcd5d54315e8b65ee40e3de4dab17579ff6d5) - setting share=True on Spaces or in wasm should warn instead of raising error. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.4
+
+### Features
+
+- [#5514](https://github.com/gradio-app/gradio/pull/5514) [`52f783175`](https://github.com/gradio-app/gradio/commit/52f7831751b432411e109bd41add4ab286023a8e) - refactor: Use package.json for version management. Thanks [@DarhkVoyd](https://github.com/DarhkVoyd)!
+- [#5535](https://github.com/gradio-app/gradio/pull/5535) [`d29b1ab74`](https://github.com/gradio-app/gradio/commit/d29b1ab740784d8c70f9ab7bc38bbbf7dd3ff737) - Makes sliders consistent across all browsers. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+### Fixes
+
+- [#5587](https://github.com/gradio-app/gradio/pull/5587) [`e0d61b8ba`](https://github.com/gradio-app/gradio/commit/e0d61b8baa0f6293f53b9bdb1647d42f9ae2583a) - Fix `.clear()` events for audio and image. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5534](https://github.com/gradio-app/gradio/pull/5534) [`d9e9ae43f`](https://github.com/gradio-app/gradio/commit/d9e9ae43f5c52c1f729af5a20e5d4f754689d429) - Guide fixes, esp. streaming audio. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5588](https://github.com/gradio-app/gradio/pull/5588) [`acdeff57e`](https://github.com/gradio-app/gradio/commit/acdeff57ece4672f943c374d537eaf47d3ec034f) - Allow multiple instances of Gradio with authentication to run on different ports. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.3
+
+### Fixes
+
+- [#5562](https://github.com/gradio-app/gradio/pull/5562) [`50d9747d0`](https://github.com/gradio-app/gradio/commit/50d9747d061962cff7f60a8da648bb3781794102) - chore(deps): update dependency iframe-resizer to v4.3.7. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5550](https://github.com/gradio-app/gradio/pull/5550) [`4ed5902e7`](https://github.com/gradio-app/gradio/commit/4ed5902e7dda2d95cd43e4ccaaef520ddd8eba57) - Adding basque language. Thanks [@EkhiAzur](https://github.com/EkhiAzur)!
+- [#5547](https://github.com/gradio-app/gradio/pull/5547) [`290f51871`](https://github.com/gradio-app/gradio/commit/290f5187160cdbd7a786494fe3c19b0e70abe167) - typo in UploadButton's docstring. Thanks [@chaeheum3](https://github.com/chaeheum3)!
+- [#5553](https://github.com/gradio-app/gradio/pull/5553) [`d1bf23cd2`](https://github.com/gradio-app/gradio/commit/d1bf23cd2c6da3692d7753856bfe7564d84778e0) - Modify Image examples docstring. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5563](https://github.com/gradio-app/gradio/pull/5563) [`ba64082ed`](https://github.com/gradio-app/gradio/commit/ba64082ed80c1ed9113497ae089e63f032dbcc75) - preprocess for components when type='index'. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.2
+
+### Fixes
+
+- [#5537](https://github.com/gradio-app/gradio/pull/5537) [`301c7878`](https://github.com/gradio-app/gradio/commit/301c7878217f9fc531c0f28330b394f02955811b) - allow gr.Image() examples to take urls. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5544](https://github.com/gradio-app/gradio/pull/5544) [`a0cc9ac9`](https://github.com/gradio-app/gradio/commit/a0cc9ac931554e06dcb091158c9b9ac0cc580b6c) - Fixes dropdown breaking if a user types in invalid value and presses enter. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.44.1
+
+### Fixes
+
+- [#5516](https://github.com/gradio-app/gradio/pull/5516) [`c5fe8eba`](https://github.com/gradio-app/gradio/commit/c5fe8ebadbf206e2f4199ccde4606e331a22148a) - Fix docstring of dropdown. Thanks [@hysts](https://github.com/hysts)!
+- [#5529](https://github.com/gradio-app/gradio/pull/5529) [`81c9ca9a`](https://github.com/gradio-app/gradio/commit/81c9ca9a2e00d19334f632fec32081d36ad54c7f) - Fix `.update()` method in `gr.Dropdown()` to handle `choices`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5528](https://github.com/gradio-app/gradio/pull/5528) [`dc86e4a7`](https://github.com/gradio-app/gradio/commit/dc86e4a7e1c40b910c74558e6f88fddf9b3292bc) - Lazy load all images. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5525](https://github.com/gradio-app/gradio/pull/5525) [`21f1db40`](https://github.com/gradio-app/gradio/commit/21f1db40de6d1717eba97a550e11422a457ba7e9) - Ensure input value saves on dropdown blur. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+## 3.44.0
+
+### Features
+
+- [#5505](https://github.com/gradio-app/gradio/pull/5505) [`9ee20f49`](https://github.com/gradio-app/gradio/commit/9ee20f499f62c1fe5af6b8f84918b3a334eb1c8d) - Validate i18n file names with ISO-639x. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5475](https://github.com/gradio-app/gradio/pull/5475) [`c60b89b0`](https://github.com/gradio-app/gradio/commit/c60b89b0a54758a27277f0a6aa20d0653647c7c8) - Adding Central Kurdish. Thanks [@Hrazhan](https://github.com/Hrazhan)!
+- [#5400](https://github.com/gradio-app/gradio/pull/5400) [`d112e261`](https://github.com/gradio-app/gradio/commit/d112e2611b0fc79ecedfaed367571f3157211387) - Allow interactive input in `gr.HighlightedText`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5488](https://github.com/gradio-app/gradio/pull/5488) [`8909e42a`](https://github.com/gradio-app/gradio/commit/8909e42a7c6272358ad413588d27a5124d151205) - Adds `autoscroll` param to `gr.Textbox()`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5384](https://github.com/gradio-app/gradio/pull/5384) [`ddc02268`](https://github.com/gradio-app/gradio/commit/ddc02268f731bd2ed04b7a5854accf3383f9a0da) - Allows the `gr.Dropdown` to have separate names and values, as well as enables `allow_custom_value` for multiselect dropdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5473](https://github.com/gradio-app/gradio/pull/5473) [`b271e738`](https://github.com/gradio-app/gradio/commit/b271e738860ca238ecdee2991f49b505c7559016) - Remove except asyncio.CancelledError which is no longer necessary due to 53d7025. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5474](https://github.com/gradio-app/gradio/pull/5474) [`041560f9`](https://github.com/gradio-app/gradio/commit/041560f9f11ca2560005b467bb412ee1becfc2b2) - Fix queueing.call_prediction to retrieve the default response class in the same manner as FastAPI's implementation. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5510](https://github.com/gradio-app/gradio/pull/5510) [`afcf3c48`](https://github.com/gradio-app/gradio/commit/afcf3c48e82712067d6d00a0caedb1562eb986f8) - Do not expose existence of files outside of working directory. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#5459](https://github.com/gradio-app/gradio/pull/5459) [`bd2fda77`](https://github.com/gradio-app/gradio/commit/bd2fda77fc98d815f4fb670f535af453ebee9b80) - Dispatch `stop_recording` event in Audio. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5508](https://github.com/gradio-app/gradio/pull/5508) [`05715f55`](https://github.com/gradio-app/gradio/commit/05715f5599ae3e928d3183c7b0a7f5291f843a96) - Adds a `filterable` parameter to `gr.Dropdown` that controls whether user can type to filter choices. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5470](https://github.com/gradio-app/gradio/pull/5470) [`a4e010a9`](https://github.com/gradio-app/gradio/commit/a4e010a96f1d8a52b3ac645e03fe472b9c3cbbb1) - Fix share button position. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5496](https://github.com/gradio-app/gradio/pull/5496) [`82ec4d26`](https://github.com/gradio-app/gradio/commit/82ec4d2622a43c31b248b78e9410e2ac918f6035) - Allow interface with components to be run inside blocks. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+## 3.43.2
+
+### Fixes
+
+- [#5456](https://github.com/gradio-app/gradio/pull/5456) [`6e381c4f`](https://github.com/gradio-app/gradio/commit/6e381c4f146cc8177a4e2b8e39f914f09cd7ff0c) - ensure dataframe doesn't steal focus. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.43.1
+
+### Fixes
+
+- [#5445](https://github.com/gradio-app/gradio/pull/5445) [`67bb7bcb`](https://github.com/gradio-app/gradio/commit/67bb7bcb6a95b7a00a8bdf612cf147850d919a44) - ensure dataframe doesn't scroll unless needed. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5447](https://github.com/gradio-app/gradio/pull/5447) [`7a4a89e5`](https://github.com/gradio-app/gradio/commit/7a4a89e5ca1dedb39e5366867501584b0c636bbb) - ensure iframe is correct size on spaces. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.43.0
+
+### Features
+
+- [#5165](https://github.com/gradio-app/gradio/pull/5165) [`c77f05ab`](https://github.com/gradio-app/gradio/commit/c77f05abb65b2828c9c19af4ec0a0c09412f9f6a) - Fix the Queue to call API endpoints without internal HTTP routing. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5427](https://github.com/gradio-app/gradio/pull/5427) [`aad7acd7`](https://github.com/gradio-app/gradio/commit/aad7acd7128dca05b227ecbba06db9f94d65b088) - Add sort to bar plot. Thanks [@Chaitanya134](https://github.com/Chaitanya134)!
+- [#5342](https://github.com/gradio-app/gradio/pull/5342) [`afac0006`](https://github.com/gradio-app/gradio/commit/afac0006337ce2840cf497cd65691f2f60ee5912) - significantly improve the performance of `gr.Dataframe` for large datasets. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5417](https://github.com/gradio-app/gradio/pull/5417) [`d14d63e3`](https://github.com/gradio-app/gradio/commit/d14d63e30c4af3f9c2a664fd11b0a01943a8300c) - Auto scroll to bottom of textbox. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+### Fixes
+
+- [#5412](https://github.com/gradio-app/gradio/pull/5412) [`26fef8c7`](https://github.com/gradio-app/gradio/commit/26fef8c7f85a006c7e25cdbed1792df19c512d02) - Skip view_api request in js client when auth enabled. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5436](https://github.com/gradio-app/gradio/pull/5436) [`7ab4b70f`](https://github.com/gradio-app/gradio/commit/7ab4b70f6821afb4e85cef225d1235c19df8ebbf) - api_open does not take precedence over show_api. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.42.0
+
+### Highlights
+
+#### Like/Dislike Button for Chatbot ([#5391](https://github.com/gradio-app/gradio/pull/5391) [`abf1c57d`](https://github.com/gradio-app/gradio/commit/abf1c57d7d85de0df233ee3b38aeb38b638477db))
+
+ Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+#### Added the ability to attach event listeners via decorators ([#5395](https://github.com/gradio-app/gradio/pull/5395) [`55fed04f`](https://github.com/gradio-app/gradio/commit/55fed04f559becb9c24f22cc6292dc572d709886))
+
+e.g.
+
+```python
+with gr.Blocks() as demo:
+ name = gr.Textbox(label="Name")
+ output = gr.Textbox(label="Output Box")
+ greet_btn = gr.Button("Greet")
+
+ @greet_btn.click(inputs=name, outputs=output)
+ def greet(name):
+ return "Hello " + name + "!"
+```
+
+ Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5334](https://github.com/gradio-app/gradio/pull/5334) [`c5bf9138`](https://github.com/gradio-app/gradio/commit/c5bf91385a632dc9f612499ee01166ac6ae509a9) - Add chat bubble width param. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5267](https://github.com/gradio-app/gradio/pull/5267) [`119c8343`](https://github.com/gradio-app/gradio/commit/119c834331bfae60d4742c8f20e9cdecdd67e8c2) - Faster reload mode. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5373](https://github.com/gradio-app/gradio/pull/5373) [`79d8f9d8`](https://github.com/gradio-app/gradio/commit/79d8f9d891901683c5a1b7486efb44eab2478c96) - Adds `height` and `zoom_speed` parameters to `Model3D` component, as well as a button to reset the camera position. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5370](https://github.com/gradio-app/gradio/pull/5370) [`61803c65`](https://github.com/gradio-app/gradio/commit/61803c6545e73fce47e8740bd46721ab9bb0ba5c) - chore(deps): update dependency extendable-media-recorder to v9. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5266](https://github.com/gradio-app/gradio/pull/5266) [`4ccb9a86`](https://github.com/gradio-app/gradio/commit/4ccb9a86f194c6997f80a09880edc3c2b0554aab) - Makes it possible to set the initial camera position for the `Model3D` component as a tuple of (alpha, beta, radius). Thanks [@mbahri](https://github.com/mbahri)!
+- [#5271](https://github.com/gradio-app/gradio/pull/5271) [`97c3c7b1`](https://github.com/gradio-app/gradio/commit/97c3c7b1730407f9e80566af9ecb4ca7cccf62ff) - Move scripts from old website to CI. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5369](https://github.com/gradio-app/gradio/pull/5369) [`b8968898`](https://github.com/gradio-app/gradio/commit/b89688984fa9c6be0db06e392e6935a544620764) - Fix typo in utils.py. Thanks [@eltociear](https://github.com/eltociear)!
+
+### Fixes
+
+- [#5304](https://github.com/gradio-app/gradio/pull/5304) [`05892302`](https://github.com/gradio-app/gradio/commit/05892302fb8fe2557d57834970a2b65aea97355b) - Adds kwarg to disable html sanitization in `gr.Chatbot()`. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5366](https://github.com/gradio-app/gradio/pull/5366) [`0cc7e2dc`](https://github.com/gradio-app/gradio/commit/0cc7e2dcf60e216e0a30e2f85a9879ce3cb2a1bd) - Hide avatar when message none. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5393](https://github.com/gradio-app/gradio/pull/5393) [`e4e7a431`](https://github.com/gradio-app/gradio/commit/e4e7a4319924aaf51dcb18d07d0c9953d4011074) - Renders LaTeX that is added to the page in `gr.Markdown`, `gr.Chatbot`, and `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5394](https://github.com/gradio-app/gradio/pull/5394) [`4d94ea0a`](https://github.com/gradio-app/gradio/commit/4d94ea0a0cf2103cda19f48398a5634f8341d04d) - Adds horizontal scrolling to content that overflows in gr.Markdown. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5368](https://github.com/gradio-app/gradio/pull/5368) [`b27f7583`](https://github.com/gradio-app/gradio/commit/b27f7583254165b135bf1496a7d8c489a62ba96f) - Change markdown rendering to set breaks to false. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5360](https://github.com/gradio-app/gradio/pull/5360) [`64666525`](https://github.com/gradio-app/gradio/commit/6466652583e3c620df995fb865ef3511a34cb676) - Cancel Dropdown Filter. Thanks [@deckar01](https://github.com/deckar01)!
+
+## 3.41.2
+
+### Features
+
+- [#5284](https://github.com/gradio-app/gradio/pull/5284) [`5f25eb68`](https://github.com/gradio-app/gradio/commit/5f25eb6836f6a78ce6208b53495a01e1fc1a1d2f) - Minor bug fix sweep. Thanks [@aliabid94](https://github.com/aliabid94)!/n - Our use of __exit__ was catching errors and corrupting the traceback of any component that failed to instantiate (try running blocks_kitchen_sink off main for an example). Now the __exit__ exits immediately if there's been an exception, so the original exception can be printed cleanly/n - HighlightedText was rendering weird, cleaned it up
+
+### Fixes
+
+- [#5319](https://github.com/gradio-app/gradio/pull/5319) [`3341148c`](https://github.com/gradio-app/gradio/commit/3341148c109b5458cc88435d27eb154210efc472) - Fix: wrap avatar-image in a div to clip its shape. Thanks [@Keldos-Li](https://github.com/Keldos-Li)!
+- [#5340](https://github.com/gradio-app/gradio/pull/5340) [`df090e89`](https://github.com/gradio-app/gradio/commit/df090e89f74a16e4cb2b700a1e3263cabd2bdd91) - Fix Checkbox select dispatch. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+## 3.41.1
+
+### Fixes
+
+- [#5324](https://github.com/gradio-app/gradio/pull/5324) [`31996c99`](https://github.com/gradio-app/gradio/commit/31996c991d6bfca8cef975eb8e3c9f61a7aced19) - ensure login form has correct styles. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5323](https://github.com/gradio-app/gradio/pull/5323) [`e32b0928`](https://github.com/gradio-app/gradio/commit/e32b0928d2d00342ca917ebb10c379ffc2ec200d) - ensure dropdown stays open when identical data is passed in. Thanks [@pngwn](https://github.com/pngwn)!
+
+## 3.41.0
+
+### Highlights
+
+#### Improve startup performance and markdown support ([#5279](https://github.com/gradio-app/gradio/pull/5279) [`fe057300`](https://github.com/gradio-app/gradio/commit/fe057300f0672c62dab9d9b4501054ac5d45a4ec))
+
+##### Improved markdown support
+
+We now have better support for markdown in `gr.Markdown` and `gr.Dataframe`. Including syntax highlighting and Github Flavoured Markdown. We also have more consistent markdown behaviour and styling.
+
+##### Various performance improvements
+
+These improvements will be particularly beneficial to large applications.
+
+- Rather than attaching events manually, they are now delegated, leading to a significant performance improvement and addressing a performance regression introduced in a recent version of Gradio. App startup for large applications is now around twice as fast.
+- Optimised the mounting of individual components, leading to a modest performance improvement during startup (~30%).
+- Corrected an issue that was causing markdown to re-render infinitely.
+- Ensured that the `gr.3DModel` does re-render prematurely.
+
+ Thanks [@pngwn](https://github.com/pngwn)!
+
+#### Enable streaming audio in python client ([#5248](https://github.com/gradio-app/gradio/pull/5248) [`390624d8`](https://github.com/gradio-app/gradio/commit/390624d8ad2b1308a5bf8384435fd0db98d8e29e))
+
+The `gradio_client` now supports streaming file outputs 🌊
+
+No new syntax! Connect to a gradio demo that supports streaming file outputs and call `predict` or `submit` as you normally would.
+
+```python
+import gradio_client as grc
+client = grc.Client("gradio/stream_audio_out")
+
+# Get the entire generated audio as a local file
+client.predict("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+job = client.submit("/Users/freddy/Pictures/bark_demo.mp4", api_name="/predict")
+
+# Get the entire generated audio as a local file
+job.result()
+
+# Each individual chunk
+job.outputs()
+```
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+#### Add `render` function to `` ([#5158](https://github.com/gradio-app/gradio/pull/5158) [`804fcc05`](https://github.com/gradio-app/gradio/commit/804fcc058e147f283ece67f1f353874e26235535))
+
+We now have an event `render` on the web component, which is triggered once the embedded space has finished rendering.
+
+```html
+
+```
+
+ Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Features
+
+- [#5268](https://github.com/gradio-app/gradio/pull/5268) [`f49028cf`](https://github.com/gradio-app/gradio/commit/f49028cfe3e21097001ddbda71c560b3d8b42e1c) - Move markdown & latex processing to the frontend for the gr.Markdown and gr.DataFrame components. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5215](https://github.com/gradio-app/gradio/pull/5215) [`fbdad78a`](https://github.com/gradio-app/gradio/commit/fbdad78af4c47454cbb570f88cc14bf4479bbceb) - Lazy load interactive or static variants of a component individually, rather than loading both variants regardless. This change will improve performance for many applications. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5216](https://github.com/gradio-app/gradio/pull/5216) [`4b58ea6d`](https://github.com/gradio-app/gradio/commit/4b58ea6d98e7a43b3f30d8a4cb6f379bc2eca6a8) - Update i18n tokens and locale files. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5283](https://github.com/gradio-app/gradio/pull/5283) [`a7460557`](https://github.com/gradio-app/gradio/commit/a74605572dd0d6bb41df6b38b120d656370dd67d) - Add height parameter and scrolling to `gr.Dataframe`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5232](https://github.com/gradio-app/gradio/pull/5232) [`c57d4c23`](https://github.com/gradio-app/gradio/commit/c57d4c232a97e03b4671f9e9edc3af456438fe89) - `gr.Radio` and `gr.CheckboxGroup` can now accept different names and values. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5219](https://github.com/gradio-app/gradio/pull/5219) [`e8fd4e4e`](https://github.com/gradio-app/gradio/commit/e8fd4e4ec68a6c974bc8c84b61f4a0ec50a85bc6) - Add `api_name` parameter to `gr.Interface`. Additionally, completely hide api page if show_api=False. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5280](https://github.com/gradio-app/gradio/pull/5280) [`a2f42e28`](https://github.com/gradio-app/gradio/commit/a2f42e28bd793bce4bed6d54164bb2a327a46fd5) - Allow updating the label of `gr.UpdateButton`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5112](https://github.com/gradio-app/gradio/pull/5112) [`1cefee7f`](https://github.com/gradio-app/gradio/commit/1cefee7fc05175aca23ba04b3a3fda7b97f49bf0) - chore(deps): update dependency marked to v7. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5260](https://github.com/gradio-app/gradio/pull/5260) [`a773eaf7`](https://github.com/gradio-app/gradio/commit/a773eaf7504abb53b99885b3454dc1e027adbb42) - Stop passing inputs and preprocessing on iterators. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#4943](https://github.com/gradio-app/gradio/pull/4943) [`947d615d`](https://github.com/gradio-app/gradio/commit/947d615db6f76519d0e8bc0d1a0d7edf89df267b) - Sign in with Hugging Face (OAuth support). Thanks [@Wauplin](https://github.com/Wauplin)!
+- [#5298](https://github.com/gradio-app/gradio/pull/5298) [`cf167cd1`](https://github.com/gradio-app/gradio/commit/cf167cd1dd4acd9aee225ff1cb6fac0e849806ba) - Create event listener table for components on docs. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5173](https://github.com/gradio-app/gradio/pull/5173) [`730f0c1d`](https://github.com/gradio-app/gradio/commit/730f0c1d54792eb11359e40c9f2326e8a6e39203) - Ensure gradio client works as expected for functions that return nothing. Thanks [@raymondtri](https://github.com/raymondtri)!
+- [#5188](https://github.com/gradio-app/gradio/pull/5188) [`b22e1888`](https://github.com/gradio-app/gradio/commit/b22e1888fcf0843520525c1e4b7e1fe73fdeb948) - Fix the images in the theme builder to use permanent URI. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5221](https://github.com/gradio-app/gradio/pull/5221) [`f344592a`](https://github.com/gradio-app/gradio/commit/f344592aeb1658013235ded154107f72d86f24e7) - Allows setting a height to `gr.File` and improves the UI of the component. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5265](https://github.com/gradio-app/gradio/pull/5265) [`06982212`](https://github.com/gradio-app/gradio/commit/06982212dfbd613853133d5d0eebd75577967027) - Removes scrollbar from File preview when not needed. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5305](https://github.com/gradio-app/gradio/pull/5305) [`15075241`](https://github.com/gradio-app/gradio/commit/15075241fa7ad3f7fd9ae2a91e54faf8f19a46f9) - Rotate axes labels on LinePlot, BarPlot, and ScatterPlot. Thanks [@Faiga91](https://github.com/Faiga91)!
+- [#5258](https://github.com/gradio-app/gradio/pull/5258) [`92282cea`](https://github.com/gradio-app/gradio/commit/92282cea6afdf7e9930ece1046d8a63be34b3cea) - Chatbot Avatar Images. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5244](https://github.com/gradio-app/gradio/pull/5244) [`b3e50db9`](https://github.com/gradio-app/gradio/commit/b3e50db92f452f376aa2cc081326d40bb69d6dd7) - Remove aiohttp dependency. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5264](https://github.com/gradio-app/gradio/pull/5264) [`46a2b600`](https://github.com/gradio-app/gradio/commit/46a2b600a7ff030a9ea1560b882b3bf3ad266bbc) - ensure translations for audio work correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#5256](https://github.com/gradio-app/gradio/pull/5256) [`933db53e`](https://github.com/gradio-app/gradio/commit/933db53e93a1229fdf149556d61da5c4c7e1a331) - Better handling of empty dataframe in `gr.DataFrame`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5242](https://github.com/gradio-app/gradio/pull/5242) [`2b397791`](https://github.com/gradio-app/gradio/commit/2b397791fe2059e4beb72937ff0436f2d4d28b4b) - Fix message text overflow onto copy button in `gr.Chatbot`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5253](https://github.com/gradio-app/gradio/pull/5253) [`ddac7e4d`](https://github.com/gradio-app/gradio/commit/ddac7e4d0f55c3bdc6c3e9a9e24588b2563e4049) - Ensure File component uploads files to the server. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5179](https://github.com/gradio-app/gradio/pull/5179) [`6fb92b48`](https://github.com/gradio-app/gradio/commit/6fb92b48a916104db573602011a448b904d42e5e) - Fixes audio streaming issues. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5295](https://github.com/gradio-app/gradio/pull/5295) [`7b8fa8aa`](https://github.com/gradio-app/gradio/commit/7b8fa8aa58f95f5046b9add64b40368bd3f1b700) - Allow caching examples with streamed output. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#5285](https://github.com/gradio-app/gradio/pull/5285) [`cdfd4217`](https://github.com/gradio-app/gradio/commit/cdfd42174a9c777eaee9c1209bf8e90d8c7791f2) - Tweaks to `icon` parameter in `gr.Button()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5122](https://github.com/gradio-app/gradio/pull/5122) [`3b805346`](https://github.com/gradio-app/gradio/commit/3b8053469aca6c7a86a6731e641e4400fc34d7d3) - Allows code block in chatbot to scroll horizontally. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+- [#5312](https://github.com/gradio-app/gradio/pull/5312) [`f769cb67`](https://github.com/gradio-app/gradio/commit/f769cb67149d8e209091508f06d87014acaed965) - only start listening for events after the components are mounted. Thanks [@pngwn](https://github.com/pngwn)!
+- [#5254](https://github.com/gradio-app/gradio/pull/5254) [`c39f06e1`](https://github.com/gradio-app/gradio/commit/c39f06e16b9feea97984e4822df35a99c807461c) - Fix `.update()` for `gr.Radio()` and `gr.CheckboxGroup()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5231](https://github.com/gradio-app/gradio/pull/5231) [`87f1c2b4`](https://github.com/gradio-app/gradio/commit/87f1c2b4ac7c685c43477215fa5b96b6cbeffa05) - Allow `gr.Interface.from_pipeline()` and `gr.load()` to work within `gr.Blocks()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5238](https://github.com/gradio-app/gradio/pull/5238) [`de23e9f7`](https://github.com/gradio-app/gradio/commit/de23e9f7d67e685e791faf48a21f34121f6d094a) - Improve audio streaming. Thanks [@aliabid94](https://github.com/aliabid94)!/n - Proper audio streaming with WAV files. We now do the proper processing to stream out wav files as a single stream of audio without any cracks in the seams./n - Audio streaming with bytes. Stream any audio type by yielding out bytes, and it should work flawlessly.
+- [#5313](https://github.com/gradio-app/gradio/pull/5313) [`54bcb724`](https://github.com/gradio-app/gradio/commit/54bcb72417b2781ad9d7500ea0f89aa9d80f7d8f) - Restores missing part of bottom border on file component. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5235](https://github.com/gradio-app/gradio/pull/5235) [`1ecf88ac`](https://github.com/gradio-app/gradio/commit/1ecf88ac5f20bc5a1c91792d1a68559575e6afd7) - fix #5229. Thanks [@breengles](https://github.com/breengles)!
+- [#5276](https://github.com/gradio-app/gradio/pull/5276) [`502f1015`](https://github.com/gradio-app/gradio/commit/502f1015bf23b365bc32446dd2e549b0c5d0dc72) - Ensure `Blocks` translation copy renders correctly. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5296](https://github.com/gradio-app/gradio/pull/5296) [`a0f22626`](https://github.com/gradio-app/gradio/commit/a0f22626f2aff297754414bbc83d5c4cfe086ea0) - `make_waveform()` twitter video resolution fix. Thanks [@dawoodkhan82](https://github.com/dawoodkhan82)!
+
+## 3.40.0
+
+### Highlights
+
+#### Client.predict will now return the final output for streaming endpoints ([#5057](https://github.com/gradio-app/gradio/pull/5057) [`35856f8b`](https://github.com/gradio-app/gradio/commit/35856f8b54548cae7bd3b8d6a4de69e1748283b2))
+
+### This is a breaking change (for gradio_client only)!
+
+Previously, `Client.predict` would only return the first output of an endpoint that streamed results. This was causing confusion for developers that wanted to call these streaming demos via the client.
+
+We realize that developers using the client don't know the internals of whether a demo streams or not, so we're changing the behavior of predict to match developer expectations.
+
+Using `Client.predict` will now return the final output of a streaming endpoint. This will make it even easier to use gradio apps via the client.
+
+ Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+#### Gradio now supports streaming audio outputs
+
+Allows users to use generators to stream audio out, yielding consecutive chunks of audio. Requires `streaming=True` to be set on the output audio.
+
+```python
+import gradio as gr
+from pydub import AudioSegment
+
+def stream_audio(audio_file):
+ audio = AudioSegment.from_mp3(audio_file)
+ i = 0
+ chunk_size = 3000
+
+ while chunk_size*i < len(audio):
+ chunk = audio[chunk_size*i:chunk_size*(i+1)]
+ i += 1
+ if chunk:
+ file = f"/tmp/{i}.mp3"
+ chunk.export(file, format="mp3")
+ yield file
+
+demo = gr.Interface(
+ fn=stream_audio,
+ inputs=gr.Audio(type="filepath", label="Audio file to stream"),
+ outputs=gr.Audio(autoplay=True, streaming=True),
+)
+
+demo.queue().launch()
+```
+
+From the backend, streamed outputs are served from the `/stream/` endpoint instead of the `/file/` endpoint. Currently just used to serve audio streaming output. The output JSON will have `is_stream`: `true`, instead of `is_file`: `true` in the file data object. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+### Features
+
+- [#5081](https://github.com/gradio-app/gradio/pull/5081) [`d7f83823`](https://github.com/gradio-app/gradio/commit/d7f83823fbd7604456b0127d689a63eed759807d) - solve how can I config root_path dynamically? #4968. Thanks [@eastonsuo](https://github.com/eastonsuo)!
+- [#5025](https://github.com/gradio-app/gradio/pull/5025) [`6693660a`](https://github.com/gradio-app/gradio/commit/6693660a790996f8f481feaf22a8c49130d52d89) - Add download button to selected images in `Gallery`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5133](https://github.com/gradio-app/gradio/pull/5133) [`61129052`](https://github.com/gradio-app/gradio/commit/61129052ed1391a75c825c891d57fa0ad6c09fc8) - Update dependency esbuild to ^0.19.0. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5125](https://github.com/gradio-app/gradio/pull/5125) [`80be7a1c`](https://github.com/gradio-app/gradio/commit/80be7a1ca44c0adef1668367b2cf36b65e52e576) - chatbot conversation nodes can contain a copy button. Thanks [@fazpu](https://github.com/fazpu)!
+- [#5048](https://github.com/gradio-app/gradio/pull/5048) [`0b74a159`](https://github.com/gradio-app/gradio/commit/0b74a1595b30df744e32a2c358c07acb7fd1cfe5) - Use `importlib` in favor of deprecated `pkg_resources`. Thanks [@jayceslesar](https://github.com/jayceslesar)!
+- [#5045](https://github.com/gradio-app/gradio/pull/5045) [`3b9494f5`](https://github.com/gradio-app/gradio/commit/3b9494f5c57e6b52e6a040ce8d6b5141f780e84d) - Lite: Fix the analytics module to use asyncio to work in the Wasm env. Thanks [@whitphx](https://github.com/whitphx)!
+- [#5046](https://github.com/gradio-app/gradio/pull/5046) [`5244c587`](https://github.com/gradio-app/gradio/commit/5244c5873c355cf3e2f0acb7d67fda3177ef8b0b) - Allow new lines in `HighlightedText` with `/n` and preserve whitespace. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5076](https://github.com/gradio-app/gradio/pull/5076) [`2745075a`](https://github.com/gradio-app/gradio/commit/2745075a26f80e0e16863d483401ff1b6c5ada7a) - Add deploy_discord to docs. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5116](https://github.com/gradio-app/gradio/pull/5116) [`0dc49b4c`](https://github.com/gradio-app/gradio/commit/0dc49b4c517706f572240f285313a881089ced79) - Add support for async functions and async generators to `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5047](https://github.com/gradio-app/gradio/pull/5047) [`883ac364`](https://github.com/gradio-app/gradio/commit/883ac364f69d92128774ac446ce49bdf8415fd7b) - Add `step` param to `Number`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5137](https://github.com/gradio-app/gradio/pull/5137) [`22aa5eba`](https://github.com/gradio-app/gradio/commit/22aa5eba3fee3f14473e4b0fac29cf72fe31ef04) - Use font size `--text-md` for `` in Chatbot messages. Thanks [@jaywonchung](https://github.com/jaywonchung)!
+- [#5005](https://github.com/gradio-app/gradio/pull/5005) [`f5539c76`](https://github.com/gradio-app/gradio/commit/f5539c7618e31451420bd3228754774da14dc65f) - Enhancement: Add focus event to textbox and number component. Thanks [@JodyZ0203](https://github.com/JodyZ0203)!
+- [#5104](https://github.com/gradio-app/gradio/pull/5104) [`34f6b22e`](https://github.com/gradio-app/gradio/commit/34f6b22efbfedfa569d452f3f99ed2e6593e3c21) - Strip leading and trailing spaces from username in login route. Thanks [@sweep-ai](https://github.com/apps/sweep-ai)!
+- [#5149](https://github.com/gradio-app/gradio/pull/5149) [`144df459`](https://github.com/gradio-app/gradio/commit/144df459a3b7895e524defcfc4c03fbb8b083aca) - Add `show_edit_button` param to `gr.Audio`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5136](https://github.com/gradio-app/gradio/pull/5136) [`eaa1ce14`](https://github.com/gradio-app/gradio/commit/eaa1ce14ac41de1c23321e93f11f1b03a2f3c7f4) - Enhancing Tamil Translation: Language Refinement 🌟. Thanks [@sanjaiyan-dev](https://github.com/sanjaiyan-dev)!
+- [#5035](https://github.com/gradio-app/gradio/pull/5035) [`8b4eb8ca`](https://github.com/gradio-app/gradio/commit/8b4eb8cac9ea07bde31b44e2006ca2b7b5f4de36) - JS Client: Fixes cannot read properties of null (reading 'is_file'). Thanks [@raymondtri](https://github.com/raymondtri)!
+- [#5023](https://github.com/gradio-app/gradio/pull/5023) [`e6317d77`](https://github.com/gradio-app/gradio/commit/e6317d77f87d3dad638acca3dbc4a9228570e63c) - Update dependency extendable-media-recorder to v8. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5085](https://github.com/gradio-app/gradio/pull/5085) [`13e47835`](https://github.com/gradio-app/gradio/commit/13e478353532c4af18cfa50772f8b6fb3c6c9818) - chore(deps): update dependency extendable-media-recorder to v8. Thanks [@renovate](https://github.com/apps/renovate)!
+- [#5080](https://github.com/gradio-app/gradio/pull/5080) [`37caa2e0`](https://github.com/gradio-app/gradio/commit/37caa2e0fe95d6cab8beb174580fb557904f137f) - Add icon and link params to `gr.Button`. Thanks [@hannahblair](https://github.com/hannahblair)!
+
+### Fixes
+
+- [#5062](https://github.com/gradio-app/gradio/pull/5062) [`7d897165`](https://github.com/gradio-app/gradio/commit/7d89716519d0751072792c9bbda668ffeb597296) - `gr.Dropdown` now has correct behavior in static mode as well as when an option is selected. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5077](https://github.com/gradio-app/gradio/pull/5077) [`667875b2`](https://github.com/gradio-app/gradio/commit/667875b2441753e74d25bd9d3c8adedd8ede11cd) - Live audio streaming output
+- [#5118](https://github.com/gradio-app/gradio/pull/5118) [`1b017e68`](https://github.com/gradio-app/gradio/commit/1b017e68f6a9623cc2ec085bd20e056229552028) - Add `interactive` args to `gr.ColorPicker`. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5114](https://github.com/gradio-app/gradio/pull/5114) [`56d2609d`](https://github.com/gradio-app/gradio/commit/56d2609de93387a75dc82b1c06c1240c5b28c0b8) - Reset textbox value to empty string when value is None. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#5075](https://github.com/gradio-app/gradio/pull/5075) [`67265a58`](https://github.com/gradio-app/gradio/commit/67265a58027ef1f9e4c0eb849a532f72eaebde48) - Allow supporting >1000 files in `gr.File()` and `gr.UploadButton()`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5135](https://github.com/gradio-app/gradio/pull/5135) [`80727bbe`](https://github.com/gradio-app/gradio/commit/80727bbe2c6d631022054edf01515017691b3bdd) - Fix dataset features and dataset preview for HuggingFaceDatasetSaver. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+- [#5039](https://github.com/gradio-app/gradio/pull/5039) [`620e4645`](https://github.com/gradio-app/gradio/commit/620e46452729d6d4877b3fab84a65daf2f2b7bc6) - `gr.Dropdown()` now supports values with arbitrary characters and doesn't clear value when re-focused. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5061](https://github.com/gradio-app/gradio/pull/5061) [`136adc9c`](https://github.com/gradio-app/gradio/commit/136adc9ccb23e5cb4d02d2e88f23f0b850041f98) - Ensure `gradio_client` is backwards compatible with `gradio==3.24.1`. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5129](https://github.com/gradio-app/gradio/pull/5129) [`97d804c7`](https://github.com/gradio-app/gradio/commit/97d804c748be9acfe27b8369dd2d64d61f43c2e7) - [Spaces] ZeroGPU Queue fix. Thanks [@cbensimon](https://github.com/cbensimon)!
+- [#5140](https://github.com/gradio-app/gradio/pull/5140) [`cd1353fa`](https://github.com/gradio-app/gradio/commit/cd1353fa3eb1b015f5860ca5d5a8e8d1aa4a831c) - Fixes the display of minutes in the video player. Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#5111](https://github.com/gradio-app/gradio/pull/5111) [`b84a35b7`](https://github.com/gradio-app/gradio/commit/b84a35b7b91eca947f787648ceb361b1d023427b) - Add icon and link to DuplicateButton. Thanks [@aliabd](https://github.com/aliabd)!
+- [#5030](https://github.com/gradio-app/gradio/pull/5030) [`f6c491b0`](https://github.com/gradio-app/gradio/commit/f6c491b079d335af633dd854c68eb26f9e61c552) - highlightedtext throws an error basing on model. Thanks [@rajeunoia](https://github.com/rajeunoia)!
+
+## 3.39.0
+
+### Highlights
+
+#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
+
+We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
+
+It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
+
+_🦙 Turning Llama 2 70b into a discord bot 🦙_
+
+```python
+import gradio_client as grc
+grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
+```
+
+
+
+#### Getting started with template spaces
+
+To help get you started, we have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) with template spaces you can use to turn state of the art LLMs powered by Gradio to discord bots.
+
+Currently we have template spaces for:
+
+- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
+- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
+- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
+
+But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
+
+❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
+
+Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
+
+### Features
+
+- [#4995](https://github.com/gradio-app/gradio/pull/4995) [`3f8c210b`](https://github.com/gradio-app/gradio/commit/3f8c210b01ef1ceaaf8ee73be4bf246b5b745bbf) - Implement left and right click in `Gallery` component and show implicit images in `Gallery` grid. Thanks [@hannahblair](https://github.com/hannahblair)!
+- [#4993](https://github.com/gradio-app/gradio/pull/4993) [`dc07a9f9`](https://github.com/gradio-app/gradio/commit/dc07a9f947de44b419d8384987a02dcf94977851) - Bringing back the "Add download button for audio" PR by [@leuryr](https://github.com/leuryr). Thanks [@abidlabs](https://github.com/abidlabs)!
+- [#4979](https://github.com/gradio-app/gradio/pull/4979) [`44ac8ad0`](https://github.com/gradio-app/gradio/commit/44ac8ad08d82ea12c503dde5c78f999eb0452de2) - Allow setting sketch color default. Thanks [@aliabid94](https://github.com/aliabid94)!
+- [#4985](https://github.com/gradio-app/gradio/pull/4985) [`b74f8453`](https://github.com/gradio-app/gradio/commit/b74f8453034328f0e42da8e41785f5eb039b45d7) - Adds `additional_inputs` to `gr.ChatInterface`. Thanks [@abidlabs](https://github.com/abidlabs)!
+
+### Fixes
+
+- [#4997](https://github.com/gradio-app/gradio/pull/4997) [`41c83070`](https://github.com/gradio-app/gradio/commit/41c83070b01632084e7d29123048a96c1e261407) - Add CSS resets and specifiers to play nice with HF blog. Thanks [@aliabid94](https://github.com/aliabid94)!
+
+## 3.38
+
+### New Features:
+
+- Provide a parameter `animate` (`False` by default) in `gr.make_waveform()` which animates the overlayed waveform by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4918](https://github.com/gradio-app/gradio/pull/4918)
+- Add `show_download_button` param to allow the download button in static Image components to be hidden by [@hannahblair](https://github.com/hannahblair) in [PR 4959](https://github.com/gradio-app/gradio/pull/4959)
+- Added autofocus argument to Textbox by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
+- The `gr.ChatInterface` UI now converts the "Submit" button to a "Stop" button in ChatInterface while streaming, which can be used to pause generation. By [@abidlabs](https://github.com/abidlabs) in [PR 4971](https://github.com/gradio-app/gradio/pull/4971).
+- Add a `border_color_accent_subdued` theme variable to add a subdued border color to accented items. This is used by chatbot user messages. Set the value of this variable in `Default` theme to `*primary_200`. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4989](https://github.com/gradio-app/gradio/pull/4989)
+- Add default sketch color argument `brush_color`. Also, masks drawn on images are now slightly translucent (and mask color can also be set via brush_color). By [@aliabid94](https://github.com/aliabid94) in [PR 4979](https://github.com/gradio-app/gradio/pull/4979)
+
+### Bug Fixes:
+
+- Fixes `cancels` for generators so that if a generator is canceled before it is complete, subsequent runs of the event do not continue from the previous iteration, but rather start from the beginning. By [@abidlabs](https://github.com/abidlabs) in [PR 4969](https://github.com/gradio-app/gradio/pull/4969).
+- Use `gr.State` in `gr.ChatInterface` to reduce latency by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4976](https://github.com/gradio-app/gradio/pull/4976)
+- Fix bug with `gr.Interface` where component labels inferred from handler parameters were including special args like `gr.Request` or `gr.EventData`. By [@cbensimon](https://github.com/cbensimon) in [PR 4956](https://github.com/gradio-app/gradio/pull/4956)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Other Changes:
+
+- Apply pyright to the `components` directory by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4948](https://github.com/gradio-app/gradio/pull/4948)
+- Improved look of ChatInterface by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
+
+## 3.37
+
+### New Features:
+
+Introducing a new `gr.ChatInterface` abstraction, which allows Gradio users to build fully functioning Chat interfaces very easily. The only required parameter is a chat function `fn`, which accepts a (string) user input `message` and a (list of lists) chat `history` and returns a (string) response. Here's a toy example:
+
+```py
+import gradio as gr
+
+def echo(message, history):
+ return message
+
+demo = gr.ChatInterface(fn=echo, examples=["hello", "hola", "merhaba"], title="Echo Bot")
+demo.launch()
+```
+
+Which produces:
+
+
+
+And a corresponding easy-to-use API at `/chat`:
+
+
+
+The `gr.ChatInterface` abstraction works nicely with various LLM libraries, such as `langchain`. See the [dedicated guide](https://gradio.app/guides/creating-a-chatbot-fast) for more examples using `gr.ChatInterface`. Collective team effort in [PR 4869](https://github.com/gradio-app/gradio/pull/4869)
+
+- Chatbot messages now show hyperlinks to download files uploaded to `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4848](https://github.com/gradio-app/gradio/pull/4848)
+- Cached examples now work with generators and async generators by [@abidlabs](https://github.com/abidlabs) in [PR 4927](https://github.com/gradio-app/gradio/pull/4927)
+- Add RTL support to `gr.Markdown`, `gr.Chatbot`, `gr.Textbox` (via the `rtl` boolean parameter) and text-alignment to `gr.Textbox`(via the string `text_align` parameter) by [@abidlabs](https://github.com/abidlabs) in [PR 4933](https://github.com/gradio-app/gradio/pull/4933)
+
+Examples of usage:
+
+```py
+with gr.Blocks() as demo:
+ gr.Textbox(interactive=True, text_align="right")
+demo.launch()
+```
+
+```py
+with gr.Blocks() as demo:
+ gr.Markdown("سلام", rtl=True)
+demo.launch()
+```
+
+- The `get_api_info` method of `Blocks` now supports layout output components [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
+
+- Added the support for the new command `gradio environment`to make it easier for people to file bug reports if we shipped an easy command to list the OS, gradio version, and versions of gradio/gradio-client dependencies. bu [@varshneydevansh](https://github.com/varshneydevansh) in [PR 4915](https://github.com/gradio-app/gradio/pull/4915).
+
+### Bug Fixes:
+
+- The `.change()` event is fixed in `Video` and `Image` so that it only fires once by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
+- The `.change()` event is fixed in `Audio` so that fires when the component value is programmatically updated by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
+
+* Add missing `display: flex` property to `Row` so that flex styling is applied to children by [@hannahblair] in [PR 4896](https://github.com/gradio-app/gradio/pull/4896)
+* Fixed bug where `gr.Video` could not preprocess urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4904](https://github.com/gradio-app/gradio/pull/4904)
+* Fixed copy button rendering in API page on Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4924](https://github.com/gradio-app/gradio/pull/4924)
+* Fixed `gr.Group` and `container=False`. `container` parameter only available for `Textbox`, `Number`, and `Dropdown`, the only elements where it makes sense. By [@aliabid94](https://github.com/aliabid94) in [PR 4916](https://github.com/gradio-app/gradio/pull/4916)
+* Fixed broken image link in auto-generated `app.py` from `ThemeClass.push_to_hub` by [@deepkyu](https://github.com/deepkyu) in [PR 4944](https://github.com/gradio-app/gradio/pull/4944)
+
+### Other Changes:
+
+- Warning on mobile that if a user leaves the tab, websocket connection may break. On broken connection, tries to rejoin queue and displays error conveying connection broke. By [@aliabid94](https://github.com/aliabid94) in [PR 4742](https://github.com/gradio-app/gradio/pull/4742)
+- Remove blocking network calls made before the local URL gets printed - these slow down the display of the local URL, especially when no internet is available. [@aliabid94](https://github.com/aliabid94) in [PR 4905](https://github.com/gradio-app/gradio/pull/4905).
+- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
+- Queue `max_size` defaults to parent Blocks `max_thread` when running on Spaces with ZeroGPU hardware. By [@cbensimon](https://github.com/cbensimon) in [PR 4937](https://github.com/gradio-app/gradio/pull/4937)
+
+### Breaking Changes:
+
+Motivated by the release of `pydantic==2.0`, which included breaking changes that broke a large number of Gradio apps, we've pinned many gradio dependencies. Note that pinned dependencies can cause downstream conflicts, so this may be a breaking change. That being said, we've kept the pins pretty loose, and we're expecting change to be better for the long-term stability of Gradio apps.
+
+## 3.36.1
+
+### New Features:
+
+- Hotfix to support pydantic v1 and v2 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4835](https://github.com/gradio-app/gradio/pull/4835)
+
+### Bug Fixes:
+
+- Fix bug where `gr.File` change event was not triggered when the value was changed by another event by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4811](https://github.com/gradio-app/gradio/pull/4811)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.36.0
+
+### New Features:
+
+- The `gr.Video`, `gr.Audio`, `gr.Image`, `gr.Chatbot`, and `gr.Gallery` components now include a share icon when deployed on Spaces. This behavior can be modified by setting the `show_share_button` parameter in the component classes. by [@aliabid94](https://github.com/aliabid94) in [PR 4651](https://github.com/gradio-app/gradio/pull/4651)
+- Allow the web component `space`, `src`, and `host` attributes to be updated dynamically by [@pngwn](https://github.com/pngwn) in [PR 4461](https://github.com/gradio-app/gradio/pull/4461)
+- Suggestion for Spaces Duplication built into Gradio, by [@aliabid94](https://github.com/aliabid94) in [PR 4458](https://github.com/gradio-app/gradio/pull/4458)
+- The `api_name` parameter now accepts `False` as a value, which means it does not show up in named or unnamed endpoints. By [@abidlabs](https://github.com/aliabid94) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+- Added support for `pathlib.Path` in `gr.Video`, `gr.Gallery`, and `gr.Chatbot` by [sunilkumardash9](https://github.com/sunilkumardash9) in [PR 4581](https://github.com/gradio-app/gradio/pull/4581).
+
+### Bug Fixes:
+
+- Updated components with `info` attribute to update when `update()` is called on them. by [@jebarpg](https://github.com/jebarpg) in [PR 4715](https://github.com/gradio-app/gradio/pull/4715).
+- Ensure the `Image` components undo button works mode is `mask` or `color-sketch` by [@amyorz](https://github.com/AmyOrz) in [PR 4692](https://github.com/gradio-app/gradio/pull/4692)
+- Load the iframe resizer external asset asynchronously, by [@akx](https://github.com/akx) in [PR 4336](https://github.com/gradio-app/gradio/pull/4336)
+- Restored missing imports in `gr.components` by [@abidlabs](https://github.com/abidlabs) in [PR 4566](https://github.com/gradio-app/gradio/pull/4566)
+- Fix bug where `select` event was not triggered in `gr.Gallery` if `height` was set to be large with `allow_preview=False` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4551](https://github.com/gradio-app/gradio/pull/4551)
+- Fix bug where setting `visible=False` in `gr.Group` event did not work by [@abidlabs](https://github.com/abidlabs) in [PR 4567](https://github.com/gradio-app/gradio/pull/4567)
+- Fix `make_waveform` to work with paths that contain spaces [@akx](https://github.com/akx) in [PR 4570](https://github.com/gradio-app/gradio/pull/4570) & [PR 4578](https://github.com/gradio-app/gradio/pull/4578)
+- Send captured data in `stop_recording` event for `gr.Audio` and `gr.Video` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4554](https://github.com/gradio-app/gradio/pull/4554)
+- Fix bug in `gr.Gallery` where `height` and `object_fit` parameters where being ignored by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4576](https://github.com/gradio-app/gradio/pull/4576)
+- Fixes an HTML sanitization issue in DOMPurify where links in markdown were not opening in a new window by [@hannahblair] in [PR 4577](https://github.com/gradio-app/gradio/pull/4577)
+- Fixed Dropdown height rendering in Columns by [@aliabid94](https://github.com/aliabid94) in [PR 4584](https://github.com/gradio-app/gradio/pull/4584)
+- Fixed bug where `AnnotatedImage` css styling was causing the annotation masks to not be displayed correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4628](https://github.com/gradio-app/gradio/pull/4628)
+- Ensure that Gradio does not silently fail when running on a port that is occupied by [@abidlabs](https://github.com/abidlabs) in [PR 4624](https://github.com/gradio-app/gradio/pull/4624).
+- Fix double upload bug that caused lag in file uploads by [@aliabid94](https://github.com/aliabid94) in [PR 4661](https://github.com/gradio-app/gradio/pull/4661)
+- `Progress` component now appears even when no `iterable` is specified in `tqdm` constructor by [@itrushkin](https://github.com/itrushkin) in [PR 4475](https://github.com/gradio-app/gradio/pull/4475)
+- Deprecation warnings now point at the user code using those deprecated features, instead of Gradio internals, by (https://github.com/akx) in [PR 4694](https://github.com/gradio-app/gradio/pull/4694)
+- Adapt column widths in gr.Examples based on content by [@pngwn](https://github.com/pngwn) & [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4700](https://github.com/gradio-app/gradio/pull/4700)
+- The `plot` parameter deprecation warnings should now only be emitted for `Image` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
+- Removed uncessessary `type` deprecation warning by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
+- Ensure Audio autoplays works when `autoplay=True` and the video source is dynamically updated [@pngwn](https://github.com/pngwn) in [PR 4705](https://github.com/gradio-app/gradio/pull/4705)
+- When an error modal is shown in spaces, ensure we scroll to the top so it can be seen by [@pngwn](https://github.com/pngwn) in [PR 4712](https://github.com/gradio-app/gradio/pull/4712)
+- Update depedencies by [@pngwn](https://github.com/pngwn) in [PR 4675](https://github.com/gradio-app/gradio/pull/4675)
+- Fixes `gr.Dropdown` being cutoff at the bottom by [@abidlabs](https://github.com/abidlabs) in [PR 4691](https://github.com/gradio-app/gradio/pull/4691).
+- Scroll top when clicking "View API" in spaces by [@pngwn](https://github.com/pngwn) in [PR 4714](https://github.com/gradio-app/gradio/pull/4714)
+- Fix bug where `show_label` was hiding the entire component for `gr.Label` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4713](https://github.com/gradio-app/gradio/pull/4713)
+- Don't crash when uploaded image has broken EXIF data, by [@akx](https://github.com/akx) in [PR 4764](https://github.com/gradio-app/gradio/pull/4764)
+- Place toast messages at the top of the screen by [@pngwn](https://github.com/pngwn) in [PR 4796](https://github.com/gradio-app/gradio/pull/4796)
+- Fix regressed styling of Login page when auth is enabled by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4797](https://github.com/gradio-app/gradio/pull/4797)
+- Prevent broken scrolling to output on Spaces by [@aliabid94](https://github.com/aliabid94) in [PR 4822](https://github.com/gradio-app/gradio/pull/4822)
+
+### Other Changes:
+
+- Add `.git-blame-ignore-revs` by [@akx](https://github.com/akx) in [PR 4586](https://github.com/gradio-app/gradio/pull/4586)
+- Update frontend dependencies in [PR 4601](https://github.com/gradio-app/gradio/pull/4601)
+- Use `typing.Literal` where possible in gradio library and client by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4608](https://github.com/gradio-app/gradio/pull/4608)
+- Remove unnecessary mock json files for frontend E2E tests by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4625](https://github.com/gradio-app/gradio/pull/4625)
+- Update dependencies by [@pngwn](https://github.com/pngwn) in [PR 4643](https://github.com/gradio-app/gradio/pull/4643)
+- The theme builder now launches successfully, and the API docs are cleaned up. By [@abidlabs](https://github.com/aliabid94) in [PR 4683](https://github.com/gradio-app/gradio/pull/4683)
+- Remove `cleared_value` from some components as its no longer used internally by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4685](https://github.com/gradio-app/gradio/pull/4685)
+- Better errors when you define two Blocks and reference components in one Blocks from the events in the other Blocks [@abidlabs](https://github.com/abidlabs) in [PR 4738](https://github.com/gradio-app/gradio/pull/4738).
+- Better message when share link is not created by [@abidlabs](https://github.com/abidlabs) in [PR 4773](https://github.com/gradio-app/gradio/pull/4773).
+- Improve accessibility around selected images in gr.Gallery component by [@hannahblair](https://github.com/hannahblair) in [PR 4790](https://github.com/gradio-app/gradio/pull/4790)
+
+### Breaking Changes:
+
+[PR 4683](https://github.com/gradio-app/gradio/pull/4683) removes the explict named endpoint "load_examples" from gr.Interface that was introduced in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).
+
+## 3.35.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix chatbot streaming by [@aliabid94](https://github.com/aliabid94) in [PR 4537](https://github.com/gradio-app/gradio/pull/4537)
+- Fix chatbot height and scrolling by [@aliabid94](https://github.com/aliabid94) in [PR 4540](https://github.com/gradio-app/gradio/pull/4540)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.35.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix chatbot streaming by [@aliabid94](https://github.com/aliabid94) in [PR 4537](https://github.com/gradio-app/gradio/pull/4537)
+- Fix error modal position and text size by [@pngwn](https://github.com/pngwn) in [PR 4538](https://github.com/gradio-app/gradio/pull/4538).
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.35.0
+
+### New Features:
+
+- A `gr.ClearButton` which allows users to easily clear the values of components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)
+
+Example usage:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot([("Hello", "How are you?")])
+ with gr.Row():
+ textbox = gr.Textbox(scale=3, interactive=True)
+ gr.ClearButton([textbox, chatbot], scale=1)
+
+demo.launch()
+```
+
+- Min and max value for gr.Number by [@artegoser](https://github.com/artegoser) and [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3991](https://github.com/gradio-app/gradio/pull/3991)
+- Add `start_recording` and `stop_recording` events to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4422](https://github.com/gradio-app/gradio/pull/4422)
+- Allow any function to generate an error message and allow multiple messages to appear at a time. Other error modal improvements such as auto dismiss after a time limit and a new layout on mobile [@pngwn](https://github.com/pngwn) in [PR 4459](https://github.com/gradio-app/gradio/pull/4459).
+- Add `autoplay` kwarg to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4453](https://github.com/gradio-app/gradio/pull/4453)
+- Add `allow_preview` parameter to `Gallery` to control whether a detailed preview is displayed on click by
+ [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4470](https://github.com/gradio-app/gradio/pull/4470)
+- Add `latex_delimiters` parameter to `Chatbot` to control the delimiters used for LaTeX and to disable LaTeX in the `Chatbot` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4516](https://github.com/gradio-app/gradio/pull/4516)
+- Can now issue `gr.Warning` and `gr.Info` modals. Simply put the code `gr.Warning("Your warning message")` or `gr.Info("Your info message")` as a standalone line in your function. By [@aliabid94](https://github.com/aliabid94) in [PR 4518](https://github.com/gradio-app/gradio/pull/4518).
+
+Example:
+
+```python
+def start_process(name):
+ gr.Info("Starting process")
+ if name is None:
+ gr.Warning("Name is empty")
+ ...
+ if success == False:
+ raise gr.Error("Process failed")
+```
+
+### Bug Fixes:
+
+- Add support for PAUSED state in the JS client by [@abidlabs](https://github.com/abidlabs) in [PR 4438](https://github.com/gradio-app/gradio/pull/4438)
+- Ensure Tabs only occupy the space required by [@pngwn](https://github.com/pngwn) in [PR 4419](https://github.com/gradio-app/gradio/pull/4419)
+- Ensure components have the correct empty sizes to prevent empty containers from collapsing by [@pngwn](https://github.com/pngwn) in [PR 4447](https://github.com/gradio-app/gradio/pull/4447).
+- Frontend code no longer crashes when there is a relative URL in an `` element, by [@akx](https://github.com/akx) in [PR 4449](https://github.com/gradio-app/gradio/pull/4449).
+- Fix bug where setting `format='mp4'` on a video component would cause the function to error out if the uploaded video was not playable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4467](https://github.com/gradio-app/gradio/pull/4467)
+- Fix `_js` parameter to work even without backend function, by [@aliabid94](https://github.com/aliabid94) in [PR 4486](https://github.com/gradio-app/gradio/pull/4486).
+- Fix new line issue with `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4491](https://github.com/gradio-app/gradio/pull/4491)
+- Fixes issue with Clear button not working for `Label` component by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)
+- Restores the ability to pass in a tuple (sample rate, audio array) to gr.Audio() by [@abidlabs](https://github.com/abidlabs) in [PR 4525](https://github.com/gradio-app/gradio/pull/4525)
+- Ensure code is correctly formatted and copy button is always present in Chatbot by [@pngwn](https://github.com/pngwn) in [PR 4527](https://github.com/gradio-app/gradio/pull/4527)
+- `show_label` will not automatically be set to `True` in `gr.BarPlot.update` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4531](https://github.com/gradio-app/gradio/pull/4531)
+- `gr.BarPlot` group text now respects darkmode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4531](https://github.com/gradio-app/gradio/pull/4531)
+- Fix dispatched errors from within components [@aliabid94](https://github.com/aliabid94) in [PR 4786](https://github.com/gradio-app/gradio/pull/4786)
+
+### Other Changes:
+
+- Change styling of status and toast error components by [@hannahblair](https://github.com/hannahblair) in [PR 4454](https://github.com/gradio-app/gradio/pull/4454).
+- Clean up unnecessary `new Promise()`s by [@akx](https://github.com/akx) in [PR 4442](https://github.com/gradio-app/gradio/pull/4442).
+- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
+- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
+- Add Catalan translation [@jordimas](https://github.com/jordimas) in [PR 4483](https://github.com/gradio-app/gradio/pull/4483).
+- The API endpoint that loads examples upon click has been given an explicit name ("/load_examples") by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).
+- Allows configuration of FastAPI app when calling `mount_gradio_app`, by [@charlesfrye](https://github.com/charlesfrye) in [PR4519](https://github.com/gradio-app/gradio/pull/4519).
+
+### Breaking Changes:
+
+- The behavior of the `Clear` button has been changed for `Slider`, `CheckboxGroup`, `Radio`, `Dropdown` components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456). The Clear button now sets the value of these components to be empty as opposed to the original default set by the developer. This is to make them in line with the rest of the Gradio components.
+- Python 3.7 end of life is June 27 2023. Gradio will no longer support python 3.7 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4484](https://github.com/gradio-app/gradio/pull/4484)
+- Removed `$` as a default LaTeX delimiter for the `Chatbot` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4516](https://github.com/gradio-app/gradio/pull/4516). The specific LaTeX delimeters can be set using the new `latex_delimiters` parameter in `Chatbot`.
+
+## 3.34.0
+
+### New Features:
+
+- The `gr.UploadButton` component now supports the `variant` and `interactive` parameters by [@abidlabs](https://github.com/abidlabs) in [PR 4436](https://github.com/gradio-app/gradio/pull/4436).
+
+### Bug Fixes:
+
+- Remove target="\_blank" override on anchor tags with internal targets by [@hannahblair](https://github.com/hannahblair) in [PR 4405](https://github.com/gradio-app/gradio/pull/4405)
+- Fixed bug where `gr.File(file_count='multiple')` could not be cached as output by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4421](https://github.com/gradio-app/gradio/pull/4421)
+- Restricts the domains that can be proxied via `/proxy` route by [@abidlabs](https://github.com/abidlabs) in [PR 4406](https://github.com/gradio-app/gradio/pull/4406).
+- Fixes issue where `gr.UploadButton` could not be used to upload the same file twice by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4437](https://github.com/gradio-app/gradio/pull/4437)
+- Fixes bug where `/proxy` route was being incorrectly constructed by the frontend by [@abidlabs](https://github.com/abidlabs) in [PR 4430](https://github.com/gradio-app/gradio/pull/4430).
+- Fix z-index of status component by [@hannahblair](https://github.com/hannahblair) in [PR 4429](https://github.com/gradio-app/gradio/pull/4429)
+- Fix video rendering in Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4433](https://github.com/gradio-app/gradio/pull/4433).
+- The output directory for files downloaded when calling Blocks as a function is now set to a temporary directory by default (instead of the working directory in some cases) by [@abidlabs](https://github.com/abidlabs) in [PR 4501](https://github.com/gradio-app/gradio/pull/4501)
+
+### Other Changes:
+
+- When running on Spaces, handler functions will be transformed by the [PySpaces](https://pypi.org/project/spaces/) library in order to make them work with specific hardware. It will have no effect on standalone Gradio apps or regular Gradio Spaces and can be globally deactivated as follows : `import spaces; spaces.disable_gradio_auto_wrap()` by [@cbensimon](https://github.com/cbensimon) in [PR 4389](https://github.com/gradio-app/gradio/pull/4389).
+- Deprecated `.style` parameter and moved arguments to constructor. Added support for `.update()` to all arguments initially in style. Added `scale` and `min_width` support to every Component. By [@aliabid94](https://github.com/aliabid94) in [PR 4374](https://github.com/gradio-app/gradio/pull/4374)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.33.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Allow `every` to work with generators by [@dkjshk](https://github.com/dkjshk) in [PR 4434](https://github.com/gradio-app/gradio/pull/4434)
+- Fix z-index of status component by [@hannahblair](https://github.com/hannahblair) in [PR 4429](https://github.com/gradio-app/gradio/pull/4429)
+- Allow gradio to work offline, by [@aliabid94](https://github.com/aliabid94) in [PR 4398](https://github.com/gradio-app/gradio/pull/4398).
+- Fixed `validate_url` to check for 403 errors and use a GET request in place of a HEAD by [@alvindaiyan](https://github.com/alvindaiyan) in [PR 4388](https://github.com/gradio-app/gradio/pull/4388).
+
+### Other Changes:
+
+- More explicit error message when share link binary is blocked by antivirus by [@abidlabs](https://github.com/abidlabs) in [PR 4380](https://github.com/gradio-app/gradio/pull/4380).
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.33.0
+
+### New Features:
+
+- Introduced `gradio deploy` to launch a Gradio app to Spaces directly from your terminal. By [@aliabid94](https://github.com/aliabid94) in [PR 4033](https://github.com/gradio-app/gradio/pull/4033).
+- Introduce `show_progress='corner'` argument to event listeners, which will not cover the output components with the progress animation, but instead show it in the corner of the components. By [@aliabid94](https://github.com/aliabid94) in [PR 4396](https://github.com/gradio-app/gradio/pull/4396).
+
+### Bug Fixes:
+
+- Fix bug where Label change event was triggering itself by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4371](https://github.com/gradio-app/gradio/pull/4371)
+- Make `Blocks.load` behave like other event listeners (allows chaining `then` off of it) [@anentropic](https://github.com/anentropic/) in [PR 4304](https://github.com/gradio-app/gradio/pull/4304)
+- Respect `interactive=True` in output components of a `gr.Interface` by [@abidlabs](https://github.com/abidlabs) in [PR 4356](https://github.com/gradio-app/gradio/pull/4356).
+- Remove unused frontend code by [@akx](https://github.com/akx) in [PR 4275](https://github.com/gradio-app/gradio/pull/4275)
+- Fixes favicon path on Windows by [@abidlabs](https://github.com/abidlabs) in [PR 4369](https://github.com/gradio-app/gradio/pull/4369).
+- Prevent path traversal in `/file` routes by [@abidlabs](https://github.com/abidlabs) in [PR 4370](https://github.com/gradio-app/gradio/pull/4370).
+- Do not send HF token to other domains via `/proxy` route by [@abidlabs](https://github.com/abidlabs) in [PR 4368](https://github.com/gradio-app/gradio/pull/4368).
+- Replace default `markedjs` sanitize function with DOMPurify sanitizer for `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4360](https://github.com/gradio-app/gradio/pull/4360)
+- Prevent the creation of duplicate copy buttons in the chatbot and ensure copy buttons work in non-secure contexts by [@binary-husky](https://github.com/binary-husky) in [PR 4350](https://github.com/gradio-app/gradio/pull/4350).
+
+### Other Changes:
+
+- Remove flicker of loading bar by adding opacity transition, by [@aliabid94](https://github.com/aliabid94) in [PR 4349](https://github.com/gradio-app/gradio/pull/4349).
+- Performance optimization in the frontend's Blocks code by [@akx](https://github.com/akx) in [PR 4334](https://github.com/gradio-app/gradio/pull/4334)
+- Upgrade the pnpm lock file format version from v6.0 to v6.1 by [@whitphx](https://github.com/whitphx) in [PR 4393](https://github.com/gradio-app/gradio/pull/4393)
+
+### Breaking Changes:
+
+- The `/file=` route no longer allows accessing dotfiles or files in "dot directories" by [@akx](https://github.com/akx) in [PR 4303](https://github.com/gradio-app/gradio/pull/4303)
+
+## 3.32.0
+
+### New Features:
+
+- `Interface.launch()` and `Blocks.launch()` now accept an `app_kwargs` argument to allow customizing the configuration of the underlying FastAPI app, by [@akx](https://github.com/akx) in [PR 4282](https://github.com/gradio-app/gradio/pull/4282)
+
+### Bug Fixes:
+
+- Fixed Gallery/AnnotatedImage components not respecting GRADIO_DEFAULT_DIR variable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed Gallery/AnnotatedImage components resaving identical images by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed Audio/Video/File components creating empty tempfiles on each run by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4256](https://github.com/gradio-app/gradio/pull/4256)
+- Fixed the behavior of the `run_on_click` parameter in `gr.Examples` by [@abidlabs](https://github.com/abidlabs) in [PR 4258](https://github.com/gradio-app/gradio/pull/4258).
+- Ensure error modal displays when the queue is enabled by [@pngwn](https://github.com/pngwn) in [PR 4273](https://github.com/gradio-app/gradio/pull/4273)
+- Ensure js client respcts the full root when making requests to the server by [@pngwn](https://github.com/pngwn) in [PR 4271](https://github.com/gradio-app/gradio/pull/4271)
+
+### Other Changes:
+
+- Refactor web component `initial_height` attribute by [@whitphx](https://github.com/whitphx) in [PR 4223](https://github.com/gradio-app/gradio/pull/4223)
+- Relocate `mount_css` fn to remove circular dependency [@whitphx](https://github.com/whitphx) in [PR 4222](https://github.com/gradio-app/gradio/pull/4222)
+- Upgrade Black to 23.3 by [@akx](https://github.com/akx) in [PR 4259](https://github.com/gradio-app/gradio/pull/4259)
+- Add frontend LaTeX support in `gr.Chatbot()` using `KaTeX` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4285](https://github.com/gradio-app/gradio/pull/4285).
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.31.0
+
+### New Features:
+
+- The reloader command (`gradio app.py`) can now accept command line arguments by [@micky2be](https://github.com/micky2be) in [PR 4119](https://github.com/gradio-app/gradio/pull/4119)
+- Added `format` argument to `Audio` component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4178](https://github.com/gradio-app/gradio/pull/4178)
+- Add JS client code snippets to use via api page by [@aliabd](https://github.com/aliabd) in [PR 3927](https://github.com/gradio-app/gradio/pull/3927).
+- Update to the JS client by [@pngwn](https://github.com/pngwn) in [PR 4202](https://github.com/gradio-app/gradio/pull/4202)
+
+### Bug Fixes:
+
+- Fix "TypeError: issubclass() arg 1 must be a class" When use Optional[Types] by [@lingfengchencn](https://github.com/lingfengchencn) in [PR 4200](https://github.com/gradio-app/gradio/pull/4200).
+- Gradio will no longer send any analytics or call home if analytics are disabled with the GRADIO_ANALYTICS_ENABLED environment variable. By [@akx](https://github.com/akx) in [PR 4194](https://github.com/gradio-app/gradio/pull/4194) and [PR 4236](https://github.com/gradio-app/gradio/pull/4236)
+- The deprecation warnings for kwargs now show the actual stack level for the invocation, by [@akx](https://github.com/akx) in [PR 4203](https://github.com/gradio-app/gradio/pull/4203).
+- Fix "TypeError: issubclass() arg 1 must be a class" When use Optional[Types] by [@lingfengchencn](https://github.com/lingfengchencn) in [PR 4200](https://github.com/gradio-app/gradio/pull/4200).
+- Ensure cancelling functions work correctly by [@pngwn](https://github.com/pngwn) in [PR 4225](https://github.com/gradio-app/gradio/pull/4225)
+- Fixes a bug with typing.get_type_hints() on Python 3.9 by [@abidlabs](https://github.com/abidlabs) in [PR 4228](https://github.com/gradio-app/gradio/pull/4228).
+- Fixes JSONDecodeError by [@davidai](https://github.com/davidai) in [PR 4241](https://github.com/gradio-app/gradio/pull/4241)
+- Fix `chatbot_dialogpt` demo by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4238](https://github.com/gradio-app/gradio/pull/4238).
+
+### Other Changes:
+
+- Change `gr.Chatbot()` markdown parsing to frontend using `marked` library and `prism` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4150](https://github.com/gradio-app/gradio/pull/4150)
+- Update the js client by [@pngwn](https://github.com/pngwn) in [PR 3899](https://github.com/gradio-app/gradio/pull/3899)
+- Fix documentation for the shape of the numpy array produced by the `Image` component by [@der3318](https://github.com/der3318) in [PR 4204](https://github.com/gradio-app/gradio/pull/4204).
+- Updates the timeout for websocket messaging from 1 second to 5 seconds by [@abidlabs](https://github.com/abidlabs) in [PR 4235](https://github.com/gradio-app/gradio/pull/4235)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.30.0
+
+### New Features:
+
+- Adds a `root_path` parameter to `launch()` that allows running Gradio applications on subpaths (e.g. www.example.com/app) behind a proxy, by [@abidlabs](https://github.com/abidlabs) in [PR 4133](https://github.com/gradio-app/gradio/pull/4133)
+- Fix dropdown change listener to trigger on change when updated as an output by [@aliabid94](https://github.com/aliabid94) in [PR 4128](https://github.com/gradio-app/gradio/pull/4128).
+- Add `.input` event listener, which is only triggered when a user changes the component value (as compared to `.change`, which is also triggered when a component updates as the result of a function trigger), by [@aliabid94](https://github.com/aliabid94) in [PR 4157](https://github.com/gradio-app/gradio/pull/4157).
+
+### Bug Fixes:
+
+- Records username when flagging by [@abidlabs](https://github.com/abidlabs) in [PR 4135](https://github.com/gradio-app/gradio/pull/4135)
+- Fix website build issue by [@aliabd](https://github.com/aliabd) in [PR 4142](https://github.com/gradio-app/gradio/pull/4142)
+- Fix lang agnostic type info for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
+
+### Other Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+## 3.29.0
+
+### New Features:
+
+- Returning language agnostic types in the `/info` route by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4039](https://github.com/gradio-app/gradio/pull/4039)
+
+### Bug Fixes:
+
+- Allow users to upload audio files in Audio component on iOS by by [@aliabid94](https://github.com/aliabid94) in [PR 4071](https://github.com/gradio-app/gradio/pull/4071).
+- Fixes the gradio theme builder error that appeared on launch by [@aliabid94](https://github.com/aliabid94) and [@abidlabs](https://github.com/abidlabs) in [PR 4080](https://github.com/gradio-app/gradio/pull/4080)
+- Keep Accordion content in DOM by [@aliabid94](https://github.com/aliabid94) in [PR 4070](https://github.com/gradio-app/gradio/pull/4073)
+- Fixed bug where type hints in functions caused the event handler to crash by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4068](https://github.com/gradio-app/gradio/pull/4068)
+- Fix dropdown default value not appearing by [@aliabid94](https://github.com/aliabid94) in [PR 4072](https://github.com/gradio-app/gradio/pull/4072).
+- Soft theme label color fix by [@aliabid94](https://github.com/aliabid94) in [PR 4070](https://github.com/gradio-app/gradio/pull/4070)
+- Fix `gr.Slider` `release` event not triggering on mobile by [@space-nuko](https://github.com/space-nuko) in [PR 4098](https://github.com/gradio-app/gradio/pull/4098)
+- Removes extraneous `State` component info from the `/info` route by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
+- Make .then() work even if first event fails by [@aliabid94](https://github.com/aliabid94) in [PR 4115](https://github.com/gradio-app/gradio/pull/4115).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Allow users to submit with enter in Interfaces with textbox / number inputs [@aliabid94](https://github.com/aliabid94) in [PR 4090](https://github.com/gradio-app/gradio/pull/4090).
+- Updates gradio's requirements.txt to requires uvicorn>=0.14.0 by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+- Updates some error messaging by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+- Renames simplified Chinese translation file from `zh-cn.json` to `zh-CN.json` by [@abidlabs](https://github.com/abidlabs) in [PR 4086](https://github.com/gradio-app/gradio/pull/4086)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.3
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes issue with indentation in `gr.Code()` component with streaming by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4043](https://github.com/gradio-app/gradio/pull/4043)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.2
+
+### Bug Fixes
+
+- Code component visual updates by [@pngwn](https://github.com/pngwn) in [PR 4051](https://github.com/gradio-app/gradio/pull/4051)
+
+### New Features:
+
+- Add support for `visual-question-answering`, `document-question-answering`, and `image-to-text` using `gr.Interface.load("models/...")` and `gr.Interface.from_pipeline` by [@osanseviero](https://github.com/osanseviero) in [PR 3887](https://github.com/gradio-app/gradio/pull/3887)
+- Add code block support in `gr.Chatbot()`, by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4048](https://github.com/gradio-app/gradio/pull/4048)
+- Adds the ability to blocklist filepaths (and also improves the allowlist mechanism) by [@abidlabs](https://github.com/abidlabs) in [PR 4047](https://github.com/gradio-app/gradio/pull/4047).
+- Adds the ability to specify the upload directory via an environment variable by [@abidlabs](https://github.com/abidlabs) in [PR 4047](https://github.com/gradio-app/gradio/pull/4047).
+
+### Bug Fixes:
+
+- Fixes issue with `matplotlib` not rendering correctly if the backend was not set to `Agg` by [@abidlabs](https://github.com/abidlabs) in [PR 4029](https://github.com/gradio-app/gradio/pull/4029)
+- Fixes bug where rendering the same `gr.State` across different Interfaces/Blocks within larger Blocks would not work by [@abidlabs](https://github.com/abidlabs) in [PR 4030](https://github.com/gradio-app/gradio/pull/4030)
+- Code component visual updates by [@pngwn](https://github.com/pngwn) in [PR 4051](https://github.com/gradio-app/gradio/pull/4051)
+
+### Documentation Changes:
+
+- Adds a Guide on how to use the Python Client within a FastAPI app, by [@abidlabs](https://github.com/abidlabs) in [PR 3892](https://github.com/gradio-app/gradio/pull/3892)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+- `gr.HuggingFaceDatasetSaver` behavior changed internally. The `flagging/` folder is not a `.git/` folder anymore when using it. `organization` parameter is now ignored in favor of passing a full dataset id as `dataset_name` (e.g. `"username/my-dataset"`).
+- New lines (`\n`) are not automatically converted to ` ` in `gr.Markdown()` or `gr.Chatbot()`. For multiple new lines, a developer must add multiple ` ` tags.
+
+### Full Changelog:
+
+- Safer version of `gr.HuggingFaceDatasetSaver` using HTTP methods instead of git pull/push by [@Wauplin](https://github.com/Wauplin) in [PR 3973](https://github.com/gradio-app/gradio/pull/3973)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.1
+
+### New Features:
+
+- Add a "clear mask" button to `gr.Image` sketch modes, by [@space-nuko](https://github.com/space-nuko) in [PR 3615](https://github.com/gradio-app/gradio/pull/3615)
+
+### Bug Fixes:
+
+- Fix dropdown default value not appearing by [@aliabid94](https://github.com/aliabid94) in [PR 3996](https://github.com/gradio-app/gradio/pull/3996).
+- Fix faded coloring of output textboxes in iOS / Safari by [@aliabid94](https://github.com/aliabid94) in [PR 3993](https://github.com/gradio-app/gradio/pull/3993)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+- CI: Simplified Python CI workflow by [@akx](https://github.com/akx) in [PR 3982](https://github.com/gradio-app/gradio/pull/3982)
+- Upgrade pyright to 1.1.305 by [@akx](https://github.com/akx) in [PR 4042](https://github.com/gradio-app/gradio/pull/4042)
+- More Ruff rules are enabled and lint errors fixed by [@akx](https://github.com/akx) in [PR 4038](https://github.com/gradio-app/gradio/pull/4038)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.28.0
+
+### Bug Fixes:
+
+- Fix duplicate play commands in full-screen mode of 'video'. by [@tomchang25](https://github.com/tomchang25) in [PR 3968](https://github.com/gradio-app/gradio/pull/3968).
+- Fix the issue of the UI stuck caused by the 'selected' of DataFrame not being reset. by [@tomchang25](https://github.com/tomchang25) in [PR 3916](https://github.com/gradio-app/gradio/pull/3916).
+- Fix issue where `gr.Video()` would not work inside a `gr.Tab()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3891](https://github.com/gradio-app/gradio/pull/3891)
+- Fixed issue with old_value check in File. by [@tomchang25](https://github.com/tomchang25) in [PR 3859](https://github.com/gradio-app/gradio/pull/3859).
+- Fixed bug where all bokeh plots appeared in the same div by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3896](https://github.com/gradio-app/gradio/pull/3896)
+- Fixed image outputs to automatically take full output image height, unless explicitly set, by [@aliabid94](https://github.com/aliabid94) in [PR 3905](https://github.com/gradio-app/gradio/pull/3905)
+- Fix issue in `gr.Gallery()` where setting height causes aspect ratio of images to collapse by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3830](https://github.com/gradio-app/gradio/pull/3830)
+- Fix issue where requesting for a non-existing file would trigger a 500 error by [@micky2be](https://github.com/micky2be) in `[PR 3895](https://github.com/gradio-app/gradio/pull/3895)`.
+- Fix bugs with abspath about symlinks, and unresolvable path on Windows by [@micky2be](https://github.com/micky2be) in `[PR 3895](https://github.com/gradio-app/gradio/pull/3895)`.
+- Fixes type in client `Status` enum by [@10zinten](https://github.com/10zinten) in [PR 3931](https://github.com/gradio-app/gradio/pull/3931)
+- Fix `gr.ChatBot` to handle image url [tye-singwa](https://github.com/tye-signwa) in [PR 3953](https://github.com/gradio-app/gradio/pull/3953)
+- Move Google Tag Manager related initialization code to analytics-enabled block by [@akx](https://github.com/akx) in [PR 3956](https://github.com/gradio-app/gradio/pull/3956)
+- Fix bug where port was not reused if the demo was closed and then re-launched by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3896](https://github.com/gradio-app/gradio/pull/3959)
+- Fixes issue where dropdown does not position itself at selected element when opened [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3639](https://github.com/gradio-app/gradio/pull/3639)
+
+### Documentation Changes:
+
+- Make use of `gr` consistent across the docs by [@duerrsimon](https://github.com/duerrsimon) in [PR 3901](https://github.com/gradio-app/gradio/pull/3901)
+- Fixed typo in theming-guide.md by [@eltociear](https://github.com/eltociear) in [PR 3952](https://github.com/gradio-app/gradio/pull/3952)
+
+### Testing and Infrastructure Changes:
+
+- CI: Python backend lint is only run once, by [@akx](https://github.com/akx) in [PR 3960](https://github.com/gradio-app/gradio/pull/3960)
+- Format invocations and concatenations were replaced by f-strings where possible by [@akx](https://github.com/akx) in [PR 3984](https://github.com/gradio-app/gradio/pull/3984)
+- Linting rules were made more strict and issues fixed by [@akx](https://github.com/akx) in [PR 3979](https://github.com/gradio-app/gradio/pull/3979).
+
+### Breaking Changes:
+
+- Some re-exports in `gradio.themes` utilities (introduced in 3.24.0) have been eradicated.
+ By [@akx](https://github.com/akx) in [PR 3958](https://github.com/gradio-app/gradio/pull/3958)
+
+### Full Changelog:
+
+- Add DESCRIPTION.md to image_segmentation demo by [@aliabd](https://github.com/aliabd) in [PR 3866](https://github.com/gradio-app/gradio/pull/3866)
+- Fix error in running `gr.themes.builder()` by [@deepkyu](https://github.com/deepkyu) in [PR 3869](https://github.com/gradio-app/gradio/pull/3869)
+- Fixed a JavaScript TypeError when loading custom JS with `_js` and setting `outputs` to `None` in `gradio.Blocks()` by [@DavG25](https://github.com/DavG25) in [PR 3883](https://github.com/gradio-app/gradio/pull/3883)
+- Fixed bg_background_fill theme property to expand to whole background, block_radius to affect form elements as well, and added block_label_shadow theme property by [@aliabid94](https://github.com/aliabid94) in [PR 3590](https://github.com/gradio-app/gradio/pull/3590)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.27.0
+
+### New Features:
+
+###### AnnotatedImage Component
+
+New AnnotatedImage component allows users to highlight regions of an image, either by providing bounding boxes, or 0-1 pixel masks. This component is useful for tasks such as image segmentation, object detection, and image captioning.
+
+![AnnotatedImage screenshot](https://user-images.githubusercontent.com/7870876/232142720-86e0020f-beaf-47b9-a843-689c9621f09c.gif)
+
+Example usage:
+
+```python
+with gr.Blocks() as demo:
+ img = gr.Image()
+ img_section = gr.AnnotatedImage()
+ def mask(img):
+ top_left_corner = [0, 0, 20, 20]
+ random_mask = np.random.randint(0, 2, img.shape[:2])
+ return (img, [(top_left_corner, "left corner"), (random_mask, "random")])
+ img.change(mask, img, img_section)
+```
+
+See the [image_segmentation demo](https://github.com/gradio-app/gradio/tree/main/demo/image_segmentation) for a full example. By [@aliabid94](https://github.com/aliabid94) in [PR 3836](https://github.com/gradio-app/gradio/pull/3836)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.26.0
+
+### New Features:
+
+###### `Video` component supports subtitles
+
+- Allow the video component to accept subtitles as input, by [@tomchang25](https://github.com/tomchang25) in [PR 3673](https://github.com/gradio-app/gradio/pull/3673). To provide subtitles, simply return a tuple consisting of `(path_to_video, path_to_subtitles)` from your function. Both `.srt` and `.vtt` formats are supported:
+
+```py
+with gr.Blocks() as demo:
+ gr.Video(("video.mp4", "captions.srt"))
+```
+
+### Bug Fixes:
+
+- Fix code markdown support in `gr.Chatbot()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3816](https://github.com/gradio-app/gradio/pull/3816)
+
+### Documentation Changes:
+
+- Updates the "view API" page in Gradio apps to use the `gradio_client` library by [@aliabd](https://github.com/aliabd) in [PR 3765](https://github.com/gradio-app/gradio/pull/3765)
+
+- Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.25.0
+
+### New Features:
+
+- Improve error messages when number of inputs/outputs to event handlers mismatch, by [@space-nuko](https://github.com/space-nuko) in [PR 3519](https://github.com/gradio-app/gradio/pull/3519)
+
+- Add `select` listener to Images, allowing users to click on any part of an image and get the coordinates of the click by [@aliabid94](https://github.com/aliabid94) in [PR 3786](https://github.com/gradio-app/gradio/pull/3786).
+
+```python
+with gr.Blocks() as demo:
+ img = gr.Image()
+ textbox = gr.Textbox()
+
+ def select_handler(img, evt: gr.SelectData):
+ selected_pixel = img[evt.index[1], evt.index[0]]
+ return f"Selected pixel: {selected_pixel}"
+
+ img.select(select_handler, img, textbox)
+```
+
+![Recording 2023-04-08 at 17 44 39](https://user-images.githubusercontent.com/7870876/230748572-90a2a8d5-116d-4769-bb53-5516555fbd0f.gif)
+
+### Bug Fixes:
+
+- Increase timeout for sending analytics data by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3647](https://github.com/gradio-app/gradio/pull/3647)
+- Fix bug where http token was not accessed over websocket connections by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3735](https://github.com/gradio-app/gradio/pull/3735)
+- Add ability to specify `rows`, `columns` and `object-fit` in `style()` for `gr.Gallery()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3586](https://github.com/gradio-app/gradio/pull/3586)
+- Fix bug where recording an audio file through the microphone resulted in a corrupted file name by [@abidlabs](https://github.com/abidlabs) in [PR 3770](https://github.com/gradio-app/gradio/pull/3770)
+- Added "ssl_verify" to blocks.launch method to allow for use of self-signed certs by [@garrettsutula](https://github.com/garrettsutula) in [PR 3873](https://github.com/gradio-app/gradio/pull/3873)
+- Fix bug where iterators where not being reset for processes that terminated early by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3777](https://github.com/gradio-app/gradio/pull/3777)
+- Fix bug where the upload button was not properly handling the `file_count='multiple'` case by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3782](https://github.com/gradio-app/gradio/pull/3782)
+- Fix bug where use Via API button was giving error by [@Devang-C](https://github.com/Devang-C) in [PR 3783](https://github.com/gradio-app/gradio/pull/3783)
+
+### Documentation Changes:
+
+- Fix invalid argument docstrings, by [@akx](https://github.com/akx) in [PR 3740](https://github.com/gradio-app/gradio/pull/3740)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed IPv6 listening to work with bracket [::1] notation, by [@dsully](https://github.com/dsully) in [PR 3695](https://github.com/gradio-app/gradio/pull/3695)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.24.1
+
+### New Features:
+
+- No changes to highlight.
+
+### Bug Fixes:
+
+- Fixes Chatbot issue where new lines were being created every time a message was sent back and forth by [@aliabid94](https://github.com/aliabid94) in [PR 3717](https://github.com/gradio-app/gradio/pull/3717).
+- Fixes data updating in DataFrame invoking a `select` event once the dataframe has been selected. By [@yiyuezhuo](https://github.com/yiyuezhuo) in [PR 3861](https://github.com/gradio-app/gradio/pull/3861)
+- Fixes false positive warning which is due to too strict type checking by [@yiyuezhuo](https://github.com/yiyuezhuo) in [PR 3837](https://github.com/gradio-app/gradio/pull/3837).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.24.0
+
+### New Features:
+
+- Trigger the release event when Slider number input is released or unfocused by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3589](https://github.com/gradio-app/gradio/pull/3589)
+- Created Theme Builder, which allows users to create themes without writing any code, by [@aliabid94](https://github.com/aliabid94) in [PR 3664](https://github.com/gradio-app/gradio/pull/3664). Launch by:
+
+ ```python
+ import gradio as gr
+ gr.themes.builder()
+ ```
+
+ ![Theme Builder](https://user-images.githubusercontent.com/7870876/228204929-d71cbba5-69c2-45b3-bd20-e3a201d98b12.png)
+
+- The `Dropdown` component now has a `allow_custom_value` parameter that lets users type in custom values not in the original list of choices.
+- The `Colorpicker` component now has a `.blur()` event
+
+###### Added a download button for videos! 📥
+
+![download_video](https://user-images.githubusercontent.com/41651716/227009612-9bc5fb72-2a44-4c55-9b7b-a0fa098e7f25.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3581](https://github.com/gradio-app/gradio/pull/3581).
+
+- Trigger the release event when Slider number input is released or unfocused by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3589](https://github.com/gradio-app/gradio/pull/3589)
+
+### Bug Fixes:
+
+- Fixed bug where text for altair plots was not legible in dark mode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3555](https://github.com/gradio-app/gradio/pull/3555)
+- Fixes `Chatbot` and `Image` components so that files passed during processing are added to a directory where they can be served from, by [@abidlabs](https://github.com/abidlabs) in [PR 3523](https://github.com/gradio-app/gradio/pull/3523)
+- Use Gradio API server to send telemetry using `huggingface_hub` [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3488](https://github.com/gradio-app/gradio/pull/3488)
+- Fixes an an issue where if the Blocks scope was not exited, then State could be shared across sessions, by [@abidlabs](https://github.com/abidlabs) in [PR 3600](https://github.com/gradio-app/gradio/pull/3600)
+- Ensures that `gr.load()` loads and applies the upstream theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641)
+- Fixed bug where "or" was not being localized in file upload text by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3599](https://github.com/gradio-app/gradio/pull/3599)
+- Fixed bug where chatbot does not autoscroll inside of a tab, row or column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637)
+- Fixed bug where textbox shrinks when `lines` set to larger than 20 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637)
+- Ensure CSS has fully loaded before rendering the application, by [@pngwn](https://github.com/pngwn) in [PR 3573](https://github.com/gradio-app/gradio/pull/3573)
+- Support using an empty list as `gr.Dataframe` value, by [@space-nuko](https://github.com/space-nuko) in [PR 3646](https://github.com/gradio-app/gradio/pull/3646)
+- Fixed `gr.Image` not filling the entire element size, by [@space-nuko](https://github.com/space-nuko) in [PR 3649](https://github.com/gradio-app/gradio/pull/3649)
+- Make `gr.Code` support the `lines` property, by [@space-nuko](https://github.com/space-nuko) in [PR 3651](https://github.com/gradio-app/gradio/pull/3651)
+- Fixes certain `_js` return values being double wrapped in an array, by [@space-nuko](https://github.com/space-nuko) in [PR 3594](https://github.com/gradio-app/gradio/pull/3594)
+- Correct the documentation of `gr.File` component to state that its preprocessing method converts the uploaded file to a temporary file, by @RussellLuo in [PR 3660](https://github.com/gradio-app/gradio/pull/3660)
+- Fixed bug in Serializer ValueError text by [@osanseviero](https://github.com/osanseviero) in [PR 3669](https://github.com/gradio-app/gradio/pull/3669)
+- Fix default parameter argument and `gr.Progress` used in same function, by [@space-nuko](https://github.com/space-nuko) in [PR 3671](https://github.com/gradio-app/gradio/pull/3671)
+- Hide `Remove All` button in `gr.Dropdown` single-select mode by [@space-nuko](https://github.com/space-nuko) in [PR 3678](https://github.com/gradio-app/gradio/pull/3678)
+- Fix broken spaces in docs by [@aliabd](https://github.com/aliabd) in [PR 3698](https://github.com/gradio-app/gradio/pull/3698)
+- Fix items in `gr.Dropdown` besides the selected item receiving a checkmark, by [@space-nuko](https://github.com/space-nuko) in [PR 3644](https://github.com/gradio-app/gradio/pull/3644)
+- Fix several `gr.Dropdown` issues and improve usability, by [@space-nuko](https://github.com/space-nuko) in [PR 3705](https://github.com/gradio-app/gradio/pull/3705)
+
+### Documentation Changes:
+
+- Makes some fixes to the Theme Guide related to naming of variables, by [@abidlabs](https://github.com/abidlabs) in [PR 3561](https://github.com/gradio-app/gradio/pull/3561)
+- Documented `HuggingFaceDatasetJSONSaver` by [@osanseviero](https://github.com/osanseviero) in [PR 3604](https://github.com/gradio-app/gradio/pull/3604)
+- Makes some additions to documentation of `Audio` and `State` components, and fixes the `pictionary` demo by [@abidlabs](https://github.com/abidlabs) in [PR 3611](https://github.com/gradio-app/gradio/pull/3611)
+- Fix outdated sharing your app guide by [@aliabd](https://github.com/aliabd) in [PR 3699](https://github.com/gradio-app/gradio/pull/3699)
+
+### Testing and Infrastructure Changes:
+
+- Removed heavily-mocked tests related to comet_ml, wandb, and mlflow as they added a significant amount of test dependencies that prevented installation of test dependencies on Windows environments. By [@abidlabs](https://github.com/abidlabs) in [PR 3608](https://github.com/gradio-app/gradio/pull/3608)
+- Added Windows continuous integration, by [@space-nuko](https://github.com/space-nuko) in [PR 3628](https://github.com/gradio-app/gradio/pull/3628)
+- Switched linting from flake8 + isort to `ruff`, by [@akx](https://github.com/akx) in [PR 3710](https://github.com/gradio-app/gradio/pull/3710)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Mobile responsive iframes in themes guide by [@aliabd](https://github.com/aliabd) in [PR 3562](https://github.com/gradio-app/gradio/pull/3562)
+- Remove extra $demo from theme guide by [@aliabd](https://github.com/aliabd) in [PR 3563](https://github.com/gradio-app/gradio/pull/3563)
+- Set the theme name to be the upstream repo name when loading from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3595](https://github.com/gradio-app/gradio/pull/3595)
+- Copy everything in website Dockerfile, fix build issues by [@aliabd](https://github.com/aliabd) in [PR 3659](https://github.com/gradio-app/gradio/pull/3659)
+- Raise error when an event is queued but the queue is not configured by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3640](https://github.com/gradio-app/gradio/pull/3640)
+- Allows users to apss in a string name for a built-in theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641)
+- Added `orig_name` to Video output in the backend so that the front end can set the right name for downloaded video files by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3700](https://github.com/gradio-app/gradio/pull/3700)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.23.0
+
+### New Features:
+
+###### Theme Sharing!
+
+Once you have created a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it! You can also download, reuse, and remix other peoples' themes. See https://gradio.app/theming-guide/ for more details.
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3428](https://github.com/gradio-app/gradio/pull/3428)
+
+### Bug Fixes:
+
+- Removes leading spaces from all lines of code uniformly in the `gr.Code()` component. By [@abidlabs](https://github.com/abidlabs) in [PR 3556](https://github.com/gradio-app/gradio/pull/3556)
+- Fixed broken login page, by [@aliabid94](https://github.com/aliabid94) in [PR 3529](https://github.com/gradio-app/gradio/pull/3529)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fix rendering of dropdowns to take more space, and related bugs, by [@aliabid94](https://github.com/aliabid94) in [PR 3549](https://github.com/gradio-app/gradio/pull/3549)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.22.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Restore label bars by [@aliabid94](https://github.com/aliabid94) in [PR 3507](https://github.com/gradio-app/gradio/pull/3507)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.22.0
+
+### New Features:
+
+###### Official Theme release
+
+Gradio now supports a new theme system, which allows you to customize the look and feel of your app. You can now use the `theme=` kwarg to pass in a prebuilt theme, or customize your own! See https://gradio.app/theming-guide/ for more details. By [@aliabid94](https://github.com/aliabid94) in [PR 3470](https://github.com/gradio-app/gradio/pull/3470) and [PR 3497](https://github.com/gradio-app/gradio/pull/3497)
+
+###### `elem_classes`
+
+Add keyword argument `elem_classes` to Components to control class names of components, in the same manner as existing `elem_id`.
+By [@aliabid94](https://github.com/aliabid94) in [PR 3466](https://github.com/gradio-app/gradio/pull/3466)
+
+### Bug Fixes:
+
+- Fixes the File.upload() event trigger which broke as part of the change in how we uploaded files by [@abidlabs](https://github.com/abidlabs) in [PR 3462](https://github.com/gradio-app/gradio/pull/3462)
+- Fixed issue with `gr.Request` object failing to handle dictionaries when nested keys couldn't be converted to variable names [#3454](https://github.com/gradio-app/gradio/issues/3454) by [@radames](https://github.com/radames) in [PR 3459](https://github.com/gradio-app/gradio/pull/3459)
+- Fixed bug where css and client api was not working properly when mounted in a subpath by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3482](https://github.com/gradio-app/gradio/pull/3482)
+
+### Documentation Changes:
+
+- Document gr.Error in the docs by [@aliabd](https://github.com/aliabd) in [PR 3465](https://github.com/gradio-app/gradio/pull/3465)
+
+### Testing and Infrastructure Changes:
+
+- Pinned `pyright==1.1.298` for stability by [@abidlabs](https://github.com/abidlabs) in [PR 3475](https://github.com/gradio-app/gradio/pull/3475)
+- Removed `IOComponent.add_interactive_to_config()` by [@space-nuko](https://github.com/space-nuko) in [PR 3476](https://github.com/gradio-app/gradio/pull/3476)
+- Removed `IOComponent.generate_sample()` by [@space-nuko](https://github.com/space-nuko) in [PR 3475](https://github.com/gradio-app/gradio/pull/3483)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Revert primary button background color in dark mode by [@aliabid94](https://github.com/aliabid94) in [PR 3468](https://github.com/gradio-app/gradio/pull/3468)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.21.0
+
+### New Features:
+
+###### Theme Sharing 🎨 🤝
+
+You can now share your gradio themes with the world!
+
+After creating a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it!
+
+###### Uploading
+
+There are two ways to upload a theme, via the theme class instance or the command line.
+
+1. Via the class instance
+
+```python
+my_theme.push_to_hub(repo_name="my_theme",
+ version="0.2.0",
+ hf_token="...")
+```
+
+2. Via the command line
+
+First save the theme to disk
+
+```python
+my_theme.dump(filename="my_theme.json")
+```
+
+Then use the `upload_theme` command:
+
+```bash
+upload_theme\
+"my_theme.json"\
+"my_theme"\
+"0.2.0"\
+""
+```
+
+The `version` must be a valid [semantic version](https://www.geeksforgeeks.org/introduction-semantic-versioning/) string.
+
+This creates a space on the huggingface hub to host the theme files and show potential users a preview of your theme.
+
+An example theme space is here: https://huggingface.co/spaces/freddyaboulton/dracula_revamped
+
+###### Downloading
+
+To use a theme from the hub, use the `from_hub` method on the `ThemeClass` and pass it to your app:
+
+```python
+my_theme = gr.Theme.from_hub("freddyaboulton/my_theme")
+
+with gr.Blocks(theme=my_theme) as demo:
+ ....
+```
+
+You can also pass the theme string directly to `Blocks` or `Interface` (`gr.Blocks(theme="freddyaboulton/my_theme")`)
+
+You can pin your app to an upstream theme version by using semantic versioning expressions.
+
+For example, the following would ensure the theme we load from the `my_theme` repo was between versions `0.1.0` and `0.2.0`:
+
+```python
+with gr.Blocks(theme="freddyaboulton/my_theme@>=0.1.0,<0.2.0") as demo:
+ ....
+```
+
+by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3428](https://github.com/gradio-app/gradio/pull/3428)
+
+###### Code component 🦾
+
+New code component allows you to enter, edit and display code with full syntax highlighting by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+
+###### The `Chatbot` component now supports audio, video, and images
+
+The `Chatbot` component now supports audio, video, and images with a simple syntax: simply
+pass in a tuple with the URL or filepath (the second optional element of the tuple is alt text), and the image/audio/video will be displayed:
+
+```python
+gr.Chatbot([
+ (("driving.mp4",), "cool video"),
+ (("cantina.wav",), "cool audio"),
+ (("lion.jpg", "A lion"), "cool pic"),
+]).style(height=800)
+```
+
+
+
+Note: images were previously supported via Markdown syntax and that is still supported for backwards compatibility. By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3413](https://github.com/gradio-app/gradio/pull/3413)
+
+- Allow consecutive function triggers with `.then` and `.success` by [@aliabid94](https://github.com/aliabid94) in [PR 3430](https://github.com/gradio-app/gradio/pull/3430)
+
+- New code component allows you to enter, edit and display code with full syntax highlighting by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+
+![](https://user-images.githubusercontent.com/12937446/224116643-5cfb94b3-93ce-43ee-bb7b-c25c3b66e0a1.png)
+
+- Added the `.select()` event listener, which also includes event data that can be passed as an argument to a function with type hint `gr.SelectData`. The following components support the `.select()` event listener: Chatbot, CheckboxGroup, Dataframe, Dropdown, File, Gallery, HighlightedText, Label, Radio, TabItem, Tab, Textbox. Example usage:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gallery = gr.Gallery(["images/1.jpg", "images/2.jpg", "images/3.jpg"])
+ selected_index = gr.Textbox()
+
+ def on_select(evt: gr.SelectData):
+ return evt.index
+
+ gallery.select(on_select, None, selected_index)
+```
+
+By [@aliabid94](https://github.com/aliabid94) in [PR 3399](https://github.com/gradio-app/gradio/pull/3399)
+
+- The `Textbox` component now includes a copy button by [@abidlabs](https://github.com/abidlabs) in [PR 3452](https://github.com/gradio-app/gradio/pull/3452)
+
+### Bug Fixes:
+
+- Use `huggingface_hub` to send telemetry on `interface` and `blocks`; eventually to replace segment by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3342](https://github.com/gradio-app/gradio/pull/3342)
+- Ensure load events created by components (randomize for slider, callable values) are never queued unless every is passed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3391](https://github.com/gradio-app/gradio/pull/3391)
+- Prevent in-place updates of `generic_update` by shallow copying by [@gitgithan](https://github.com/gitgithan) in [PR 3405](https://github.com/gradio-app/gradio/pull/3405) to fix [#3282](https://github.com/gradio-app/gradio/issues/3282)
+- Fix bug caused by not importing `BlockContext` in `utils.py` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3424](https://github.com/gradio-app/gradio/pull/3424)
+- Ensure dropdown does not highlight partial matches by [@pngwn](https://github.com/pngwn) in [PR 3421](https://github.com/gradio-app/gradio/pull/3421)
+- Fix mic button display by [@aliabid94](https://github.com/aliabid94) in [PR 3456](https://github.com/gradio-app/gradio/pull/3456)
+
+### Documentation Changes:
+
+- Added a section on security and access when sharing Gradio apps by [@abidlabs](https://github.com/abidlabs) in [PR 3408](https://github.com/gradio-app/gradio/pull/3408)
+- Add Chinese README by [@uanu2002](https://github.com/uanu2002) in [PR 3394](https://github.com/gradio-app/gradio/pull/3394)
+- Adds documentation for web components by [@abidlabs](https://github.com/abidlabs) in [PR 3407](https://github.com/gradio-app/gradio/pull/3407)
+- Fixed link in Chinese readme by [@eltociear](https://github.com/eltociear) in [PR 3417](https://github.com/gradio-app/gradio/pull/3417)
+- Document Blocks methods by [@aliabd](https://github.com/aliabd) in [PR 3427](https://github.com/gradio-app/gradio/pull/3427)
+- Fixed bug where event handlers were not showing up in documentation by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3434](https://github.com/gradio-app/gradio/pull/3434)
+
+### Testing and Infrastructure Changes:
+
+- Fixes tests that were failing locally but passing on CI by [@abidlabs](https://github.com/abidlabs) in [PR 3411](https://github.com/gradio-app/gradio/pull/3411)
+- Remove codecov from the repo by [@aliabd](https://github.com/aliabd) in [PR 3415](https://github.com/gradio-app/gradio/pull/3415)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Prevent in-place updates of `generic_update` by shallow copying by [@gitgithan](https://github.com/gitgithan) in [PR 3405](https://github.com/gradio-app/gradio/pull/3405) to fix [#3282](https://github.com/gradio-app/gradio/issues/3282)
+- Persist file names of files uploaded through any Gradio component by [@abidlabs](https://github.com/abidlabs) in [PR 3412](https://github.com/gradio-app/gradio/pull/3412)
+- Fix markdown embedded component in docs by [@aliabd](https://github.com/aliabd) in [PR 3410](https://github.com/gradio-app/gradio/pull/3410)
+- Clean up event listeners code by [@aliabid94](https://github.com/aliabid94) in [PR 3420](https://github.com/gradio-app/gradio/pull/3420)
+- Fix css issue with spaces logo by [@aliabd](https://github.com/aliabd) in [PR 3422](https://github.com/gradio-app/gradio/pull/3422)
+- Makes a few fixes to the `JSON` component (show_label parameter, icons) in [@abidlabs](https://github.com/abidlabs) in [PR 3451](https://github.com/gradio-app/gradio/pull/3451)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.20.1
+
+### New Features:
+
+- Add `height` kwarg to style in `gr.Chatbot()` component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3369](https://github.com/gradio-app/gradio/pull/3369)
+
+```python
+chatbot = gr.Chatbot().style(height=500)
+```
+
+### Bug Fixes:
+
+- Ensure uploaded images are always shown in the sketch tool by [@pngwn](https://github.com/pngwn) in [PR 3386](https://github.com/gradio-app/gradio/pull/3386)
+- Fixes bug where when if fn is a non-static class member, then self should be ignored as the first param of the fn by [@or25](https://github.com/or25) in [PR #3227](https://github.com/gradio-app/gradio/pull/3227)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.20.0
+
+### New Features:
+
+###### Release event for Slider
+
+Now you can trigger your python function to run when the slider is released as opposed to every slider change value!
+
+Simply use the `release` method on the slider
+
+```python
+slider.release(function, inputs=[...], outputs=[...], api_name="predict")
+```
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3353](https://github.com/gradio-app/gradio/pull/3353)
+
+###### Dropdown Component Updates
+
+The standard dropdown component now supports searching for choices. Also when `multiselect` is `True`, you can specify `max_choices` to set the maximum number of choices you want the user to be able to select from the dropdown component.
+
+```python
+gr.Dropdown(label="Choose your favorite colors", choices=["red", "blue", "green", "yellow", "orange"], multiselect=True, max_choices=2)
+```
+
+by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3211](https://github.com/gradio-app/gradio/pull/3211)
+
+###### Download button for images 🖼️
+
+Output images will now automatically have a download button displayed to make it easier to save and share
+the results of Machine Learning art models.
+
+![download_sketch](https://user-images.githubusercontent.com/41651716/221025113-e693bf41-eabd-42b3-a4f2-26f2708d98fe.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3297](https://github.com/gradio-app/gradio/pull/3297)
+
+- Updated image upload component to accept all image formats, including lossless formats like .webp by [@fienestar](https://github.com/fienestar) in [PR 3225](https://github.com/gradio-app/gradio/pull/3225)
+- Adds a disabled mode to the `gr.Button` component by setting `interactive=False` by [@abidlabs](https://github.com/abidlabs) in [PR 3266](https://github.com/gradio-app/gradio/pull/3266) and [PR 3288](https://github.com/gradio-app/gradio/pull/3288)
+- Adds visual feedback to the when the Flag button is clicked, by [@abidlabs](https://github.com/abidlabs) in [PR 3289](https://github.com/gradio-app/gradio/pull/3289)
+- Adds ability to set `flagging_options` display text and saved flag separately by [@abidlabs](https://github.com/abidlabs) in [PR 3289](https://github.com/gradio-app/gradio/pull/3289)
+- Allow the setting of `brush_radius` for the `Image` component both as a default and via `Image.update()` by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Added `info=` argument to form components to enable extra context provided to users, by [@aliabid94](https://github.com/aliabid94) in [PR 3291](https://github.com/gradio-app/gradio/pull/3291)
+- Allow developers to access the username of a logged-in user from the `gr.Request()` object using the `.username` attribute by [@abidlabs](https://github.com/abidlabs) in [PR 3296](https://github.com/gradio-app/gradio/pull/3296)
+- Add `preview` option to `Gallery.style` that launches the gallery in preview mode when first loaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3345](https://github.com/gradio-app/gradio/pull/3345)
+
+### Bug Fixes:
+
+- Ensure `mirror_webcam` is always respected by [@pngwn](https://github.com/pngwn) in [PR 3245](https://github.com/gradio-app/gradio/pull/3245)
+- Fix issue where updated markdown links were not being opened in a new tab by [@gante](https://github.com/gante) in [PR 3236](https://github.com/gradio-app/gradio/pull/3236)
+- API Docs Fixes by [@aliabd](https://github.com/aliabd) in [PR 3287](https://github.com/gradio-app/gradio/pull/3287)
+- Added a timeout to queue messages as some demos were experiencing infinitely growing queues from active jobs waiting forever for clients to respond by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3196](https://github.com/gradio-app/gradio/pull/3196)
+- Fixes the height of rendered LaTeX images so that they match the height of surrounding text by [@abidlabs](https://github.com/abidlabs) in [PR 3258](https://github.com/gradio-app/gradio/pull/3258) and in [PR 3276](https://github.com/gradio-app/gradio/pull/3276)
+- Fix bug where matplotlib images where always too small on the front end by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3274](https://github.com/gradio-app/gradio/pull/3274)
+- Remove embed's `initial_height` when loading is complete so the embed finds its natural height once it is loaded [@pngwn](https://github.com/pngwn) in [PR 3292](https://github.com/gradio-app/gradio/pull/3292)
+- Prevent Sketch from crashing when a default image is provided by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Respect the `shape` argument on the front end when creating Image Sketches by [@pngwn](https://github.com/pngwn) in [PR 3277](https://github.com/gradio-app/gradio/pull/3277)
+- Fix infinite loop caused by setting `Dropdown's` value to be `[]` and adding a change event on the dropdown by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3295](https://github.com/gradio-app/gradio/pull/3295)
+- Fix change event listed twice in image docs by [@aliabd](https://github.com/aliabd) in [PR 3318](https://github.com/gradio-app/gradio/pull/3318)
+- Fix bug that cause UI to be vertically centered at all times by [@pngwn](https://github.com/pngwn) in [PR 3336](https://github.com/gradio-app/gradio/pull/3336)
+- Fix bug where `height` set in `Gallery.style` was not respected by the front-end by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3343](https://github.com/gradio-app/gradio/pull/3343)
+- Ensure markdown lists are rendered correctly by [@pngwn](https://github.com/pngwn) in [PR 3341](https://github.com/gradio-app/gradio/pull/3341)
+- Ensure that the initial empty value for `gr.Dropdown(Multiselect=True)` is an empty list and the initial value for `gr.Dropdown(Multiselect=False)` is an empty string by [@pngwn](https://github.com/pngwn) in [PR 3338](https://github.com/gradio-app/gradio/pull/3338)
+- Ensure uploaded images respect the shape property when the canvas is also enabled by [@pngwn](https://github.com/pngwn) in [PR 3351](https://github.com/gradio-app/gradio/pull/3351)
+- Ensure that Google Analytics works correctly when gradio apps are created with `analytics_enabled=True` by [@abidlabs](https://github.com/abidlabs) in [PR 3349](https://github.com/gradio-app/gradio/pull/3349)
+- Fix bug where files were being re-uploaded after updates by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3375](https://github.com/gradio-app/gradio/pull/3375)
+- Fix error when using backen_fn and custom js at the same time by [@jialeicui](https://github.com/jialeicui) in [PR 3358](https://github.com/gradio-app/gradio/pull/3358)
+- Support new embeds for huggingface spaces subdomains by [@pngwn](https://github.com/pngwn) in [PR 3367](https://github.com/gradio-app/gradio/pull/3367)
+
+### Documentation Changes:
+
+- Added the `types` field to the dependency field in the config by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3315](https://github.com/gradio-app/gradio/pull/3315)
+- Gradio Status Page by [@aliabd](https://github.com/aliabd) in [PR 3331](https://github.com/gradio-app/gradio/pull/3331)
+- Adds a Guide on setting up a dashboard from Supabase data using the `gr.BarPlot`
+ component by [@abidlabs](https://github.com/abidlabs) in [PR 3275](https://github.com/gradio-app/gradio/pull/3275)
+
+### Testing and Infrastructure Changes:
+
+- Adds a script to benchmark the performance of the queue and adds some instructions on how to use it. By [@freddyaboulton](https://github.com/freddyaboulton) and [@abidlabs](https://github.com/abidlabs) in [PR 3272](https://github.com/gradio-app/gradio/pull/3272)
+- Flaky python tests no longer cancel non-flaky tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3344](https://github.com/gradio-app/gradio/pull/3344)
+
+### Breaking Changes:
+
+- Chatbot bubble colors can no longer be set by `chatbot.style(color_map=)` by [@aliabid94] in [PR 3370](https://github.com/gradio-app/gradio/pull/3370)
+
+### Full Changelog:
+
+- Fixed comment typo in components.py by [@eltociear](https://github.com/eltociear) in [PR 3235](https://github.com/gradio-app/gradio/pull/3235)
+- Cleaned up chatbot ui look and feel by [@aliabid94] in [PR 3370](https://github.com/gradio-app/gradio/pull/3370)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.19.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- UI fixes including footer and API docs by [@aliabid94](https://github.com/aliabid94) in [PR 3242](https://github.com/gradio-app/gradio/pull/3242)
+- Updated image upload component to accept all image formats, including lossless formats like .webp by [@fienestar](https://github.com/fienestar) in [PR 3225](https://github.com/gradio-app/gradio/pull/3225)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Added backend support for themes by [@aliabid94](https://github.com/aliabid94) in [PR 2931](https://github.com/gradio-app/gradio/pull/2931)
+- Added support for button sizes "lg" (default) and "sm".
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.19.0
+
+### New Features:
+
+###### Improved embedding experience
+
+When embedding a spaces-hosted gradio app as a web component, you now get an improved UI linking back to the original space, better error handling and more intelligent load performance. No changes are required to your code to benefit from this enhanced experience; simply upgrade your gradio SDK to the latest version.
+
+![](https://user-images.githubusercontent.com/12937446/219653294-86937632-72c1-4e93-a77c-af705d49382a.png)
+
+This behaviour is configurable. You can disable the info panel at the bottom by passing `info="false"`. You can disable the container entirely by passing `container="false"`.
+
+Error statuses are reported in the UI with an easy way for end-users to report problems to the original space author via the community tab of that Hugginface space:
+
+![](https://user-images.githubusercontent.com/12937446/219655499-88019443-d694-44e7-9e6d-242e19d10a5c.png)
+
+By default, gradio apps are lazy loaded, vastly improving performance when there are several demos on the page. Metadata is loaded ahead of time, but the space will only be loaded and rendered when it is in view.
+
+This behaviour is configurable. You can pass `eager="true"` to load and render the space regardless of whether or not it is currently on the screen.
+
+by [@pngwn](https://github.com/pngwn) in [PR 3205](https://github.com/gradio-app/gradio/pull/3205)
+
+###### New `gr.BarPlot` component! 📊
+
+Create interactive bar plots from a high-level interface with `gr.BarPlot`.
+No need to remember matplotlib syntax anymore!
+
+Example usage:
+
+```python
+import gradio as gr
+import pandas as pd
+
+simple = pd.DataFrame({
+ 'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
+ 'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
+})
+
+with gr.Blocks() as demo:
+ gr.BarPlot(
+ simple,
+ x="a",
+ y="b",
+ title="Simple Bar Plot with made up data",
+ tooltip=['a', 'b'],
+ )
+
+demo.launch()
+```
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3157](https://github.com/gradio-app/gradio/pull/3157)
+
+###### Bokeh plots are back! 🌠
+
+Fixed a bug that prevented bokeh plots from being displayed on the front end and extended support for both 2.x and 3.x versions of bokeh!
+
+![image](https://user-images.githubusercontent.com/41651716/219468324-0d82e07f-8fb4-4ff9-b40c-8250b29e45f7.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3212](https://github.com/gradio-app/gradio/pull/3212)
+
+### Bug Fixes:
+
+- Adds ability to add a single message from the bot or user side. Ex: specify `None` as the second value in the tuple, to add a single message in the chatbot from the "bot" side.
+
+```python
+gr.Chatbot([("Hi, I'm DialoGPT. Try asking me a question.", None)])
+```
+
+By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3165](https://github.com/gradio-app/gradio/pull/3165)
+
+- Fixes `gr.utils.delete_none` to only remove props whose values are `None` from the config by [@abidlabs](https://github.com/abidlabs) in [PR 3188](https://github.com/gradio-app/gradio/pull/3188)
+- Fix bug where embedded demos were not loading files properly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3177](https://github.com/gradio-app/gradio/pull/3177)
+- The `change` event is now triggered when users click the 'Clear All' button of the multiselect DropDown component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3195](https://github.com/gradio-app/gradio/pull/3195)
+- Stops File component from freezing when a large file is uploaded by [@aliabid94](https://github.com/aliabid94) in [PR 3191](https://github.com/gradio-app/gradio/pull/3191)
+- Support Chinese pinyin in Dataframe by [@aliabid94](https://github.com/aliabid94) in [PR 3206](https://github.com/gradio-app/gradio/pull/3206)
+- The `clear` event is now triggered when images are cleared by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3218](https://github.com/gradio-app/gradio/pull/3218)
+- Fix bug where auth cookies where not sent when connecting to an app via http by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3223](https://github.com/gradio-app/gradio/pull/3223)
+- Ensure latext CSS is always applied in light and dark mode by [@pngwn](https://github.com/pngwn) in [PR 3233](https://github.com/gradio-app/gradio/pull/3233)
+
+### Documentation Changes:
+
+- Sort components in docs by alphabetic order by [@aliabd](https://github.com/aliabd) in [PR 3152](https://github.com/gradio-app/gradio/pull/3152)
+- Changes to W&B guide by [@scottire](https://github.com/scottire) in [PR 3153](https://github.com/gradio-app/gradio/pull/3153)
+- Keep pnginfo metadata for gallery by [@wfng92](https://github.com/wfng92) in [PR 3150](https://github.com/gradio-app/gradio/pull/3150)
+- Add a section on how to run a Gradio app locally [@osanseviero](https://github.com/osanseviero) in [PR 3170](https://github.com/gradio-app/gradio/pull/3170)
+- Fixed typos in gradio events function documentation by [@vidalmaxime](https://github.com/vidalmaxime) in [PR 3168](https://github.com/gradio-app/gradio/pull/3168)
+- Added an example using Gradio's batch mode with the diffusers library by [@abidlabs](https://github.com/abidlabs) in [PR 3224](https://github.com/gradio-app/gradio/pull/3224)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fix demos page css and add close demos button by [@aliabd](https://github.com/aliabd) in [PR 3151](https://github.com/gradio-app/gradio/pull/3151)
+- Caches temp files from base64 input data by giving them a deterministic path based on the contents of data by [@abidlabs](https://github.com/abidlabs) in [PR 3197](https://github.com/gradio-app/gradio/pull/3197)
+- Better warnings (when there is a mismatch between the number of output components and values returned by a function, or when the `File` component or `UploadButton` component includes a `file_types` parameter along with `file_count=="dir"`) by [@abidlabs](https://github.com/abidlabs) in [PR 3194](https://github.com/gradio-app/gradio/pull/3194)
+- Raises a `gr.Error` instead of a regular Python error when you use `gr.Interface.load()` to load a model and there's an error querying the HF API by [@abidlabs](https://github.com/abidlabs) in [PR 3194](https://github.com/gradio-app/gradio/pull/3194)
+- Fixed gradio share links so that they are persistent and do not reset if network
+ connection is disrupted by by [XciD](https://github.com/XciD), [Wauplin](https://github.com/Wauplin), and [@abidlabs](https://github.com/abidlabs) in [PR 3149](https://github.com/gradio-app/gradio/pull/3149) and a follow-up to allow it to work for users upgrading from a previous Gradio version in [PR 3221](https://github.com/gradio-app/gradio/pull/3221)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.18.0
+
+### New Features:
+
+###### Revamped Stop Button for Interfaces 🛑
+
+If your Interface function is a generator, there used to be a separate `Stop` button displayed next
+to the `Submit` button.
+
+We've revamed the `Submit` button so that it turns into a `Stop` button during the generation process.
+Clicking on the `Stop` button will cancel the generation and turn it back to a `Submit` button.
+The `Stop` button will automatically turn back to a `Submit` button at the end of the generation if you don't use it!
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3124](https://github.com/gradio-app/gradio/pull/3124)
+
+###### Queue now works with reload mode!
+
+You can now call `queue` on your `demo` outside of the `if __name__ == "__main__"` block and
+run the script in reload mode with the `gradio` command.
+
+Any changes to the `app.py` file will be reflected in the webpage automatically and the queue will work
+properly!
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+
+###### Allow serving files from additional directories
+
+```python
+demo = gr.Interface(...)
+demo.launch(
+ file_directories=["/var/lib/demo/path/to/resources"]
+)
+```
+
+By [@maxaudron](https://github.com/maxaudron) in [PR 3075](https://github.com/gradio-app/gradio/pull/3075)
+
+### Bug Fixes:
+
+- Fixes URL resolution on Windows by [@abidlabs](https://github.com/abidlabs) in [PR 3108](https://github.com/gradio-app/gradio/pull/3108)
+- Example caching now works with components without a label attribute (e.g. `Column`) by [@abidlabs](https://github.com/abidlabs) in [PR 3123](https://github.com/gradio-app/gradio/pull/3123)
+- Ensure the Video component correctly resets the UI state when a new video source is loaded and reduce choppiness of UI by [@pngwn](https://github.com/abidlabs) in [PR 3117](https://github.com/gradio-app/gradio/pull/3117)
+- Fixes loading private Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 3068](https://github.com/gradio-app/gradio/pull/3068)
+- Added a warning when attempting to launch an `Interface` via the `%%blocks` jupyter notebook magic command by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3126](https://github.com/gradio-app/gradio/pull/3126)
+- Fixes bug where interactive output image cannot be set when in edit mode by [@dawoodkhan82](https://github.com/@dawoodkhan82) in [PR 3135](https://github.com/gradio-app/gradio/pull/3135)
+- A share link will automatically be created when running on Sagemaker notebooks so that the front-end is properly displayed by [@abidlabs](https://github.com/abidlabs) in [PR 3137](https://github.com/gradio-app/gradio/pull/3137)
+- Fixes a few dropdown component issues; hide checkmark next to options as expected, and keyboard hover is visible by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3145]https://github.com/gradio-app/gradio/pull/3145)
+- Fixed bug where example pagination buttons were not visible in dark mode or displayed under the examples table. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3144](https://github.com/gradio-app/gradio/pull/3144)
+- Fixed bug where the font color of axis labels and titles for native plots did not respond to dark mode preferences. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3146](https://github.com/gradio-app/gradio/pull/3146)
+
+### Documentation Changes:
+
+- Added a guide on the 4 kinds of Gradio Interfaces by [@yvrjsharma](https://github.com/yvrjsharma) and [@abidlabs](https://github.com/abidlabs) in [PR 3003](https://github.com/gradio-app/gradio/pull/3003)
+- Explained that the parameters in `launch` will not be respected when using reload mode, e.g. `gradio` command by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+- Added a demo to show how to set up variable numbers of outputs in Gradio by [@abidlabs](https://github.com/abidlabs) in [PR 3127](https://github.com/gradio-app/gradio/pull/3127)
+- Updated docs to reflect that the `equal_height` parameter should be passed to the `.style()` method of `gr.Row()` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3125](https://github.com/gradio-app/gradio/pull/3125)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Changed URL of final image for `fake_diffusion` demos by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3120](https://github.com/gradio-app/gradio/pull/3120)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.17.1
+
+### New Features:
+
+###### iOS image rotation fixed 🔄
+
+Previously photos uploaded via iOS would be rotated after processing. This has been fixed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3091)
+
+######### Before
+
+![image](https://user-images.githubusercontent.com/41651716/215846507-a36e9d05-1ac2-4867-8ab3-ce045a9415d9.png)
+
+######### After
+
+![image](https://user-images.githubusercontent.com/41651716/215846554-e41773ed-70f0-491a-9952-6a18babf91ef.png)
+
+###### Run on Kaggle kernels 🧪
+
+A share link will automatically be created when running on Kaggle kernels (notebooks) so that the front-end is properly displayed.
+
+![image](https://user-images.githubusercontent.com/41651716/216104254-2cf55599-449c-436c-b57e-40f6a83f9eee.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3101](https://github.com/gradio-app/gradio/pull/3101)
+
+### Bug Fixes:
+
+- Fix bug where examples were not rendered correctly for demos created with Blocks api that had multiple input compinents by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3090](https://github.com/gradio-app/gradio/pull/3090)
+- Fix change event listener for JSON, HighlightedText, Chatbot by [@aliabid94](https://github.com/aliabid94) in [PR 3095](https://github.com/gradio-app/gradio/pull/3095)
+- Fixes bug where video and file change event not working [@tomchang25](https://github.com/tomchang25) in [PR 3098](https://github.com/gradio-app/gradio/pull/3098)
+- Fixes bug where static_video play and pause event not working [@tomchang25](https://github.com/tomchang25) in [PR 3098](https://github.com/gradio-app/gradio/pull/3098)
+- Fixed `Gallery.style(grid=...)` by by [@aliabd](https://github.com/aliabd) in [PR 3107](https://github.com/gradio-app/gradio/pull/3107)
+
+### Documentation Changes:
+
+- Update chatbot guide to include blocks demo and markdown support section by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3023](https://github.com/gradio-app/gradio/pull/3023)
+
+* Fix a broken link in the Quick Start guide, by [@cakiki](https://github.com/cakiki) in [PR 3109](https://github.com/gradio-app/gradio/pull/3109)
+* Better docs navigation on mobile by [@aliabd](https://github.com/aliabd) in [PR 3112](https://github.com/gradio-app/gradio/pull/3112)
+* Add a guide on using Gradio with [Comet](https://comet.com/), by [@DN6](https://github.com/DN6/) in [PR 3058](https://github.com/gradio-app/gradio/pull/3058)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Set minimum `markdown-it-py` version to `2.0.0` so that the dollar math plugin is compatible by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3102](https://github.com/gradio-app/gradio/pull/3102)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.17.0
+
+### New Features:
+
+###### Extended support for Interface.load! 🏗️
+
+You can now load `image-to-text` and `conversational` pipelines from the hub!
+
+###### Image-to-text Demo
+
+```python
+io = gr.Interface.load("models/nlpconnect/vit-gpt2-image-captioning",
+ api_key="")
+io.launch()
+```
+
+
+
+###### conversational Demo
+
+```python
+chatbot = gr.Interface.load("models/microsoft/DialoGPT-medium",
+ api_key="")
+chatbot.launch()
+```
+
+![chatbot_load](https://user-images.githubusercontent.com/41651716/213260220-3eaa25b7-a38b-48c6-adeb-2718bdf297a2.gif)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3011](https://github.com/gradio-app/gradio/pull/3011)
+
+###### Download Button added to Model3D Output Component 📥
+
+No need for an additional file output component to enable model3d file downloads anymore. We now added a download button to the model3d component itself.
+
+
+
+By [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3014](https://github.com/gradio-app/gradio/pull/3014)
+
+###### Fixing Auth on Spaces 🔑
+
+Authentication on spaces works now! Third party cookies must be enabled on your browser to be able
+to log in. Some browsers disable third party cookies by default (Safari, Chrome Incognito).
+
+![auth_spaces](https://user-images.githubusercontent.com/41651716/215528417-09538933-0576-4d1d-b3b9-1e877ab01905.gif)
+
+### Bug Fixes:
+
+- Fixes bug where interpretation event was not configured correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2993](https://github.com/gradio-app/gradio/pull/2993)
+- Fix relative import bug in reload mode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2992](https://github.com/gradio-app/gradio/pull/2992)
+- Fixes bug where png files were not being recognized when uploading images by [@abidlabs](https://github.com/abidlabs) in [PR 3002](https://github.com/gradio-app/gradio/pull/3002)
+- Fixes bug where external Spaces could not be loaded and used as functions if they returned files by [@abidlabs](https://github.com/abidlabs) in [PR 3004](https://github.com/gradio-app/gradio/pull/3004)
+- Fix bug where file serialization output was not JSON serializable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2999](https://github.com/gradio-app/gradio/pull/2999)
+- Fixes bug where png files were not being recognized when uploading images by [@abidlabs](https://github.com/abidlabs) in [PR 3002](https://github.com/gradio-app/gradio/pull/3002)
+- Fixes bug where temporary uploaded files were not being added to temp sets by [@abidlabs](https://github.com/abidlabs) in [PR 3005](https://github.com/gradio-app/gradio/pull/3005)
+- Fixes issue where markdown support in chatbot breaks older demos [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3006](https://github.com/gradio-app/gradio/pull/3006)
+- Fixes the `/file/` route that was broken in a recent change in [PR 3010](https://github.com/gradio-app/gradio/pull/3010)
+- Fix bug where the Image component could not serialize image urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2957](https://github.com/gradio-app/gradio/pull/2957)
+- Fix forwarding for guides after SEO renaming by [@aliabd](https://github.com/aliabd) in [PR 3017](https://github.com/gradio-app/gradio/pull/3017)
+- Switch all pages on the website to use latest stable gradio by [@aliabd](https://github.com/aliabd) in [PR 3016](https://github.com/gradio-app/gradio/pull/3016)
+- Fix bug related to deprecated parameters in `huggingface_hub` for the HuggingFaceDatasetSaver in [PR 3025](https://github.com/gradio-app/gradio/pull/3025)
+- Added better support for symlinks in the way absolute paths are resolved by [@abidlabs](https://github.com/abidlabs) in [PR 3037](https://github.com/gradio-app/gradio/pull/3037)
+- Fix several minor frontend bugs (loading animation, examples as gallery) frontend [@aliabid94](https://github.com/3026) in [PR 2961](https://github.com/gradio-app/gradio/pull/3026).
+- Fixes bug that the chatbot sample code does not work with certain input value by [@petrov826](https://github.com/petrov826) in [PR 3039](https://github.com/gradio-app/gradio/pull/3039).
+- Fix shadows for form element and ensure focus styles more visible in dark mode [@pngwn](https://github.com/pngwn) in [PR 3042](https://github.com/gradio-app/gradio/pull/3042).
+- Fixed bug where the Checkbox and Dropdown change events were not triggered in response to other component changes by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3045](https://github.com/gradio-app/gradio/pull/3045)
+- Fix bug where the queue was not properly restarted after launching a `closed` app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3022](https://github.com/gradio-app/gradio/pull/3022)
+- Adding missing embedded components on docs by [@aliabd](https://github.com/aliabd) in [PR 3027](https://github.com/gradio-app/gradio/pull/3027)
+- Fixes bug where app would crash if the `file_types` parameter of `gr.File` or `gr.UploadButton` was not a list by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3048](https://github.com/gradio-app/gradio/pull/3048)
+- Ensure CSS mounts correctly regardless of how many Gradio instances are on the page [@pngwn](https://github.com/pngwn) in [PR 3059](https://github.com/gradio-app/gradio/pull/3059).
+- Fix bug where input component was not hidden in the frontend for `UploadButton` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3053](https://github.com/gradio-app/gradio/pull/3053)
+- Fixes issue where after clicking submit or undo, the sketch output wouldn't clear. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3047](https://github.com/gradio-app/gradio/pull/3047)
+- Ensure spaces embedded via the web component always use the correct URLs for server requests and change ports for testing to avoid strange collisions when users are working with embedded apps locally by [@pngwn](https://github.com/pngwn) in [PR 3065](https://github.com/gradio-app/gradio/pull/3065)
+- Preserve selected image of Gallery through updated by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3061](https://github.com/gradio-app/gradio/pull/3061)
+- Fix bug where auth was not respected on HF spaces by [@freddyaboulton](https://github.com/freddyaboulton) and [@aliabid94](https://github.com/aliabid94) in [PR 3049](https://github.com/gradio-app/gradio/pull/3049)
+- Fixes bug where tabs selected attribute not working if manually change tab by [@tomchang25](https://github.com/tomchang25) in [3055](https://github.com/gradio-app/gradio/pull/3055)
+- Change chatbot to show dots on progress, and fix bug where chatbot would not stick to bottom in the case of images by [@aliabid94](https://github.com/aliabid94) in [PR 3067](https://github.com/gradio-app/gradio/pull/3079)
+
+### Documentation Changes:
+
+- SEO improvements to guides by[@aliabd](https://github.com/aliabd) in [PR 2915](https://github.com/gradio-app/gradio/pull/2915)
+- Use `gr.LinePlot` for the `blocks_kinematics` demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2998](https://github.com/gradio-app/gradio/pull/2998)
+- Updated the `interface_series_load` to include some inline markdown code by [@abidlabs](https://github.com/abidlabs) in [PR 3051](https://github.com/gradio-app/gradio/pull/3051)
+
+### Testing and Infrastructure Changes:
+
+- Adds a GitHub action to test if any large files (> 5MB) are present by [@abidlabs](https://github.com/abidlabs) in [PR 3013](https://github.com/gradio-app/gradio/pull/3013)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Rewrote frontend using CSS variables for themes by [@pngwn](https://github.com/pngwn) in [PR 2840](https://github.com/gradio-app/gradio/pull/2840)
+- Moved telemetry requests to run on background threads by [@abidlabs](https://github.com/abidlabs) in [PR 3054](https://github.com/gradio-app/gradio/pull/3054)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fixed file upload fails for files with zero size by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2923](https://github.com/gradio-app/gradio/pull/2923)
+- Fixed bug where `mount_gradio_app` would not launch if the queue was enabled in a gradio app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2939](https://github.com/gradio-app/gradio/pull/2939)
+- Fix custom long CSS handling in Blocks by [@anton-l](https://github.com/anton-l) in [PR 2953](https://github.com/gradio-app/gradio/pull/2953)
+- Recovers the dropdown change event by [@abidlabs](https://github.com/abidlabs) in [PR 2954](https://github.com/gradio-app/gradio/pull/2954).
+- Fix audio file output by [@aliabid94](https://github.com/aliabid94) in [PR 2961](https://github.com/gradio-app/gradio/pull/2961).
+- Fixed bug where file extensions of really long files were not kept after download by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2929](https://github.com/gradio-app/gradio/pull/2929)
+- Fix bug where outputs for examples where not being returned by the backend by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2955](https://github.com/gradio-app/gradio/pull/2955)
+- Fix bug in `blocks_plug` demo that prevented switching tabs programmatically with python [@TashaSkyUp](https://github.com/https://github.com/TashaSkyUp) in [PR 2971](https://github.com/gradio-app/gradio/pull/2971).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Fix audio file output by [@aliabid94](https://github.com/aliabid94) in [PR 2950](https://github.com/gradio-app/gradio/pull/2950).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.16.0
+
+### New Features:
+
+###### Send custom progress updates by adding a `gr.Progress` argument after the input arguments to any function. Example:
+
+```python
+def reverse(word, progress=gr.Progress()):
+ progress(0, desc="Starting")
+ time.sleep(1)
+ new_string = ""
+ for letter in progress.tqdm(word, desc="Reversing"):
+ time.sleep(0.25)
+ new_string = letter + new_string
+ return new_string
+
+demo = gr.Interface(reverse, gr.Text(), gr.Text())
+```
+
+Progress indicator bar by [@aliabid94](https://github.com/aliabid94) in [PR 2750](https://github.com/gradio-app/gradio/pull/2750).
+
+- Added `title` argument to `TabbedInterface` by @MohamedAliRashad in [#2888](https://github.com/gradio-app/gradio/pull/2888)
+- Add support for specifying file extensions for `gr.File` and `gr.UploadButton`, using `file_types` parameter (e.g `gr.File(file_count="multiple", file_types=["text", ".json", ".csv"])`) by @dawoodkhan82 in [#2901](https://github.com/gradio-app/gradio/pull/2901)
+- Added `multiselect` option to `Dropdown` by @dawoodkhan82 in [#2871](https://github.com/gradio-app/gradio/pull/2871)
+
+###### With `multiselect` set to `true` a user can now select multiple options from the `gr.Dropdown` component.
+
+```python
+gr.Dropdown(["angola", "pakistan", "canada"], multiselect=True, value=["angola"])
+```
+
+
+
+### Bug Fixes:
+
+- Fixed bug where an error opening an audio file led to a crash by [@FelixDombek](https://github.com/FelixDombek) in [PR 2898](https://github.com/gradio-app/gradio/pull/2898)
+- Fixed bug where setting `default_enabled=False` made it so that the entire queue did not start by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2876](https://github.com/gradio-app/gradio/pull/2876)
+- Fixed bug where csv preview for DataFrame examples would show filename instead of file contents by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2877](https://github.com/gradio-app/gradio/pull/2877)
+- Fixed bug where an error raised after yielding iterative output would not be displayed in the browser by
+ [@JaySmithWpg](https://github.com/JaySmithWpg) in [PR 2889](https://github.com/gradio-app/gradio/pull/2889)
+- Fixed bug in `blocks_style` demo that was preventing it from launching by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2890](https://github.com/gradio-app/gradio/pull/2890)
+- Fixed bug where files could not be downloaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2926](https://github.com/gradio-app/gradio/pull/2926)
+- Fixed bug where cached examples were not displaying properly by [@a-rogalska](https://github.com/a-rogalska) in [PR 2974](https://github.com/gradio-app/gradio/pull/2974)
+
+### Documentation Changes:
+
+- Added a Guide on using Google Sheets to create a real-time dashboard with Gradio's `DataFrame` and `LinePlot` component, by [@abidlabs](https://github.com/abidlabs) in [PR 2816](https://github.com/gradio-app/gradio/pull/2816)
+- Add a components - events matrix on the docs by [@aliabd](https://github.com/aliabd) in [PR 2921](https://github.com/gradio-app/gradio/pull/2921)
+
+### Testing and Infrastructure Changes:
+
+- Deployed PRs from forks to spaces by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2895](https://github.com/gradio-app/gradio/pull/2895)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- The `default_enabled` parameter of the `Blocks.queue` method has no effect by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2876](https://github.com/gradio-app/gradio/pull/2876)
+- Added typing to several Python files in codebase by [@abidlabs](https://github.com/abidlabs) in [PR 2887](https://github.com/gradio-app/gradio/pull/2887)
+- Excluding untracked files from demo notebook check action by [@aliabd](https://github.com/aliabd) in [PR 2897](https://github.com/gradio-app/gradio/pull/2897)
+- Optimize images and gifs by [@aliabd](https://github.com/aliabd) in [PR 2922](https://github.com/gradio-app/gradio/pull/2922)
+- Updated typing by [@1nF0rmed](https://github.com/1nF0rmed) in [PR 2904](https://github.com/gradio-app/gradio/pull/2904)
+
+### Contributors Shoutout:
+
+- @JaySmithWpg for making their first contribution to gradio!
+- @MohamedAliRashad for making their first contribution to gradio!
+
+## 3.15.0
+
+### New Features:
+
+Gradio's newest plotting component `gr.LinePlot`! 📈
+
+With this component you can easily create time series visualizations with customizable
+appearance for your demos and dashboards ... all without having to know an external plotting library.
+
+For an example of the api see below:
+
+```python
+gr.LinePlot(stocks,
+ x="date",
+ y="price",
+ color="symbol",
+ color_legend_position="bottom",
+ width=600, height=400, title="Stock Prices")
+```
+
+![image](https://user-images.githubusercontent.com/41651716/208711646-81ae3745-149b-46a3-babd-0569aecdd409.png)
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2807](https://github.com/gradio-app/gradio/pull/2807)
+
+### Bug Fixes:
+
+- Fixed bug where the `examples_per_page` parameter of the `Examples` component was not passed to the internal `Dataset` component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2861](https://github.com/gradio-app/gradio/pull/2861)
+- Fixes loading Spaces that have components with default values by [@abidlabs](https://github.com/abidlabs) in [PR 2855](https://github.com/gradio-app/gradio/pull/2855)
+- Fixes flagging when `allow_flagging="auto"` in `gr.Interface()` by [@abidlabs](https://github.com/abidlabs) in [PR 2695](https://github.com/gradio-app/gradio/pull/2695)
+- Fixed bug where passing a non-list value to `gr.CheckboxGroup` would crash the entire app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2866](https://github.com/gradio-app/gradio/pull/2866)
+
+### Documentation Changes:
+
+- Added a Guide on using BigQuery with Gradio's `DataFrame` and `ScatterPlot` component,
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2794](https://github.com/gradio-app/gradio/pull/2794)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed importing gradio can cause PIL.Image.registered_extensions() to break by `[@aliencaocao](https://github.com/aliencaocao)` in `[PR 2846](https://github.com/gradio-app/gradio/pull/2846)`
+- Fix css glitch and navigation in docs by [@aliabd](https://github.com/aliabd) in [PR 2856](https://github.com/gradio-app/gradio/pull/2856)
+- Added the ability to set `x_lim`, `y_lim` and legend positions for `gr.ScatterPlot` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2807](https://github.com/gradio-app/gradio/pull/2807)
+- Remove footers and min-height the correct way by [@aliabd](https://github.com/aliabd) in [PR 2860](https://github.com/gradio-app/gradio/pull/2860)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.14.0
+
+### New Features:
+
+###### Add Waveform Visual Support to Audio
+
+Adds a `gr.make_waveform()` function that creates a waveform video by combining an audio and an optional background image by [@dawoodkhan82](http://github.com/dawoodkhan82) and [@aliabid94](http://github.com/aliabid94) in [PR 2706](https://github.com/gradio-app/gradio/pull/2706. Helpful for making audio outputs much more shareable.
+
+![waveform screenrecording](https://user-images.githubusercontent.com/7870876/206062396-164a5e71-451a-4fe0-94a7-cbe9269d57e6.gif)
+
+###### Allows Every Component to Accept an `every` Parameter
+
+When a component's initial value is a function, the `every` parameter re-runs the function every `every` seconds. By [@abidlabs](https://github.com/abidlabs) in [PR 2806](https://github.com/gradio-app/gradio/pull/2806). Here's a code example:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ df = gr.DataFrame(run_query, every=60*60)
+
+demo.queue().launch()
+```
+
+### Bug Fixes:
+
+- Fixed issue where too many temporary files were created, all with randomly generated
+ filepaths. Now fewer temporary files are created and are assigned a path that is a
+ hash based on the file contents by [@abidlabs](https://github.com/abidlabs) in [PR 2758](https://github.com/gradio-app/gradio/pull/2758)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.13.2
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+\*No changes to highlight.
+
+-
+
+### Documentation Changes:
+
+- Improves documentation of several queuing-related parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2825](https://github.com/gradio-app/gradio/pull/2825)
+
+### Testing and Infrastructure Changes:
+
+- Remove h11 pinning by [@ecederstrand](https://github.com/ecederstrand) in [PR 2820](https://github.com/gradio-app/gradio/pull/2820)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+No changes to highlight.
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.13.1
+
+### New Features:
+
+###### New Shareable Links
+
+Replaces tunneling logic based on ssh port-forwarding to that based on `frp` by [XciD](https://github.com/XciD) and [Wauplin](https://github.com/Wauplin) in [PR 2509](https://github.com/gradio-app/gradio/pull/2509)
+
+You don't need to do anything differently, but when you set `share=True` in `launch()`,
+you'll get this message and a public link that look a little bit different:
+
+```bash
+Setting up a public link... we have recently upgraded the way public links are generated. If you encounter any problems, please downgrade to gradio version 3.13.0
+.
+Running on public URL: https://bec81a83-5b5c-471e.gradio.live
+```
+
+These links are a more secure and scalable way to create shareable demos!
+
+### Bug Fixes:
+
+- Allows `gr.Dataframe()` to take a `pandas.DataFrame` that includes numpy array and other types as its initial value, by [@abidlabs](https://github.com/abidlabs) in [PR 2804](https://github.com/gradio-app/gradio/pull/2804)
+- Add `altair` to requirements.txt by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2811](https://github.com/gradio-app/gradio/pull/2811)
+- Added aria-labels to icon buttons that are built into UI components by [@emilyuhde](http://github.com/emilyuhde) in [PR 2791](https://github.com/gradio-app/gradio/pull/2791)
+
+### Documentation Changes:
+
+- Fixed some typos in the "Plot Component for Maps" guide by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2811](https://github.com/gradio-app/gradio/pull/2811)
+
+### Testing and Infrastructure Changes:
+
+- Fixed test for IP address by [@abidlabs](https://github.com/abidlabs) in [PR 2808](https://github.com/gradio-app/gradio/pull/2808)
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixed typo in parameter `visible` in classes in `templates.py` by [@abidlabs](https://github.com/abidlabs) in [PR 2805](https://github.com/gradio-app/gradio/pull/2805)
+- Switched external service for getting IP address from `https://api.ipify.org` to `https://checkip.amazonaws.com/` by [@abidlabs](https://github.com/abidlabs) in [PR 2810](https://github.com/gradio-app/gradio/pull/2810)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+- Fixed typo in parameter `visible` in classes in `templates.py` by [@abidlabs](https://github.com/abidlabs) in [PR 2805](https://github.com/gradio-app/gradio/pull/2805)
+- Switched external service for getting IP address from `https://api.ipify.org` to `https://checkip.amazonaws.com/` by [@abidlabs](https://github.com/abidlabs) in [PR 2810](https://github.com/gradio-app/gradio/pull/2810)
+
+## 3.13.0
+
+### New Features:
+
+###### Scatter plot component
+
+It is now possible to create a scatter plot natively in Gradio!
+
+The `gr.ScatterPlot` component accepts a pandas dataframe and some optional configuration parameters
+and will automatically create a plot for you!
+
+This is the first of many native plotting components in Gradio!
+
+For an example of how to use `gr.ScatterPlot` see below:
+
+```python
+import gradio as gr
+from vega_datasets import data
+
+cars = data.cars()
+
+with gr.Blocks() as demo:
+ gr.ScatterPlot(show_label=False,
+ value=cars,
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ tooltip="Name",
+ title="Car Data",
+ y_title="Miles per Gallon",
+ color_legend_title="Origin of Car").style(container=False)
+
+demo.launch()
+```
+
+
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2764](https://github.com/gradio-app/gradio/pull/2764)
+
+###### Support for altair plots
+
+The `Plot` component can now accept altair plots as values!
+Simply return an altair plot from your event listener and gradio will display it in the front-end.
+See the example below:
+
+```python
+import gradio as gr
+import altair as alt
+from vega_datasets import data
+
+cars = data.cars()
+chart = (
+ alt.Chart(cars)
+ .mark_point()
+ .encode(
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ )
+)
+
+with gr.Blocks() as demo:
+ gr.Plot(value=chart)
+demo.launch()
+```
+
+
+
+By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2741](https://github.com/gradio-app/gradio/pull/2741)
+
+###### Set the background color of a Label component
+
+The `Label` component now accepts a `color` argument by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2736](https://github.com/gradio-app/gradio/pull/2736).
+The `color` argument should either be a valid css color name or hexadecimal string.
+You can update the color with `gr.Label.update`!
+
+This lets you create Alert and Warning boxes with the `Label` component. See below:
+
+```python
+import gradio as gr
+import random
+
+def update_color(value):
+ if value < 0:
+ # This is bad so use red
+ return "#FF0000"
+ elif 0 <= value <= 20:
+ # Ok but pay attention (use orange)
+ return "#ff9966"
+ else:
+ # Nothing to worry about
+ return None
+
+def update_value():
+ choice = random.choice(['good', 'bad', 'so-so'])
+ color = update_color(choice)
+ return gr.Label.update(value=choice, color=color)
+
+
+with gr.Blocks() as demo:
+ label = gr.Label(value=-10)
+ demo.load(lambda: update_value(), inputs=None, outputs=[label], every=1)
+demo.queue().launch()
+```
+
+![label_bg_color_update](https://user-images.githubusercontent.com/41651716/204400372-80e53857-f26f-4a38-a1ae-1acadff75e89.gif)
+
+###### Add Brazilian Portuguese translation
+
+Add Brazilian Portuguese translation (pt-BR.json) by [@pstwh](http://github.com/pstwh) in [PR 2753](https://github.com/gradio-app/gradio/pull/2753):
+
+
+
+### Bug Fixes:
+
+- Fixed issue where image thumbnails were not showing when an example directory was provided
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2745](https://github.com/gradio-app/gradio/pull/2745)
+- Fixed bug loading audio input models from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2779](https://github.com/gradio-app/gradio/pull/2779).
+- Fixed issue where entities were not merged when highlighted text was generated from the
+ dictionary inputs [@payoto](https://github.com/payoto) in [PR 2767](https://github.com/gradio-app/gradio/pull/2767)
+- Fixed bug where generating events did not finish running even if the websocket connection was closed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2783](https://github.com/gradio-app/gradio/pull/2783).
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Images in the chatbot component are now resized if they exceed a max width by [@abidlabs](https://github.com/abidlabs) in [PR 2748](https://github.com/gradio-app/gradio/pull/2748)
+- Missing parameters have been added to `gr.Blocks().load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2755](https://github.com/gradio-app/gradio/pull/2755)
+- Deindex share URLs from search by [@aliabd](https://github.com/aliabd) in [PR 2772](https://github.com/gradio-app/gradio/pull/2772)
+- Redirect old links and fix broken ones by [@aliabd](https://github.com/aliabd) in [PR 2774](https://github.com/gradio-app/gradio/pull/2774)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.12.0
+
+### New Features:
+
+###### The `Chatbot` component now supports a subset of Markdown (including bold, italics, code, images)
+
+You can now pass in some Markdown to the Chatbot component and it will show up,
+meaning that you can pass in images as well! by [@abidlabs](https://github.com/abidlabs) in [PR 2731](https://github.com/gradio-app/gradio/pull/2731)
+
+Here's a simple example that references a local image `lion.jpg` that is in the same
+folder as the Python script:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Chatbot([("hi", "hello **abubakar**"), ("![](/file=lion.jpg)", "cool pic")])
+
+demo.launch()
+```
+
+![Alt text](https://user-images.githubusercontent.com/1778297/204357455-5c1a4002-eee7-479d-9a1e-ba2c12522723.png)
+
+To see a more realistic example, see the new demo `/demo/chatbot_multimodal/run.py`.
+
+###### Latex support
+
+Added mathtext (a subset of latex) support to gr.Markdown. Added by [@kashif](https://github.com/kashif) and [@aliabid94](https://github.com/aliabid94) in [PR 2696](https://github.com/gradio-app/gradio/pull/2696).
+
+Example of how it can be used:
+
+```python
+gr.Markdown(
+ r"""
+ # Hello World! $\frac{\sqrt{x + y}}{4}$ is today's lesson.
+ """)
+```
+
+###### Update Accordion properties from the backend
+
+You can now update the Accordion `label` and `open` status with `gr.Accordion.update` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2690](https://github.com/gradio-app/gradio/pull/2690)
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Accordion(label="Open for greeting", open=False) as accordion:
+ gr.Textbox("Hello!")
+ open_btn = gr.Button(value="Open Accordion")
+ close_btn = gr.Button(value="Close Accordion")
+ open_btn.click(
+ lambda: gr.Accordion.update(open=True, label="Open Accordion"),
+ inputs=None,
+ outputs=[accordion],
+ )
+ close_btn.click(
+ lambda: gr.Accordion.update(open=False, label="Closed Accordion"),
+ inputs=None,
+ outputs=[accordion],
+ )
+demo.launch()
+```
+
+![update_accordion](https://user-images.githubusercontent.com/41651716/203164176-b102eae3-babe-4986-ae30-3ab4f400cedc.gif)
+
+### Bug Fixes:
+
+- Fixed bug where requests timeout is missing from utils.version_check() by [@yujiehecs](https://github.com/yujiehecs) in [PR 2729](https://github.com/gradio-app/gradio/pull/2729)
+- Fixed bug where so that the `File` component can properly preprocess files to "binary" byte-string format by [CoffeeVampir3](https://github.com/CoffeeVampir3) in [PR 2727](https://github.com/gradio-app/gradio/pull/2727)
+- Fixed bug to ensure that filenames are less than 200 characters even for non-English languages by [@SkyTNT](https://github.com/SkyTNT) in [PR 2685](https://github.com/gradio-app/gradio/pull/2685)
+
+### Documentation Changes:
+
+- Performance improvements to docs on mobile by [@aliabd](https://github.com/aliabd) in [PR 2730](https://github.com/gradio-app/gradio/pull/2730)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Make try examples button more prominent by [@aliabd](https://github.com/aliabd) in [PR 2705](https://github.com/gradio-app/gradio/pull/2705)
+- Fix id clashes in docs by [@aliabd](https://github.com/aliabd) in [PR 2713](https://github.com/gradio-app/gradio/pull/2713)
+- Fix typos in guide docs by [@andridns](https://github.com/andridns) in [PR 2722](https://github.com/gradio-app/gradio/pull/2722)
+- Add option to `include_audio` in Video component. When `True`, for `source="webcam"` this will record audio and video, for `source="upload"` this will retain the audio in an uploaded video by [@mandargogate](https://github.com/MandarGogate) in [PR 2721](https://github.com/gradio-app/gradio/pull/2721)
+
+### Contributors Shoutout:
+
+- [@andridns](https://github.com/andridns) made their first contribution in [PR 2722](https://github.com/gradio-app/gradio/pull/2722)!
+
+## 3.11.0
+
+### New Features:
+
+###### Upload Button
+
+There is now a new component called the `UploadButton` which is a file upload component but in button form! You can also specify what file types it should accept in the form of a list (ex: `image`, `video`, `audio`, `text`, or generic `file`). Added by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2591](https://github.com/gradio-app/gradio/pull/2591).
+
+Example of how it can be used:
+
+```python
+import gradio as gr
+
+def upload_file(files):
+ file_paths = [file.name for file in files]
+ return file_paths
+
+with gr.Blocks() as demo:
+ file_output = gr.File()
+ upload_button = gr.UploadButton("Click to Upload a File", file_types=["image", "video"], file_count="multiple")
+ upload_button.upload(upload_file, upload_button, file_output)
+
+demo.launch()
+```
+
+###### Revamped API documentation page
+
+New API Docs page with in-browser playground and updated aesthetics. [@gary149](https://github.com/gary149) in [PR 2652](https://github.com/gradio-app/gradio/pull/2652)
+
+###### Revamped Login page
+
+Previously our login page had its own CSS, had no dark mode, and had an ugly json message on the wrong credentials. Made the page more aesthetically consistent, added dark mode support, and a nicer error message. [@aliabid94](https://github.com/aliabid94) in [PR 2684](https://github.com/gradio-app/gradio/pull/2684)
+
+###### Accessing the Requests Object Directly
+
+You can now access the Request object directly in your Python function by [@abidlabs](https://github.com/abidlabs) in [PR 2641](https://github.com/gradio-app/gradio/pull/2641). This means that you can access request headers, the client IP address, and so on. In order to use it, add a parameter to your function and set its type hint to be `gr.Request`. Here's a simple example:
+
+```py
+import gradio as gr
+
+def echo(name, request: gr.Request):
+ if request:
+ print("Request headers dictionary:", request.headers)
+ print("IP address:", request.client.host)
+ return name
+
+io = gr.Interface(echo, "textbox", "textbox").launch()
+```
+
+### Bug Fixes:
+
+- Fixed bug that limited files from being sent over websockets to 16MB. The new limit
+ is now 1GB by [@abidlabs](https://github.com/abidlabs) in [PR 2709](https://github.com/gradio-app/gradio/pull/2709)
+
+### Documentation Changes:
+
+- Updated documentation for embedding Gradio demos on Spaces as web components by
+ [@julien-c](https://github.com/julien-c) in [PR 2698](https://github.com/gradio-app/gradio/pull/2698)
+- Updated IFrames in Guides to use the host URL instead of the Space name to be consistent with the new method for embedding Spaces, by
+ [@julien-c](https://github.com/julien-c) in [PR 2692](https://github.com/gradio-app/gradio/pull/2692)
+- Colab buttons on every demo in the website! Just click open in colab, and run the demo there.
+
+https://user-images.githubusercontent.com/9021060/202878400-cb16ed47-f4dd-4cb0-b2f0-102a9ff64135.mov
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Better warnings and error messages for `gr.Interface.load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2694](https://github.com/gradio-app/gradio/pull/2694)
+- Add open in colab buttons to demos in docs and /demos by [@aliabd](https://github.com/aliabd) in [PR 2608](https://github.com/gradio-app/gradio/pull/2608)
+- Apply different formatting for the types in component docstrings by [@aliabd](https://github.com/aliabd) in [PR 2707](https://github.com/gradio-app/gradio/pull/2707)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.10.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Passes kwargs into `gr.Interface.load()` by [@abidlabs](https://github.com/abidlabs) in [PR 2669](https://github.com/gradio-app/gradio/pull/2669)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Clean up printed statements in Embedded Colab Mode by [@aliabid94](https://github.com/aliabid94) in [PR 2612](https://github.com/gradio-app/gradio/pull/2612)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.10.0
+
+- Add support for `'password'` and `'email'` types to `Textbox`. [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653)
+- `gr.Textbox` component will now raise an exception if `type` is not "text", "email", or "password" [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653). This will cause demos using the deprecated `gr.Textbox(type="number")` to raise an exception.
+
+### Bug Fixes:
+
+- Updated the minimum FastApi used in tests to version 0.87 by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2647](https://github.com/gradio-app/gradio/pull/2647)
+- Fixed bug where interfaces with examples could not be loaded with `gr.Interface.load` by [@freddyaboulton](https://github.com/freddyaboulton) [PR 2640](https://github.com/gradio-app/gradio/pull/2640)
+- Fixed bug where the `interactive` property of a component could not be updated by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2639](https://github.com/gradio-app/gradio/pull/2639)
+- Fixed bug where some URLs were not being recognized as valid URLs and thus were not
+ loading correctly in various components by [@abidlabs](https://github.com/abidlabs) in [PR 2659](https://github.com/gradio-app/gradio/pull/2659)
+
+### Documentation Changes:
+
+- Fix some typos in the embedded demo names in "05_using_blocks_like_functions.md" by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2656](https://github.com/gradio-app/gradio/pull/2656)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Add support for `'password'` and `'email'` types to `Textbox`. [@pngwn](https://github.com/pngwn) in [PR 2653](https://github.com/gradio-app/gradio/pull/2653)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.9.1
+
+### New Features:
+
+No changes to highlight.
+
+### Bug Fixes:
+
+- Only set a min height on md and html when loading by [@pngwn](https://github.com/pngwn) in [PR 2623](https://github.com/gradio-app/gradio/pull/2623)
+
+### Documentation Changes:
+
+- See docs for the latest gradio commit to main as well the latest pip release:
+
+![main-vs-pip](https://user-images.githubusercontent.com/9021060/199607887-aab1ae4e-a070-4527-966d-024397abe15b.gif)
+
+- Modified the "Connecting To a Database Guide" to use `pd.read_sql` as opposed to low-level postgres connector by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2604](https://github.com/gradio-app/gradio/pull/2604)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Dropdown for seeing docs as latest or main by [@aliabd](https://github.com/aliabd) in [PR 2544](https://github.com/gradio-app/gradio/pull/2544)
+- Allow `gr.Templates` to accept parameters to override the defaults by [@abidlabs](https://github.com/abidlabs) in [PR 2600](https://github.com/gradio-app/gradio/pull/2600)
+- Components now throw a `ValueError()` if constructed with invalid parameters for `type` or `source` (for components that take those parameters) in [PR 2610](https://github.com/gradio-app/gradio/pull/2610)
+- Allow auth with using queue by [@GLGDLY](https://github.com/GLGDLY) in [PR 2611](https://github.com/gradio-app/gradio/pull/2611)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.9
+
+### New Features:
+
+- Gradio is now embedded directly in colab without requiring the share link by [@aliabid94](https://github.com/aliabid94) in [PR 2455](https://github.com/gradio-app/gradio/pull/2455)
+
+###### Calling functions by api_name in loaded apps
+
+When you load an upstream app with `gr.Blocks.load`, you can now specify which fn
+to call with the `api_name` parameter.
+
+```python
+import gradio as gr
+english_translator = gr.Blocks.load(name="spaces/gradio/english-translator")
+german = english_translator("My name is Freddy", api_name='translate-to-german')
+```
+
+The `api_name` parameter will take precedence over the `fn_index` parameter.
+
+### Bug Fixes:
+
+- Fixed bug where None could not be used for File,Model3D, and Audio examples by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2588](https://github.com/gradio-app/gradio/pull/2588)
+- Fixed links in Plotly map guide + demo by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2578](https://github.com/gradio-app/gradio/pull/2578)
+- `gr.Blocks.load()` now correctly loads example files from Spaces [@abidlabs](https://github.com/abidlabs) in [PR 2594](https://github.com/gradio-app/gradio/pull/2594)
+- Fixed bug when image clear started upload dialog [@mezotaken](https://github.com/mezotaken) in [PR 2577](https://github.com/gradio-app/gradio/pull/2577)
+
+### Documentation Changes:
+
+- Added a Guide on how to configure the queue for maximum performance by [@abidlabs](https://github.com/abidlabs) in [PR 2558](https://github.com/gradio-app/gradio/pull/2558)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Add `api_name` to `Blocks.__call__` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2593](https://github.com/gradio-app/gradio/pull/2593)
+- Update queue with using deque & update requirements by [@GLGDLY](https://github.com/GLGDLY) in [PR 2428](https://github.com/gradio-app/gradio/pull/2428)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.8.2
+
+### Bug Fixes:
+
+- Ensure gradio apps embedded via spaces use the correct endpoint for predictions. [@pngwn](https://github.com/pngwn) in [PR 2567](https://github.com/gradio-app/gradio/pull/2567)
+- Ensure gradio apps embedded via spaces use the correct websocket protocol. [@pngwn](https://github.com/pngwn) in [PR 2571](https://github.com/gradio-app/gradio/pull/2571)
+
+### New Features:
+
+###### Running Events Continuously
+
+Gradio now supports the ability to run an event continuously on a fixed schedule. To use this feature,
+pass `every=# of seconds` to the event definition. This will run the event every given number of seconds!
+
+This can be used to:
+
+- Create live visualizations that show the most up to date data
+- Refresh the state of the frontend automatically in response to changes in the backend
+
+Here is an example of a live plot that refreshes every half second:
+
+```python
+import math
+import gradio as gr
+import plotly.express as px
+import numpy as np
+
+
+plot_end = 2 * math.pi
+
+
+def get_plot(period=1):
+ global plot_end
+ x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)
+ y = np.sin(2*math.pi*period * x)
+ fig = px.line(x=x, y=y)
+ plot_end += 2 * math.pi
+ return fig
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ gr.Markdown("Change the value of the slider to automatically update the plot")
+ period = gr.Slider(label="Period of plot", value=1, minimum=0, maximum=10, step=1)
+ plot = gr.Plot(label="Plot (updates every half second)")
+
+ dep = demo.load(get_plot, None, plot, every=0.5)
+ period.change(get_plot, period, plot, every=0.5, cancels=[dep])
+
+demo.queue().launch()
+```
+
+![live_demo](https://user-images.githubusercontent.com/41651716/198357377-633ce460-4e31-47bd-8202-1440cdd6fe19.gif)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+- Explained how to set up `queue` and `auth` when working with reload mode by by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3089)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Allows loading private Spaces by passing an an `api_key` to `gr.Interface.load()`
+ by [@abidlabs](https://github.com/abidlabs) in [PR 2568](https://github.com/gradio-app/gradio/pull/2568)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.8
+
+### New Features:
+
+- Allows event listeners to accept a single dictionary as its argument, where the keys are the components and the values are the component values. This is set by passing the input components in the event listener as a set instead of a list. [@aliabid94](https://github.com/aliabid94) in [PR 2550](https://github.com/gradio-app/gradio/pull/2550)
+
+### Bug Fixes:
+
+- Fix whitespace issue when using plotly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2548](https://github.com/gradio-app/gradio/pull/2548)
+- Apply appropriate alt text to all gallery images. [@camenduru](https://github.com/camenduru) in [PR 2358](https://github.com/gradio-app/gradio/pull/2538)
+- Removed erroneous tkinter import in gradio.blocks by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2555](https://github.com/gradio-app/gradio/pull/2555)
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Added the `every` keyword to event listeners that runs events on a fixed schedule by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2512](https://github.com/gradio-app/gradio/pull/2512)
+- Fix whitespace issue when using plotly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2548](https://github.com/gradio-app/gradio/pull/2548)
+- Apply appropriate alt text to all gallery images. [@camenduru](https://github.com/camenduru) in [PR 2358](https://github.com/gradio-app/gradio/pull/2538)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.7
+
+### New Features:
+
+###### Batched Functions
+
+Gradio now supports the ability to pass _batched_ functions. Batched functions are just
+functions which take in a list of inputs and return a list of predictions.
+
+For example, here is a batched function that takes in two lists of inputs (a list of
+words and a list of ints), and returns a list of trimmed words as output:
+
+```py
+import time
+
+def trim_words(words, lens):
+ trimmed_words = []
+ time.sleep(5)
+ for w, l in zip(words, lens):
+ trimmed_words.append(w[:l])
+ return [trimmed_words]
+```
+
+The advantage of using batched functions is that if you enable queuing, the Gradio
+server can automatically _batch_ incoming requests and process them in parallel,
+potentially speeding up your demo. Here's what the Gradio code looks like (notice
+the `batch=True` and `max_batch_size=16` -- both of these parameters can be passed
+into event triggers or into the `Interface` class)
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ word = gr.Textbox(label="word", value="abc")
+ leng = gr.Number(label="leng", precision=0, value=1)
+ output = gr.Textbox(label="Output")
+ with gr.Row():
+ run = gr.Button()
+
+ event = run.click(trim_words, [word, leng], output, batch=True, max_batch_size=16)
+
+demo.queue()
+demo.launch()
+```
+
+In the example above, 16 requests could be processed in parallel (for a total inference
+time of 5 seconds), instead of each request being processed separately (for a total
+inference time of 80 seconds).
+
+###### Upload Event
+
+`Video`, `Audio`, `Image`, and `File` components now support a `upload()` event that is triggered when a user uploads a file into any of these components.
+
+Example usage:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ input_video = gr.Video()
+ output_video = gr.Video()
+
+ # Clears the output video when an input video is uploaded
+ input_video.upload(lambda : None, None, output_video)
+```
+
+### Bug Fixes:
+
+- Fixes issue where plotly animations, interactivity, titles, legends, were not working properly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2486](https://github.com/gradio-app/gradio/pull/2486)
+- Prevent requests to the `/api` endpoint from skipping the queue if the queue is enabled for that event by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2493](https://github.com/gradio-app/gradio/pull/2493)
+- Fixes a bug with `cancels` in event triggers so that it works properly if multiple
+ Blocks are rendered by [@abidlabs](https://github.com/abidlabs) in [PR 2530](https://github.com/gradio-app/gradio/pull/2530)
+- Prevent invalid targets of events from crashing the whole application. [@pngwn](https://github.com/pngwn) in [PR 2534](https://github.com/gradio-app/gradio/pull/2534)
+- Properly dequeue cancelled events when multiple apps are rendered by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2540](https://github.com/gradio-app/gradio/pull/2540)
+- Fixes videos being cropped due to height/width params not being used [@hannahblair](https://github.com/hannahblair) in [PR 4946](https://github.com/gradio-app/gradio/pull/4946)
+
+### Documentation Changes:
+
+- Added an example interactive dashboard to the "Tabular & Plots" section of the Demos page by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2508](https://github.com/gradio-app/gradio/pull/2508)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Fixes the error message if a user builds Gradio locally and tries to use `share=True` by [@abidlabs](https://github.com/abidlabs) in [PR 2502](https://github.com/gradio-app/gradio/pull/2502)
+- Allows the render() function to return self by [@Raul9595](https://github.com/Raul9595) in [PR 2514](https://github.com/gradio-app/gradio/pull/2514)
+- Fixes issue where plotly animations, interactivity, titles, legends, were not working properly. [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2486](https://github.com/gradio-app/gradio/pull/2486)
+- Gradio now supports batched functions by [@abidlabs](https://github.com/abidlabs) in [PR 2218](https://github.com/gradio-app/gradio/pull/2218)
+- Add `upload` event for `Video`, `Audio`, `Image`, and `File` components [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2448](https://github.com/gradio-app/gradio/pull/2456)
+- Changes websocket path for Spaces as it is no longer necessary to have a different URL for websocket connections on Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 2528](https://github.com/gradio-app/gradio/pull/2528)
+- Clearer error message when events are defined outside of a Blocks scope, and a warning if you
+ try to use `Series` or `Parallel` with `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 2543](https://github.com/gradio-app/gradio/pull/2543)
+- Adds support for audio samples that are in `float64`, `float16`, or `uint16` formats by [@abidlabs](https://github.com/abidlabs) in [PR 2545](https://github.com/gradio-app/gradio/pull/2545)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.6
+
+### New Features:
+
+###### Cancelling Running Events
+
+Running events can be cancelled when other events are triggered! To test this feature, pass the `cancels` parameter to the event listener.
+For this feature to work, the queue must be enabled.
+
+![cancel_on_change_rl](https://user-images.githubusercontent.com/41651716/195952623-61a606bd-e82b-4e1a-802e-223154cb8727.gif)
+
+Code:
+
+```python
+import time
+import gradio as gr
+
+def fake_diffusion(steps):
+ for i in range(steps):
+ time.sleep(1)
+ yield str(i)
+
+def long_prediction(*args, **kwargs):
+ time.sleep(10)
+ return 42
+
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ n = gr.Slider(1, 10, value=9, step=1, label="Number Steps")
+ run = gr.Button()
+ output = gr.Textbox(label="Iterative Output")
+ stop = gr.Button(value="Stop Iterating")
+ with gr.Column():
+ prediction = gr.Number(label="Expensive Calculation")
+ run_pred = gr.Button(value="Run Expensive Calculation")
+ with gr.Column():
+ cancel_on_change = gr.Textbox(label="Cancel Iteration and Expensive Calculation on Change")
+
+ click_event = run.click(fake_diffusion, n, output)
+ stop.click(fn=None, inputs=None, outputs=None, cancels=[click_event])
+ pred_event = run_pred.click(fn=long_prediction, inputs=None, outputs=prediction)
+
+ cancel_on_change.change(None, None, None, cancels=[click_event, pred_event])
+
+
+demo.queue(concurrency_count=1, max_size=20).launch()
+```
+
+For interfaces, a stop button will be added automatically if the function uses a `yield` statement.
+
+```python
+import gradio as gr
+import time
+
+def iteration(steps):
+ for i in range(steps):
+ time.sleep(0.5)
+ yield i
+
+gr.Interface(iteration,
+ inputs=gr.Slider(minimum=1, maximum=10, step=1, value=5),
+ outputs=gr.Number()).queue().launch()
+```
+
+![stop_interface_rl](https://user-images.githubusercontent.com/41651716/195952883-e7ca4235-aae3-4852-8f28-96d01d0c5822.gif)
+
+### Bug Fixes:
+
+- Add loading status tracker UI to HTML and Markdown components. [@pngwn](https://github.com/pngwn) in [PR 2474](https://github.com/gradio-app/gradio/pull/2474)
+- Fixed videos being mirrored in the front-end if source is not webcam by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2475](https://github.com/gradio-app/gradio/pull/2475)
+- Add clear button for timeseries component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2487](https://github.com/gradio-app/gradio/pull/2487)
+- Removes special characters from temporary filenames so that the files can be served by components [@abidlabs](https://github.com/abidlabs) in [PR 2480](https://github.com/gradio-app/gradio/pull/2480)
+- Fixed infinite reload loop when mounting gradio as a sub application by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2477](https://github.com/gradio-app/gradio/pull/2477)
+
+### Documentation Changes:
+
+- Adds a demo to show how a sound alert can be played upon completion of a prediction by [@abidlabs](https://github.com/abidlabs) in [PR 2478](https://github.com/gradio-app/gradio/pull/2478)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Enable running events to be cancelled from other events by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2433](https://github.com/gradio-app/gradio/pull/2433)
+- Small fix for version check before reuploading demos by [@aliabd](https://github.com/aliabd) in [PR 2469](https://github.com/gradio-app/gradio/pull/2469)
+- Add loading status tracker UI to HTML and Markdown components. [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2474)
+- Add clear button for timeseries component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2487](https://github.com/gradio-app/gradio/pull/2487)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.5
+
+### Bug Fixes:
+
+- Ensure that Gradio does not take control of the HTML page title when embedding a gradio app as a web component, this behaviour flipped by adding `control_page_title="true"` to the webcomponent. [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2400)
+- Decreased latency in iterative-output demos by making the iteration asynchronous [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2409](https://github.com/gradio-app/gradio/pull/2409)
+- Fixed queue getting stuck under very high load by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2374](https://github.com/gradio-app/gradio/pull/2374)
+- Ensure that components always behave as if `interactive=True` were set when the following conditions are true:
+
+ - no default value is provided,
+ - they are not set as the input or output of an event,
+ - `interactive` kwarg is not set.
+
+ [@pngwn](https://github.com/pngwn) in [PR 2459](https://github.com/gradio-app/gradio/pull/2459)
+
+### New Features:
+
+- When an `Image` component is set to `source="upload"`, it is now possible to drag and drop and image to replace a previously uploaded image by [@pngwn](https://github.com/pngwn) in [PR 1711](https://github.com/gradio-app/gradio/issues/1711)
+- The `gr.Dataset` component now accepts `HTML` and `Markdown` components by [@abidlabs](https://github.com/abidlabs) in [PR 2437](https://github.com/gradio-app/gradio/pull/2437)
+
+### Documentation Changes:
+
+- Improved documentation for the `gr.Dataset` component by [@abidlabs](https://github.com/abidlabs) in [PR 2437](https://github.com/gradio-app/gradio/pull/2437)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+- The `Carousel` component is officially deprecated. Since gradio 3.0, code containing the `Carousel` component would throw warnings. As of the next release, the `Carousel` component will raise an exception.
+
+### Full Changelog:
+
+- Speeds up Gallery component by using temporary files instead of base64 representation in the front-end by [@proxyphi](https://github.com/proxyphi), [@pngwn](https://github.com/pngwn), and [@abidlabs](https://github.com/abidlabs) in [PR 2265](https://github.com/gradio-app/gradio/pull/2265)
+- Fixed some embedded demos in the guides by not loading the gradio web component in some guides by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2403](https://github.com/gradio-app/gradio/pull/2403)
+- When an `Image` component is set to `source="upload"`, it is now possible to drag and drop and image to replace a previously uploaded image by [@pngwn](https://github.com/pngwn) in [PR 2400](https://github.com/gradio-app/gradio/pull/2410)
+- Improve documentation of the `Blocks.load()` event by [@abidlabs](https://github.com/abidlabs) in [PR 2413](https://github.com/gradio-app/gradio/pull/2413)
+- Decreased latency in iterative-output demos by making the iteration asynchronous [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2409](https://github.com/gradio-app/gradio/pull/2409)
+- Updated share link message to reference new Spaces Hardware [@abidlabs](https://github.com/abidlabs) in [PR 2423](https://github.com/gradio-app/gradio/pull/2423)
+- Automatically restart spaces if they're down by [@aliabd](https://github.com/aliabd) in [PR 2405](https://github.com/gradio-app/gradio/pull/2405)
+- Carousel component is now deprecated by [@abidlabs](https://github.com/abidlabs) in [PR 2434](https://github.com/gradio-app/gradio/pull/2434)
+- Build Gradio from source in ui tests by by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2440](https://github.com/gradio-app/gradio/pull/2440)
+- Change "return ValueError" to "raise ValueError" by [@vzakharov](https://github.com/vzakharov) in [PR 2445](https://github.com/gradio-app/gradio/pull/2445)
+- Add guide on creating a map demo using the `gr.Plot()` component [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2402](https://github.com/gradio-app/gradio/pull/2402)
+- Add blur event for `Textbox` and `Number` components [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2448](https://github.com/gradio-app/gradio/pull/2448)
+- Stops a gradio launch from hogging a port even after it's been killed [@aliabid94](https://github.com/aliabid94) in [PR 2453](https://github.com/gradio-app/gradio/pull/2453)
+- Fix embedded interfaces on touch screen devices by [@aliabd](https://github.com/aliabd) in [PR 2457](https://github.com/gradio-app/gradio/pull/2457)
+- Upload all demos to spaces by [@aliabd](https://github.com/aliabd) in [PR 2281](https://github.com/gradio-app/gradio/pull/2281)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.4.1
+
+### New Features:
+
+###### 1. See Past and Upcoming Changes in the Release History 👀
+
+You can now see gradio's release history directly on the website, and also keep track of upcoming changes. Just go [here](https://gradio.app/changelog/).
+
+![release-history](https://user-images.githubusercontent.com/9021060/193145458-3de699f7-7620-45de-aa73-a1c1b9b96257.gif)
+
+### Bug Fixes:
+
+1. Fix typo in guide image path by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2357](https://github.com/gradio-app/gradio/pull/2357)
+2. Raise error if Blocks has duplicate component with same IDs by [@abidlabs](https://github.com/abidlabs) in [PR 2359](https://github.com/gradio-app/gradio/pull/2359)
+3. Catch the permission exception on the audio component by [@Ian-GL](https://github.com/Ian-GL) in [PR 2330](https://github.com/gradio-app/gradio/pull/2330)
+4. Fix image_classifier_interface_load demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2365](https://github.com/gradio-app/gradio/pull/2365)
+5. Fix combining adjacent components without gaps by introducing `gr.Row(variant="compact")` by [@aliabid94](https://github.com/aliabid94) in [PR 2291](https://github.com/gradio-app/gradio/pull/2291) This comes with deprecation of the following arguments for `Component.style`: `round`, `margin`, `border`.
+6. Fix audio streaming, which was previously choppy in [PR 2351](https://github.com/gradio-app/gradio/pull/2351). Big thanks to [@yannickfunk](https://github.com/yannickfunk) for the proposed solution.
+7. Fix bug where new typeable slider doesn't respect the minimum and maximum values [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2380](https://github.com/gradio-app/gradio/pull/2380)
+
+### Documentation Changes:
+
+1. New Guide: Connecting to a Database 🗄️
+
+ A new guide by [@freddyaboulton](https://github.com/freddyaboulton) that explains how you can use Gradio to connect your app to a database. Read more [here](https://gradio.app/connecting_to_a_database/).
+
+2. New Guide: Running Background Tasks 🥷
+
+ A new guide by [@freddyaboulton](https://github.com/freddyaboulton) that explains how you can run background tasks from your gradio app. Read more [here](https://gradio.app/running_background_tasks/).
+
+3. Small fixes to docs for `Image` component by [@abidlabs](https://github.com/abidlabs) in [PR 2372](https://github.com/gradio-app/gradio/pull/2372)
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- Create a guide on how to connect an app to a database hosted on the cloud by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2341](https://github.com/gradio-app/gradio/pull/2341)
+- Removes `analytics` dependency by [@abidlabs](https://github.com/abidlabs) in [PR 2347](https://github.com/gradio-app/gradio/pull/2347)
+- Add guide on launching background tasks from your app by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2350](https://github.com/gradio-app/gradio/pull/2350)
+- Fix typo in guide image path by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2357](https://github.com/gradio-app/gradio/pull/2357)
+- Raise error if Blocks has duplicate component with same IDs by [@abidlabs](https://github.com/abidlabs) in [PR 2359](https://github.com/gradio-app/gradio/pull/2359)
+- Hotfix: fix version back to 3.4 by [@abidlabs](https://github.com/abidlabs) in [PR 2361](https://github.com/gradio-app/gradio/pull/2361)
+- Change version.txt to 3.4 instead of 3.4.0 by [@aliabd](https://github.com/aliabd) in [PR 2363](https://github.com/gradio-app/gradio/pull/2363)
+- Catch the permission exception on the audio component by [@Ian-GL](https://github.com/Ian-GL) in [PR 2330](https://github.com/gradio-app/gradio/pull/2330)
+- Fix image_classifier_interface_load demo by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2365](https://github.com/gradio-app/gradio/pull/2365)
+- Small fixes to docs for `Image` component by [@abidlabs](https://github.com/abidlabs) in [PR 2372](https://github.com/gradio-app/gradio/pull/2372)
+- Automated Release Notes by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2306](https://github.com/gradio-app/gradio/pull/2306)
+- Fixed small typos in the docs [@julien-c](https://github.com/julien-c) in [PR 2373](https://github.com/gradio-app/gradio/pull/2373)
+- Adds ability to disable pre/post-processing for examples [@abidlabs](https://github.com/abidlabs) in [PR 2383](https://github.com/gradio-app/gradio/pull/2383)
+- Copy changelog file in website docker by [@aliabd](https://github.com/aliabd) in [PR 2384](https://github.com/gradio-app/gradio/pull/2384)
+- Lets users provide a `gr.update()` dictionary even if post-processing is disabled [@abidlabs](https://github.com/abidlabs) in [PR 2385](https://github.com/gradio-app/gradio/pull/2385)
+- Fix bug where errors would cause apps run in reload mode to hang forever by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2394](https://github.com/gradio-app/gradio/pull/2394)
+- Fix bug where new typeable slider doesn't respect the minimum and maximum values [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2380](https://github.com/gradio-app/gradio/pull/2380)
+
+### Contributors Shoutout:
+
+No changes to highlight.
+
+## 3.4
+
+### New Features:
+
+###### 1. Gallery Captions 🖼️
+
+You can now pass captions to images in the Gallery component. To do so you need to pass a {List} of (image, {str} caption) tuples. This is optional and the component also accepts just a list of the images.
+
+Here's an example:
+
+```python
+import gradio as gr
+
+images_with_captions = [
+ ("https://images.unsplash.com/photo-1551969014-7d2c4cddf0b6", "Cheetah by David Groves"),
+ ("https://images.unsplash.com/photo-1546182990-dffeafbe841d", "Lion by Francesco"),
+ ("https://images.unsplash.com/photo-1561731216-c3a4d99437d5", "Tiger by Mike Marrah")
+ ]
+
+with gr.Blocks() as demo:
+ gr.Gallery(value=images_with_captions)
+
+demo.launch()
+```
+
+
+
+###### 2. Type Values into the Slider 🔢
+
+You can now type values directly on the Slider component! Here's what it looks like:
+
+![type-slider](https://user-images.githubusercontent.com/9021060/192399877-76b662a1-fede-4417-a932-fc15f0da7360.gif)
+
+###### 3. Better Sketching and Inpainting 🎨
+
+We've made a lot of changes to our Image component so that it can support better sketching and inpainting.
+
+Now supports:
+
+- A standalone black-and-white sketch
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Sketchpad(), gr.Image())
+demo.launch()
+```
+
+![bw](https://user-images.githubusercontent.com/9021060/192410264-b08632b5-7b2a-4f86-afb0-5760e7b474cf.gif)
+
+- A standalone color sketch
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Paint(), gr.Image())
+demo.launch()
+```
+
+![color-sketch](https://user-images.githubusercontent.com/9021060/192410500-3c8c3e64-a5fd-4df2-a991-f0a5cef93728.gif)
+
+- An uploadable image with black-and-white or color sketching
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Image(source='upload', tool='color-sketch'), gr.Image()) # for black and white, tool = 'sketch'
+demo.launch()
+```
+
+![sketch-new](https://user-images.githubusercontent.com/9021060/192402422-e53cb7b6-024e-448c-87eb-d6a35a63c476.gif)
+
+- Webcam with black-and-white or color sketching
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x: x, gr.Image(source='webcam', tool='color-sketch'), gr.Image()) # for black and white, tool = 'sketch'
+demo.launch()
+```
+
+![webcam-sketch](https://user-images.githubusercontent.com/9021060/192410820-0ffaf324-776e-4e1f-9de6-0fdbbf4940fa.gif)
+
+As well as other fixes
+
+### Bug Fixes:
+
+1. Fix bug where max concurrency count is not respected in queue by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2286](https://github.com/gradio-app/gradio/pull/2286)
+2. fix : queue could be blocked by [@SkyTNT](https://github.com/SkyTNT) in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+3. Supports `gr.update()` in example caching by [@abidlabs](https://github.com/abidlabs) in [PR 2309](https://github.com/gradio-app/gradio/pull/2309)
+4. Clipboard fix for iframes by [@abidlabs](https://github.com/abidlabs) in [PR 2321](https://github.com/gradio-app/gradio/pull/2321)
+5. Fix: Dataframe column headers are reset when you add a new column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2318](https://github.com/gradio-app/gradio/pull/2318)
+6. Added support for URLs for Video, Audio, and Image by [@abidlabs](https://github.com/abidlabs) in [PR 2256](https://github.com/gradio-app/gradio/pull/2256)
+7. Add documentation about how to create and use the Gradio FastAPI app by [@abidlabs](https://github.com/abidlabs) in [PR 2263](https://github.com/gradio-app/gradio/pull/2263)
+
+### Documentation Changes:
+
+1. Adding a Playground Tab to the Website by [@aliabd](https://github.com/aliabd) in [PR 1860](https://github.com/gradio-app/gradio/pull/1860)
+2. Gradio for Tabular Data Science Workflows Guide by [@merveenoyan](https://github.com/merveenoyan) in [PR 2199](https://github.com/gradio-app/gradio/pull/2199)
+3. Promotes `postprocess` and `preprocess` to documented parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2293](https://github.com/gradio-app/gradio/pull/2293)
+4. Update 2)key_features.md by [@voidxd](https://github.com/voidxd) in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+5. Add docs to blocks context postprocessing function by [@Ian-GL](https://github.com/Ian-GL) in [PR 2332](https://github.com/gradio-app/gradio/pull/2332)
+
+### Testing and Infrastructure Changes
+
+1. Website fixes and refactoring by [@aliabd](https://github.com/aliabd) in [PR 2280](https://github.com/gradio-app/gradio/pull/2280)
+2. Don't deploy to spaces on release by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2313](https://github.com/gradio-app/gradio/pull/2313)
+
+### Full Changelog:
+
+- Website fixes and refactoring by [@aliabd](https://github.com/aliabd) in [PR 2280](https://github.com/gradio-app/gradio/pull/2280)
+- Fix bug where max concurrency count is not respected in queue by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2286](https://github.com/gradio-app/gradio/pull/2286)
+- Promotes `postprocess` and `preprocess` to documented parameters by [@abidlabs](https://github.com/abidlabs) in [PR 2293](https://github.com/gradio-app/gradio/pull/2293)
+- Raise warning when trying to cache examples but not all inputs have examples by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2279](https://github.com/gradio-app/gradio/pull/2279)
+- fix : queue could be blocked by [@SkyTNT](https://github.com/SkyTNT) in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+- Don't deploy to spaces on release by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2313](https://github.com/gradio-app/gradio/pull/2313)
+- Supports `gr.update()` in example caching by [@abidlabs](https://github.com/abidlabs) in [PR 2309](https://github.com/gradio-app/gradio/pull/2309)
+- Respect Upstream Queue when loading interfaces/blocks from Spaces by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2294](https://github.com/gradio-app/gradio/pull/2294)
+- Clipboard fix for iframes by [@abidlabs](https://github.com/abidlabs) in [PR 2321](https://github.com/gradio-app/gradio/pull/2321)
+- Sketching + Inpainting Capabilities to Gradio by [@abidlabs](https://github.com/abidlabs) in [PR 2144](https://github.com/gradio-app/gradio/pull/2144)
+- Update 2)key_features.md by [@voidxd](https://github.com/voidxd) in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+- release 3.4b3 by [@abidlabs](https://github.com/abidlabs) in [PR 2328](https://github.com/gradio-app/gradio/pull/2328)
+- Fix: Dataframe column headers are reset when you add a new column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2318](https://github.com/gradio-app/gradio/pull/2318)
+- Start queue when gradio is a sub application by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2319](https://github.com/gradio-app/gradio/pull/2319)
+- Fix Web Tracker Script by [@aliabd](https://github.com/aliabd) in [PR 2308](https://github.com/gradio-app/gradio/pull/2308)
+- Add docs to blocks context postprocessing function by [@Ian-GL](https://github.com/Ian-GL) in [PR 2332](https://github.com/gradio-app/gradio/pull/2332)
+- Fix typo in iterator variable name in run_predict function by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2340](https://github.com/gradio-app/gradio/pull/2340)
+- Add captions to galleries by [@aliabid94](https://github.com/aliabid94) in [PR 2284](https://github.com/gradio-app/gradio/pull/2284)
+- Typeable value on gradio.Slider by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2329](https://github.com/gradio-app/gradio/pull/2329)
+
+### Contributors Shoutout:
+
+- [@SkyTNT](https://github.com/SkyTNT) made their first contribution in [PR 2288](https://github.com/gradio-app/gradio/pull/2288)
+- [@voidxd](https://github.com/voidxd) made their first contribution in [PR 2326](https://github.com/gradio-app/gradio/pull/2326)
+
+## 3.3
+
+### New Features:
+
+###### 1. Iterative Outputs ⏳
+
+You can now create an iterative output simply by having your function return a generator!
+
+Here's (part of) an example that was used to generate the interface below it. [See full code](https://colab.research.google.com/drive/1m9bWS6B82CT7bw-m4L6AJR8za7fEK7Ov?usp=sharing).
+
+```python
+def predict(steps, seed):
+ generator = torch.manual_seed(seed)
+ for i in range(1,steps):
+ yield pipeline(generator=generator, num_inference_steps=i)["sample"][0]
+```
+
+![example](https://user-images.githubusercontent.com/9021060/189086273-f5e7087d-71fa-4158-90a9-08e84da0421c.mp4)
+
+###### 2. Accordion Layout 🆕
+
+This version of Gradio introduces a new layout component to Blocks: the Accordion. Wrap your elements in a neat, expandable layout that allows users to toggle them as needed.
+
+Usage: ([Read the docs](https://gradio.app/docs/#accordion))
+
+```python
+with gr.Accordion("open up"):
+# components here
+```
+
+![accordion](https://user-images.githubusercontent.com/9021060/189088465-f0ffd7f0-fc6a-42dc-9249-11c5e1e0529b.gif)
+
+###### 3. Skops Integration 📈
+
+Our new integration with [skops](https://huggingface.co/blog/skops) allows you to load tabular classification and regression models directly from the [hub](https://huggingface.co/models).
+
+Here's a classification example showing how quick it is to set up an interface for a [model](https://huggingface.co/scikit-learn/tabular-playground).
+
+```python
+import gradio as gr
+gr.Interface.load("models/scikit-learn/tabular-playground").launch()
+```
+
+![187936493-5c90c01d-a6dd-400f-aa42-833a096156a1](https://user-images.githubusercontent.com/9021060/189090519-328fbcb4-120b-43c8-aa54-d6fccfa6b7e8.png)
+
+### Bug Fixes:
+
+No changes to highlight.
+
+### Documentation Changes:
+
+No changes to highlight.
+
+### Testing and Infrastructure Changes:
+
+No changes to highlight.
+
+### Breaking Changes:
+
+No changes to highlight.
+
+### Full Changelog:
+
+- safari fixes by [@pngwn](https://github.com/pngwn) in [PR 2138](https://github.com/gradio-app/gradio/pull/2138)
+- Fix roundedness and form borders by [@aliabid94](https://github.com/aliabid94) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- Better processing of example data prior to creating dataset component by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- Show error on Connection drops by [@aliabid94](https://github.com/aliabid94) in [PR 2147](https://github.com/gradio-app/gradio/pull/2147)
+- 3.2 release! by [@abidlabs](https://github.com/abidlabs) in [PR 2139](https://github.com/gradio-app/gradio/pull/2139)
+- Fixed Named API Requests by [@abidlabs](https://github.com/abidlabs) in [PR 2151](https://github.com/gradio-app/gradio/pull/2151)
+- Quick Fix: Cannot upload Model3D image after clearing it by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2168](https://github.com/gradio-app/gradio/pull/2168)
+- Fixed misleading log when server_name is '0.0.0.0' by [@lamhoangtung](https://github.com/lamhoangtung) in [PR 2176](https://github.com/gradio-app/gradio/pull/2176)
+- Keep embedded PngInfo metadata by [@cobryan05](https://github.com/cobryan05) in [PR 2170](https://github.com/gradio-app/gradio/pull/2170)
+- Skops integration: Load tabular classification and regression models from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2126](https://github.com/gradio-app/gradio/pull/2126)
+- Respect original filename when cached example files are downloaded by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2145](https://github.com/gradio-app/gradio/pull/2145)
+- Add manual trigger to deploy to pypi by [@abidlabs](https://github.com/abidlabs) in [PR 2192](https://github.com/gradio-app/gradio/pull/2192)
+- Fix bugs with gr.update by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2157](https://github.com/gradio-app/gradio/pull/2157)
+- Make queue per app by [@aliabid94](https://github.com/aliabid94) in [PR 2193](https://github.com/gradio-app/gradio/pull/2193)
+- Preserve Labels In Interpretation Components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2166](https://github.com/gradio-app/gradio/pull/2166)
+- Quick Fix: Multiple file download not working by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2169](https://github.com/gradio-app/gradio/pull/2169)
+- use correct MIME type for js-script file by [@daspartho](https://github.com/daspartho) in [PR 2200](https://github.com/gradio-app/gradio/pull/2200)
+- Add accordion component by [@aliabid94](https://github.com/aliabid94) in [PR 2208](https://github.com/gradio-app/gradio/pull/2208)
+
+### Contributors Shoutout:
+
+- [@lamhoangtung](https://github.com/lamhoangtung) made their first contribution in [PR 2176](https://github.com/gradio-app/gradio/pull/2176)
+- [@cobryan05](https://github.com/cobryan05) made their first contribution in [PR 2170](https://github.com/gradio-app/gradio/pull/2170)
+- [@daspartho](https://github.com/daspartho) made their first contribution in [PR 2200](https://github.com/gradio-app/gradio/pull/2200)
+
+## 3.2
+
+### New Features:
+
+###### 1. Improvements to Queuing 🥇
+
+We've implemented a brand new queuing system based on **web sockets** instead of HTTP long polling. Among other things, this allows us to manage queue sizes better on Hugging Face Spaces. There are also additional queue-related parameters you can add:
+
+- Now supports concurrent workers (parallelization)
+
+```python
+demo = gr.Interface(...)
+demo.queue(concurrency_count=3)
+demo.launch()
+```
+
+- Configure a maximum queue size
+
+```python
+demo = gr.Interface(...)
+demo.queue(max_size=100)
+demo.launch()
+```
+
+- If a user closes their tab / browser, they leave the queue, which means the demo will run faster for everyone else
+
+###### 2. Fixes to Examples
+
+- Dataframe examples will render properly, and look much clearer in the UI: (thanks to PR #2125)
+
+![Screen Shot 2022-08-30 at 8 29 58 PM](https://user-images.githubusercontent.com/9021060/187586561-d915bafb-f968-4966-b9a2-ef41119692b2.png)
+
+- Image and Video thumbnails are cropped to look neater and more uniform: (thanks to PR #2109)
+
+![Screen Shot 2022-08-30 at 8 32 15 PM](https://user-images.githubusercontent.com/9021060/187586890-56e1e4f0-1b84-42d9-a82f-911772c41030.png)
+
+- Other fixes in PR #2131 and #2064 make it easier to design and use Examples
+
+###### 3. Component Fixes 🧱
+
+- Specify the width and height of an image in its style tag (thanks to PR #2133)
+
+```python
+components.Image().style(height=260, width=300)
+```
+
+- Automatic conversion of videos so they are playable in the browser (thanks to PR #2003). Gradio will check if a video's format is playable in the browser and, if it isn't, will automatically convert it to a format that is (mp4).
+- Pass in a json filepath to the Label component (thanks to PR #2083)
+- Randomize the default value of a Slider (thanks to PR #1935)
+
+![slider-random](https://user-images.githubusercontent.com/9021060/187596230-3db9697f-9f4d-42f5-9387-d77573513448.gif)
+
+- Improvements to State in PR #2100
+
+###### 4. Ability to Randomize Input Sliders and Reload Data whenever the Page Loads
+
+- In some cases, you want to be able to show a different set of input data to every user as they load the page app. For example, you might want to randomize the value of a "seed" `Slider` input. Or you might want to show a `Textbox` with the current date. We now supporting passing _functions_ as the default value in input components. When you pass in a function, it gets **re-evaluated** every time someone loads the demo, allowing you to reload / change data for different users.
+
+Here's an example loading the current date time into an input Textbox:
+
+```python
+import gradio as gr
+import datetime
+
+with gr.Blocks() as demo:
+ gr.Textbox(datetime.datetime.now)
+
+demo.launch()
+```
+
+Note that we don't evaluate the function -- `datetime.datetime.now()` -- we pass in the function itself to get this behavior -- `datetime.datetime.now`
+
+Because randomizing the initial value of `Slider` is a common use case, we've added a `randomize` keyword argument you can use to randomize its initial value:
+
+```python
+import gradio as gr
+demo = gr.Interface(lambda x:x, gr.Slider(0, 10, randomize=True), "number")
+demo.launch()
+```
+
+###### 5. New Guide 🖊️
+
+- [Gradio and W&B Integration](https://gradio.app/Gradio_and_Wandb_Integration/)
+
+### Full Changelog:
+
+- Reset components to original state by setting value to None by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2044](https://github.com/gradio-app/gradio/pull/2044)
+- Cleaning up the way data is processed for components by [@abidlabs](https://github.com/abidlabs) in [PR 1967](https://github.com/gradio-app/gradio/pull/1967)
+- version 3.1.8b by [@abidlabs](https://github.com/abidlabs) in [PR 2063](https://github.com/gradio-app/gradio/pull/2063)
+- Wandb guide by [@AK391](https://github.com/AK391) in [PR 1898](https://github.com/gradio-app/gradio/pull/1898)
+- Add a flagging callback to save json files to a hugging face dataset by [@chrisemezue](https://github.com/chrisemezue) in [PR 1821](https://github.com/gradio-app/gradio/pull/1821)
+- Add data science demos to landing page by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2067](https://github.com/gradio-app/gradio/pull/2067)
+- Hide time series + xgboost demos by default by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2079](https://github.com/gradio-app/gradio/pull/2079)
+- Encourage people to keep trying when queue full by [@apolinario](https://github.com/apolinario) in [PR 2076](https://github.com/gradio-app/gradio/pull/2076)
+- Updated our analytics on creation of Blocks/Interface by [@abidlabs](https://github.com/abidlabs) in [PR 2082](https://github.com/gradio-app/gradio/pull/2082)
+- `Label` component now accepts file paths to `.json` files by [@abidlabs](https://github.com/abidlabs) in [PR 2083](https://github.com/gradio-app/gradio/pull/2083)
+- Fix issues related to demos in Spaces by [@abidlabs](https://github.com/abidlabs) in [PR 2086](https://github.com/gradio-app/gradio/pull/2086)
+- Fix TimeSeries examples not properly displayed in UI by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2064](https://github.com/gradio-app/gradio/pull/2064)
+- Fix infinite requests when doing tab item select by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2070](https://github.com/gradio-app/gradio/pull/2070)
+- Accept deprecated `file` route as well by [@abidlabs](https://github.com/abidlabs) in [PR 2099](https://github.com/gradio-app/gradio/pull/2099)
+- Allow frontend method execution on Block.load event by [@codedealer](https://github.com/codedealer) in [PR 2108](https://github.com/gradio-app/gradio/pull/2108)
+- Improvements to `State` by [@abidlabs](https://github.com/abidlabs) in [PR 2100](https://github.com/gradio-app/gradio/pull/2100)
+- Catch IndexError, KeyError in video_is_playable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2113](https://github.com/gradio-app/gradio/pull/2113)
+- Fix: Download button does not respect the filepath returned by the function by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 2073](https://github.com/gradio-app/gradio/pull/2073)
+- Refactoring Layout: Adding column widths, forms, and more. by [@aliabid94](https://github.com/aliabid94) in [PR 2097](https://github.com/gradio-app/gradio/pull/2097)
+- Update CONTRIBUTING.md by [@abidlabs](https://github.com/abidlabs) in [PR 2118](https://github.com/gradio-app/gradio/pull/2118)
+- 2092 df ex by [@pngwn](https://github.com/pngwn) in [PR 2125](https://github.com/gradio-app/gradio/pull/2125)
+- feat(samples table/gallery): Crop thumbs to square by [@ronvoluted](https://github.com/ronvoluted) in [PR 2109](https://github.com/gradio-app/gradio/pull/2109)
+- Some enhancements to `gr.Examples` by [@abidlabs](https://github.com/abidlabs) in [PR 2131](https://github.com/gradio-app/gradio/pull/2131)
+- Image size fix by [@aliabid94](https://github.com/aliabid94) in [PR 2133](https://github.com/gradio-app/gradio/pull/2133)
+
+### Contributors Shoutout:
+
+- [@chrisemezue](https://github.com/chrisemezue) made their first contribution in [PR 1821](https://github.com/gradio-app/gradio/pull/1821)
+- [@apolinario](https://github.com/apolinario) made their first contribution in [PR 2076](https://github.com/gradio-app/gradio/pull/2076)
+- [@codedealer](https://github.com/codedealer) made their first contribution in [PR 2108](https://github.com/gradio-app/gradio/pull/2108)
+
+## 3.1
+
+### New Features:
+
+###### 1. Embedding Demos on Any Website 💻
+
+With PR #1444, Gradio is now distributed as a web component. This means demos can be natively embedded on websites. You'll just need to add two lines: one to load the gradio javascript, and one to link to the demos backend.
+
+Here's a simple example that embeds the demo from a Hugging Face space:
+
+```html
+
+
+```
+
+But you can also embed demos that are running anywhere, you just need to link the demo to `src` instead of `space`. In fact, all the demos on the gradio website are embedded this way:
+
+
+
+Read more in the [Embedding Gradio Demos](https://gradio.app/embedding_gradio_demos) guide.
+
+###### 2. Reload Mode 👨💻
+
+Reload mode helps developers create gradio demos faster by automatically reloading the demo whenever the code changes. It can support development on Python IDEs (VS Code, PyCharm, etc), the terminal, as well as Jupyter notebooks.
+
+If your demo code is in a script named `app.py`, instead of running `python app.py` you can now run `gradio app.py` and that will launch the demo in reload mode:
+
+```bash
+Launching in reload mode on: http://127.0.0.1:7860 (Press CTRL+C to quit)
+Watching...
+WARNING: The --reload flag should not be used in production on Windows.
+```
+
+If you're working from a Jupyter or Colab Notebook, use these magic commands instead: `%load_ext gradio` when you import gradio, and `%%blocks` in the top of the cell with the demo code. Here's an example that shows how much faster the development becomes:
+
+![Blocks](https://user-images.githubusercontent.com/9021060/178986488-ed378cc8-5141-4330-ba41-672b676863d0.gif)
+
+###### 3. Inpainting Support on `gr.Image()` 🎨
+
+We updated the Image component to add support for inpainting demos. It works by adding `tool="sketch"` as a parameter, that passes both an image and a sketchable mask to your prediction function.
+
+Here's an example from the [LAMA space](https://huggingface.co/spaces/akhaliq/lama):
+
+![FXApVlFVsAALSD-](https://user-images.githubusercontent.com/9021060/178989479-549867c8-7fb0-436a-a97d-1e91c9f5e611.jpeg)
+
+###### 4. Markdown and HTML support in Dataframes 🔢
+
+We upgraded the Dataframe component in PR #1684 to support rendering Markdown and HTML inside the cells.
+
+This means you can build Dataframes that look like the following:
+
+![image (8)](https://user-images.githubusercontent.com/9021060/178991233-41cb07a5-e7a3-433e-89b8-319bc78eb9c2.png)
+
+###### 5. `gr.Examples()` for Blocks 🧱
+
+We've added the `gr.Examples` component helper to allow you to add examples to any Blocks demo. This class is a wrapper over the `gr.Dataset` component.
+
+
+
+gr.Examples takes two required parameters:
+
+- `examples` which takes in a nested list
+- `inputs` which takes in a component or list of components
+
+You can read more in the [Examples docs](https://gradio.app/docs/#examples) or the [Adding Examples to your Demos guide](https://gradio.app/adding_examples_to_your_app/).
+
+###### 6. Fixes to Audio Streaming
+
+With [PR 1828](https://github.com/gradio-app/gradio/pull/1828) we now hide the status loading animation, as well as remove the echo in streaming. Check out the [stream_audio](https://github.com/gradio-app/gradio/blob/main/demo/stream_audio/run.py) demo for more or read through our [Real Time Speech Recognition](https://gradio.app/real_time_speech_recognition/) guide.
+
+
+
+### Full Changelog:
+
+- File component: list multiple files and allow for download #1446 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1681](https://github.com/gradio-app/gradio/pull/1681)
+- Add ColorPicker to docs by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1768](https://github.com/gradio-app/gradio/pull/1768)
+- Mock out requests in TestRequest unit tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1794](https://github.com/gradio-app/gradio/pull/1794)
+- Add requirements.txt and test_files to source dist by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1817](https://github.com/gradio-app/gradio/pull/1817)
+- refactor: f-string for tunneling.py by [@nhankiet](https://github.com/nhankiet) in [PR 1819](https://github.com/gradio-app/gradio/pull/1819)
+- Miscellaneous formatting improvements to website by [@aliabd](https://github.com/aliabd) in [PR 1754](https://github.com/gradio-app/gradio/pull/1754)
+- `integrate()` method moved to `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 1776](https://github.com/gradio-app/gradio/pull/1776)
+- Add python-3.7 tests by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1818](https://github.com/gradio-app/gradio/pull/1818)
+- Copy test dir in website dockers by [@aliabd](https://github.com/aliabd) in [PR 1827](https://github.com/gradio-app/gradio/pull/1827)
+- Add info to docs on how to set default values for components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1788](https://github.com/gradio-app/gradio/pull/1788)
+- Embedding Components on Docs by [@aliabd](https://github.com/aliabd) in [PR 1726](https://github.com/gradio-app/gradio/pull/1726)
+- Remove usage of deprecated gr.inputs and gr.outputs from website by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1796](https://github.com/gradio-app/gradio/pull/1796)
+- Some cleanups to the docs page by [@abidlabs](https://github.com/abidlabs) in [PR 1822](https://github.com/gradio-app/gradio/pull/1822)
+
+### Contributors Shoutout:
+
+- [@nhankiet](https://github.com/nhankiet) made their first contribution in [PR 1819](https://github.com/gradio-app/gradio/pull/1819)
+
+## 3.0
+
+###### 🔥 Gradio 3.0 is the biggest update to the library, ever.
+
+### New Features:
+
+###### 1. Blocks 🧱
+
+Blocks is a new, low-level API that allows you to have full control over the data flows and layout of your application. It allows you to build very complex, multi-step applications. For example, you might want to:
+
+- Group together related demos as multiple tabs in one web app
+- Change the layout of your demo instead of just having all of the inputs on the left and outputs on the right
+- Have multi-step interfaces, in which the output of one model becomes the input to the next model, or have more flexible data flows in general
+- Change a component's properties (for example, the choices in a Dropdown) or its visibility based on user input
+
+Here's a simple example that creates the demo below it:
+
+```python
+import gradio as gr
+
+def update(name):
+ return f"Welcome to Gradio, {name}!"
+
+demo = gr.Blocks()
+
+with demo:
+ gr.Markdown(
+ """
+ # Hello World!
+ Start typing below to see the output.
+ """)
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+
+ inp.change(fn=update,
+ inputs=inp,
+ outputs=out)
+
+demo.launch()
+```
+
+![hello-blocks](https://user-images.githubusercontent.com/9021060/168684108-78cbd24b-e6bd-4a04-a8d9-20d535203434.gif)
+
+Read our [Introduction to Blocks](http://gradio.app/introduction_to_blocks/) guide for more, and join the 🎈 [Gradio Blocks Party](https://huggingface.co/spaces/Gradio-Blocks/README)!
+
+###### 2. Our Revamped Design 🎨
+
+We've upgraded our design across the entire library: from components, and layouts all the way to dark mode.
+
+![kitchen_sink](https://user-images.githubusercontent.com/9021060/168686333-7a6e3096-3e23-4309-abf2-5cd7736e0463.gif)
+
+###### 3. A New Website 💻
+
+We've upgraded [gradio.app](https://gradio.app) to make it cleaner, faster and easier to use. Our docs now come with components and demos embedded directly on the page. So you can quickly get up to speed with what you're looking for.
+
+![website](https://user-images.githubusercontent.com/9021060/168687191-10d6a3bd-101f-423a-8193-48f47a5e077d.gif)
+
+###### 4. New Components: Model3D, Dataset, and More..
+
+We've introduced a lot of new components in `3.0`, including `Model3D`, `Dataset`, `Markdown`, `Button` and `Gallery`. You can find all the components and play around with them [here](https://gradio.app/docs/#components).
+
+![Model3d](https://user-images.githubusercontent.com/9021060/168689062-6ad77151-8cc5-467d-916c-f7c78e52ec0c.gif)
+
+### Full Changelog:
+
+- Gradio dash fe by [@pngwn](https://github.com/pngwn) in [PR 807](https://github.com/gradio-app/gradio/pull/807)
+- Blocks components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 765](https://github.com/gradio-app/gradio/pull/765)
+- Blocks components V2 by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 843](https://github.com/gradio-app/gradio/pull/843)
+- Blocks-Backend-Events by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 844](https://github.com/gradio-app/gradio/pull/844)
+- Interfaces from Blocks by [@aliabid94](https://github.com/aliabid94) in [PR 849](https://github.com/gradio-app/gradio/pull/849)
+- Blocks dev by [@aliabid94](https://github.com/aliabid94) in [PR 853](https://github.com/gradio-app/gradio/pull/853)
+- Started updating demos to use the new `gradio.components` syntax by [@abidlabs](https://github.com/abidlabs) in [PR 848](https://github.com/gradio-app/gradio/pull/848)
+- add test infra + add browser tests to CI by [@pngwn](https://github.com/pngwn) in [PR 852](https://github.com/gradio-app/gradio/pull/852)
+- 854 textbox by [@pngwn](https://github.com/pngwn) in [PR 859](https://github.com/gradio-app/gradio/pull/859)
+- Getting old Python unit tests to pass on `blocks-dev` by [@abidlabs](https://github.com/abidlabs) in [PR 861](https://github.com/gradio-app/gradio/pull/861)
+- initialise chatbot with empty array of messages by [@pngwn](https://github.com/pngwn) in [PR 867](https://github.com/gradio-app/gradio/pull/867)
+- add test for output to input by [@pngwn](https://github.com/pngwn) in [PR 866](https://github.com/gradio-app/gradio/pull/866)
+- More Interface -> Blocks features by [@aliabid94](https://github.com/aliabid94) in [PR 864](https://github.com/gradio-app/gradio/pull/864)
+- Fixing external.py in blocks-dev to reflect the new HF Spaces paths by [@abidlabs](https://github.com/abidlabs) in [PR 879](https://github.com/gradio-app/gradio/pull/879)
+- backend_default_value_refactoring by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 871](https://github.com/gradio-app/gradio/pull/871)
+- fix default_value by [@pngwn](https://github.com/pngwn) in [PR 869](https://github.com/gradio-app/gradio/pull/869)
+- fix buttons by [@aliabid94](https://github.com/aliabid94) in [PR 883](https://github.com/gradio-app/gradio/pull/883)
+- Checking and updating more demos to use 3.0 syntax by [@abidlabs](https://github.com/abidlabs) in [PR 892](https://github.com/gradio-app/gradio/pull/892)
+- Blocks Tests by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 902](https://github.com/gradio-app/gradio/pull/902)
+- Interface fix by [@pngwn](https://github.com/pngwn) in [PR 901](https://github.com/gradio-app/gradio/pull/901)
+- Quick fix: Issue 893 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 907](https://github.com/gradio-app/gradio/pull/907)
+- 3d Image Component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 775](https://github.com/gradio-app/gradio/pull/775)
+- fix endpoint url in prod by [@pngwn](https://github.com/pngwn) in [PR 911](https://github.com/gradio-app/gradio/pull/911)
+- rename Model3d to Image3D by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 912](https://github.com/gradio-app/gradio/pull/912)
+- update pypi to 2.9.1 by [@abidlabs](https://github.com/abidlabs) in [PR 916](https://github.com/gradio-app/gradio/pull/916)
+- blocks-with-fix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 917](https://github.com/gradio-app/gradio/pull/917)
+- Restore Interpretation, Live, Auth, Queueing by [@aliabid94](https://github.com/aliabid94) in [PR 915](https://github.com/gradio-app/gradio/pull/915)
+- Allow `Blocks` instances to be used like a `Block` in other `Blocks` by [@abidlabs](https://github.com/abidlabs) in [PR 919](https://github.com/gradio-app/gradio/pull/919)
+- Redesign 1 by [@pngwn](https://github.com/pngwn) in [PR 918](https://github.com/gradio-app/gradio/pull/918)
+- blocks-components-tests by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 904](https://github.com/gradio-app/gradio/pull/904)
+- fix unit + browser tests by [@pngwn](https://github.com/pngwn) in [PR 926](https://github.com/gradio-app/gradio/pull/926)
+- blocks-move-test-data by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 927](https://github.com/gradio-app/gradio/pull/927)
+- remove debounce from form inputs by [@pngwn](https://github.com/pngwn) in [PR 932](https://github.com/gradio-app/gradio/pull/932)
+- reimplement webcam video by [@pngwn](https://github.com/pngwn) in [PR 928](https://github.com/gradio-app/gradio/pull/928)
+- blocks-move-test-data by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 941](https://github.com/gradio-app/gradio/pull/941)
+- allow audio components to take a string value by [@pngwn](https://github.com/pngwn) in [PR 930](https://github.com/gradio-app/gradio/pull/930)
+- static mode for textbox by [@pngwn](https://github.com/pngwn) in [PR 929](https://github.com/gradio-app/gradio/pull/929)
+- fix file upload text by [@pngwn](https://github.com/pngwn) in [PR 931](https://github.com/gradio-app/gradio/pull/931)
+- tabbed-interface-rewritten by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 958](https://github.com/gradio-app/gradio/pull/958)
+- Gan demo fix by [@abidlabs](https://github.com/abidlabs) in [PR 965](https://github.com/gradio-app/gradio/pull/965)
+- Blocks analytics by [@abidlabs](https://github.com/abidlabs) in [PR 947](https://github.com/gradio-app/gradio/pull/947)
+- Blocks page load by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 963](https://github.com/gradio-app/gradio/pull/963)
+- add frontend for page load events by [@pngwn](https://github.com/pngwn) in [PR 967](https://github.com/gradio-app/gradio/pull/967)
+- fix i18n and some tweaks by [@pngwn](https://github.com/pngwn) in [PR 966](https://github.com/gradio-app/gradio/pull/966)
+- add jinja2 to reqs by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 969](https://github.com/gradio-app/gradio/pull/969)
+- Cleaning up `Launchable()` by [@abidlabs](https://github.com/abidlabs) in [PR 968](https://github.com/gradio-app/gradio/pull/968)
+- Fix #944 by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 971](https://github.com/gradio-app/gradio/pull/971)
+- New Blocks Demo: neural instrument cloning by [@abidlabs](https://github.com/abidlabs) in [PR 975](https://github.com/gradio-app/gradio/pull/975)
+- Add huggingface_hub client library by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 973](https://github.com/gradio-app/gradio/pull/973)
+- State and variables by [@aliabid94](https://github.com/aliabid94) in [PR 977](https://github.com/gradio-app/gradio/pull/977)
+- update-components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 986](https://github.com/gradio-app/gradio/pull/986)
+- ensure dataframe updates as expected by [@pngwn](https://github.com/pngwn) in [PR 981](https://github.com/gradio-app/gradio/pull/981)
+- test-guideline by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 990](https://github.com/gradio-app/gradio/pull/990)
+- Issue #785: add footer by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 972](https://github.com/gradio-app/gradio/pull/972)
+- indentation fix by [@abidlabs](https://github.com/abidlabs) in [PR 993](https://github.com/gradio-app/gradio/pull/993)
+- missing quote by [@aliabd](https://github.com/aliabd) in [PR 996](https://github.com/gradio-app/gradio/pull/996)
+- added interactive parameter to components by [@abidlabs](https://github.com/abidlabs) in [PR 992](https://github.com/gradio-app/gradio/pull/992)
+- custom-components by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 985](https://github.com/gradio-app/gradio/pull/985)
+- Refactor component shortcuts by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 995](https://github.com/gradio-app/gradio/pull/995)
+- Plot Component by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 805](https://github.com/gradio-app/gradio/pull/805)
+- updated PyPi version to 2.9.2 by [@abidlabs](https://github.com/abidlabs) in [PR 1002](https://github.com/gradio-app/gradio/pull/1002)
+- Release 2.9.3 by [@abidlabs](https://github.com/abidlabs) in [PR 1003](https://github.com/gradio-app/gradio/pull/1003)
+- Image3D Examples Fix by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1001](https://github.com/gradio-app/gradio/pull/1001)
+- release 2.9.4 by [@abidlabs](https://github.com/abidlabs) in [PR 1006](https://github.com/gradio-app/gradio/pull/1006)
+- templates import hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1008](https://github.com/gradio-app/gradio/pull/1008)
+- Progress indicator bar by [@aliabid94](https://github.com/aliabid94) in [PR 997](https://github.com/gradio-app/gradio/pull/997)
+- Fixed image input for absolute path by [@JefferyChiang](https://github.com/JefferyChiang) in [PR 1004](https://github.com/gradio-app/gradio/pull/1004)
+- Model3D + Plot Components by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1010](https://github.com/gradio-app/gradio/pull/1010)
+- Gradio Guides: Creating CryptoPunks with GANs by [@NimaBoscarino](https://github.com/NimaBoscarino) in [PR 1000](https://github.com/gradio-app/gradio/pull/1000)
+- [BIG PR] Gradio blocks & redesigned components by [@abidlabs](https://github.com/abidlabs) in [PR 880](https://github.com/gradio-app/gradio/pull/880)
+- fixed failing test on main by [@abidlabs](https://github.com/abidlabs) in [PR 1023](https://github.com/gradio-app/gradio/pull/1023)
+- Use smaller ASR model in external test by [@abidlabs](https://github.com/abidlabs) in [PR 1024](https://github.com/gradio-app/gradio/pull/1024)
+- updated PyPi version to 2.9.0b by [@abidlabs](https://github.com/abidlabs) in [PR 1026](https://github.com/gradio-app/gradio/pull/1026)
+- Fixing import issues so that the package successfully installs on colab notebooks by [@abidlabs](https://github.com/abidlabs) in [PR 1027](https://github.com/gradio-app/gradio/pull/1027)
+- Update website tracker slackbot by [@aliabd](https://github.com/aliabd) in [PR 1037](https://github.com/gradio-app/gradio/pull/1037)
+- textbox-autoheight by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1009](https://github.com/gradio-app/gradio/pull/1009)
+- Model3D Examples fixes by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1035](https://github.com/gradio-app/gradio/pull/1035)
+- GAN Gradio Guide: Adjustments to iframe heights by [@NimaBoscarino](https://github.com/NimaBoscarino) in [PR 1042](https://github.com/gradio-app/gradio/pull/1042)
+- added better default labels to form components by [@abidlabs](https://github.com/abidlabs) in [PR 1040](https://github.com/gradio-app/gradio/pull/1040)
+- Slackbot web tracker fix by [@aliabd](https://github.com/aliabd) in [PR 1043](https://github.com/gradio-app/gradio/pull/1043)
+- Plot fixes by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1044](https://github.com/gradio-app/gradio/pull/1044)
+- Small fixes to the demos by [@abidlabs](https://github.com/abidlabs) in [PR 1030](https://github.com/gradio-app/gradio/pull/1030)
+- fixing demo issue with website by [@aliabd](https://github.com/aliabd) in [PR 1047](https://github.com/gradio-app/gradio/pull/1047)
+- [hotfix] HighlightedText by [@aliabid94](https://github.com/aliabid94) in [PR 1046](https://github.com/gradio-app/gradio/pull/1046)
+- Update text by [@ronvoluted](https://github.com/ronvoluted) in [PR 1050](https://github.com/gradio-app/gradio/pull/1050)
+- Update CONTRIBUTING.md by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1052](https://github.com/gradio-app/gradio/pull/1052)
+- fix(ui): Increase contrast for footer by [@ronvoluted](https://github.com/ronvoluted) in [PR 1048](https://github.com/gradio-app/gradio/pull/1048)
+- UI design update by [@gary149](https://github.com/gary149) in [PR 1041](https://github.com/gradio-app/gradio/pull/1041)
+- updated PyPi version to 2.9.0b8 by [@abidlabs](https://github.com/abidlabs) in [PR 1059](https://github.com/gradio-app/gradio/pull/1059)
+- Running, testing, and fixing demos by [@abidlabs](https://github.com/abidlabs) in [PR 1060](https://github.com/gradio-app/gradio/pull/1060)
+- Form layout by [@pngwn](https://github.com/pngwn) in [PR 1054](https://github.com/gradio-app/gradio/pull/1054)
+- inputless-interfaces by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1038](https://github.com/gradio-app/gradio/pull/1038)
+- Update PULL_REQUEST_TEMPLATE.md by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1068](https://github.com/gradio-app/gradio/pull/1068)
+- Upgrading node memory to 4gb in website Docker by [@aliabd](https://github.com/aliabd) in [PR 1069](https://github.com/gradio-app/gradio/pull/1069)
+- Website reload error by [@aliabd](https://github.com/aliabd) in [PR 1079](https://github.com/gradio-app/gradio/pull/1079)
+- fixed favicon issue by [@abidlabs](https://github.com/abidlabs) in [PR 1064](https://github.com/gradio-app/gradio/pull/1064)
+- remove-queue-from-events by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1056](https://github.com/gradio-app/gradio/pull/1056)
+- Enable vertex colors for OBJs files by [@radames](https://github.com/radames) in [PR 1074](https://github.com/gradio-app/gradio/pull/1074)
+- Dark text by [@ronvoluted](https://github.com/ronvoluted) in [PR 1049](https://github.com/gradio-app/gradio/pull/1049)
+- Scroll to output by [@pngwn](https://github.com/pngwn) in [PR 1077](https://github.com/gradio-app/gradio/pull/1077)
+- Explicitly list pnpm version 6 in contributing guide by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1085](https://github.com/gradio-app/gradio/pull/1085)
+- hotfix for encrypt issue by [@abidlabs](https://github.com/abidlabs) in [PR 1096](https://github.com/gradio-app/gradio/pull/1096)
+- Release 2.9b9 by [@abidlabs](https://github.com/abidlabs) in [PR 1098](https://github.com/gradio-app/gradio/pull/1098)
+- tweak node circleci settings by [@pngwn](https://github.com/pngwn) in [PR 1091](https://github.com/gradio-app/gradio/pull/1091)
+- Website Reload Error by [@aliabd](https://github.com/aliabd) in [PR 1099](https://github.com/gradio-app/gradio/pull/1099)
+- Website Reload: README in demos docker by [@aliabd](https://github.com/aliabd) in [PR 1100](https://github.com/gradio-app/gradio/pull/1100)
+- Flagging fixes by [@abidlabs](https://github.com/abidlabs) in [PR 1081](https://github.com/gradio-app/gradio/pull/1081)
+- Backend for optional labels by [@abidlabs](https://github.com/abidlabs) in [PR 1080](https://github.com/gradio-app/gradio/pull/1080)
+- Optional labels fe by [@pngwn](https://github.com/pngwn) in [PR 1105](https://github.com/gradio-app/gradio/pull/1105)
+- clean-deprecated-parameters by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1090](https://github.com/gradio-app/gradio/pull/1090)
+- Blocks rendering fix by [@abidlabs](https://github.com/abidlabs) in [PR 1102](https://github.com/gradio-app/gradio/pull/1102)
+- Redos #1106 by [@abidlabs](https://github.com/abidlabs) in [PR 1112](https://github.com/gradio-app/gradio/pull/1112)
+- Interface types: handle input-only, output-only, and unified interfaces by [@abidlabs](https://github.com/abidlabs) in [PR 1108](https://github.com/gradio-app/gradio/pull/1108)
+- Hotfix + New pypi release 2.9b11 by [@abidlabs](https://github.com/abidlabs) in [PR 1118](https://github.com/gradio-app/gradio/pull/1118)
+- issue-checkbox by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1122](https://github.com/gradio-app/gradio/pull/1122)
+- issue-checkbox-hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1127](https://github.com/gradio-app/gradio/pull/1127)
+- Fix demos in website by [@aliabd](https://github.com/aliabd) in [PR 1130](https://github.com/gradio-app/gradio/pull/1130)
+- Guide for Gradio ONNX model zoo on Huggingface by [@AK391](https://github.com/AK391) in [PR 1073](https://github.com/gradio-app/gradio/pull/1073)
+- ONNX guide fixes by [@aliabd](https://github.com/aliabd) in [PR 1131](https://github.com/gradio-app/gradio/pull/1131)
+- Stacked form inputs css by [@gary149](https://github.com/gary149) in [PR 1134](https://github.com/gradio-app/gradio/pull/1134)
+- made default value in textbox empty string by [@abidlabs](https://github.com/abidlabs) in [PR 1135](https://github.com/gradio-app/gradio/pull/1135)
+- Examples UI by [@gary149](https://github.com/gary149) in [PR 1121](https://github.com/gradio-app/gradio/pull/1121)
+- Chatbot custom color support by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1092](https://github.com/gradio-app/gradio/pull/1092)
+- highlighted text colors by [@pngwn](https://github.com/pngwn) in [PR 1119](https://github.com/gradio-app/gradio/pull/1119)
+- pin to pnpm 6 for now by [@pngwn](https://github.com/pngwn) in [PR 1147](https://github.com/gradio-app/gradio/pull/1147)
+- Restore queue in Blocks by [@aliabid94](https://github.com/aliabid94) in [PR 1137](https://github.com/gradio-app/gradio/pull/1137)
+- add select event for tabitems by [@pngwn](https://github.com/pngwn) in [PR 1154](https://github.com/gradio-app/gradio/pull/1154)
+- max_lines + autoheight for textbox by [@pngwn](https://github.com/pngwn) in [PR 1153](https://github.com/gradio-app/gradio/pull/1153)
+- use color palette for chatbot by [@pngwn](https://github.com/pngwn) in [PR 1152](https://github.com/gradio-app/gradio/pull/1152)
+- Timeseries improvements by [@pngwn](https://github.com/pngwn) in [PR 1149](https://github.com/gradio-app/gradio/pull/1149)
+- move styling for interface panels to frontend by [@pngwn](https://github.com/pngwn) in [PR 1146](https://github.com/gradio-app/gradio/pull/1146)
+- html tweaks by [@pngwn](https://github.com/pngwn) in [PR 1145](https://github.com/gradio-app/gradio/pull/1145)
+- Issue #768: Support passing none to resize and crop image by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1144](https://github.com/gradio-app/gradio/pull/1144)
+- image gallery component + img css by [@aliabid94](https://github.com/aliabid94) in [PR 1140](https://github.com/gradio-app/gradio/pull/1140)
+- networking tweak by [@abidlabs](https://github.com/abidlabs) in [PR 1143](https://github.com/gradio-app/gradio/pull/1143)
+- Allow enabling queue per event listener by [@aliabid94](https://github.com/aliabid94) in [PR 1155](https://github.com/gradio-app/gradio/pull/1155)
+- config hotfix and v. 2.9b23 by [@abidlabs](https://github.com/abidlabs) in [PR 1158](https://github.com/gradio-app/gradio/pull/1158)
+- Custom JS calls by [@aliabid94](https://github.com/aliabid94) in [PR 1082](https://github.com/gradio-app/gradio/pull/1082)
+- Small fixes: queue default fix, ffmpeg installation message by [@abidlabs](https://github.com/abidlabs) in [PR 1159](https://github.com/gradio-app/gradio/pull/1159)
+- formatting by [@abidlabs](https://github.com/abidlabs) in [PR 1161](https://github.com/gradio-app/gradio/pull/1161)
+- enable flex grow for gr-box by [@radames](https://github.com/radames) in [PR 1165](https://github.com/gradio-app/gradio/pull/1165)
+- 1148 loading by [@pngwn](https://github.com/pngwn) in [PR 1164](https://github.com/gradio-app/gradio/pull/1164)
+- Put enable_queue kwarg back in launch() by [@aliabid94](https://github.com/aliabid94) in [PR 1167](https://github.com/gradio-app/gradio/pull/1167)
+- A few small fixes by [@abidlabs](https://github.com/abidlabs) in [PR 1171](https://github.com/gradio-app/gradio/pull/1171)
+- Hotfix for dropdown component by [@abidlabs](https://github.com/abidlabs) in [PR 1172](https://github.com/gradio-app/gradio/pull/1172)
+- use secondary buttons in interface by [@pngwn](https://github.com/pngwn) in [PR 1173](https://github.com/gradio-app/gradio/pull/1173)
+- 1183 component height by [@pngwn](https://github.com/pngwn) in [PR 1185](https://github.com/gradio-app/gradio/pull/1185)
+- 962 dataframe by [@pngwn](https://github.com/pngwn) in [PR 1186](https://github.com/gradio-app/gradio/pull/1186)
+- update-contributing by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1188](https://github.com/gradio-app/gradio/pull/1188)
+- Table tweaks by [@pngwn](https://github.com/pngwn) in [PR 1195](https://github.com/gradio-app/gradio/pull/1195)
+- wrap tab content in column by [@pngwn](https://github.com/pngwn) in [PR 1200](https://github.com/gradio-app/gradio/pull/1200)
+- WIP: Add dark mode support by [@gary149](https://github.com/gary149) in [PR 1187](https://github.com/gradio-app/gradio/pull/1187)
+- Restored /api/predict/ endpoint for Interfaces by [@abidlabs](https://github.com/abidlabs) in [PR 1199](https://github.com/gradio-app/gradio/pull/1199)
+- hltext-label by [@pngwn](https://github.com/pngwn) in [PR 1204](https://github.com/gradio-app/gradio/pull/1204)
+- add copy functionality to json by [@pngwn](https://github.com/pngwn) in [PR 1205](https://github.com/gradio-app/gradio/pull/1205)
+- Update component config by [@aliabid94](https://github.com/aliabid94) in [PR 1089](https://github.com/gradio-app/gradio/pull/1089)
+- fix placeholder prompt by [@pngwn](https://github.com/pngwn) in [PR 1215](https://github.com/gradio-app/gradio/pull/1215)
+- ensure webcam video value is propagated correctly by [@pngwn](https://github.com/pngwn) in [PR 1218](https://github.com/gradio-app/gradio/pull/1218)
+- Automatic word-break in highlighted text, combine_adjacent support by [@aliabid94](https://github.com/aliabid94) in [PR 1209](https://github.com/gradio-app/gradio/pull/1209)
+- async-function-support by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1190](https://github.com/gradio-app/gradio/pull/1190)
+- Sharing fix for assets by [@aliabid94](https://github.com/aliabid94) in [PR 1208](https://github.com/gradio-app/gradio/pull/1208)
+- Hotfixes for course demos by [@abidlabs](https://github.com/abidlabs) in [PR 1222](https://github.com/gradio-app/gradio/pull/1222)
+- Allow Custom CSS by [@aliabid94](https://github.com/aliabid94) in [PR 1170](https://github.com/gradio-app/gradio/pull/1170)
+- share-hotfix by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1226](https://github.com/gradio-app/gradio/pull/1226)
+- tweaks by [@pngwn](https://github.com/pngwn) in [PR 1229](https://github.com/gradio-app/gradio/pull/1229)
+- white space for class concatenation by [@radames](https://github.com/radames) in [PR 1228](https://github.com/gradio-app/gradio/pull/1228)
+- Tweaks by [@pngwn](https://github.com/pngwn) in [PR 1230](https://github.com/gradio-app/gradio/pull/1230)
+- css tweaks by [@pngwn](https://github.com/pngwn) in [PR 1235](https://github.com/gradio-app/gradio/pull/1235)
+- ensure defaults height match for media inputs by [@pngwn](https://github.com/pngwn) in [PR 1236](https://github.com/gradio-app/gradio/pull/1236)
+- Default Label label value by [@radames](https://github.com/radames) in [PR 1239](https://github.com/gradio-app/gradio/pull/1239)
+- update-shortcut-syntax by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1234](https://github.com/gradio-app/gradio/pull/1234)
+- Update version.txt by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1244](https://github.com/gradio-app/gradio/pull/1244)
+- Layout bugs by [@pngwn](https://github.com/pngwn) in [PR 1246](https://github.com/gradio-app/gradio/pull/1246)
+- Update demo by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1253](https://github.com/gradio-app/gradio/pull/1253)
+- Button default name by [@FarukOzderim](https://github.com/FarukOzderim) in [PR 1243](https://github.com/gradio-app/gradio/pull/1243)
+- Labels spacing by [@gary149](https://github.com/gary149) in [PR 1254](https://github.com/gradio-app/gradio/pull/1254)
+- add global loader for gradio app by [@pngwn](https://github.com/pngwn) in [PR 1251](https://github.com/gradio-app/gradio/pull/1251)
+- ui apis for dalle-mini by [@pngwn](https://github.com/pngwn) in [PR 1258](https://github.com/gradio-app/gradio/pull/1258)
+- Add precision to Number, backend only by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 1125](https://github.com/gradio-app/gradio/pull/1125)
+- Website Design Changes by [@abidlabs](https://github.com/abidlabs) in [PR 1015](https://github.com/gradio-app/gradio/pull/1015)
+- Small fixes for multiple demos compatible with 3.0 by [@radames](https://github.com/radames) in [PR 1257](https://github.com/gradio-app/gradio/pull/1257)
+- Issue #1160: Model 3D component not destroyed correctly by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 1219](https://github.com/gradio-app/gradio/pull/1219)
+- Fixes to components by [@abidlabs](https://github.com/abidlabs) in [PR 1260](https://github.com/gradio-app/gradio/pull/1260)
+- layout docs by [@abidlabs](https://github.com/abidlabs) in [PR 1263](https://github.com/gradio-app/gradio/pull/1263)
+- Static forms by [@pngwn](https://github.com/pngwn) in [PR 1264](https://github.com/gradio-app/gradio/pull/1264)
+- Cdn assets by [@pngwn](https://github.com/pngwn) in [PR 1265](https://github.com/gradio-app/gradio/pull/1265)
+- update logo by [@gary149](https://github.com/gary149) in [PR 1266](https://github.com/gradio-app/gradio/pull/1266)
+- fix slider by [@aliabid94](https://github.com/aliabid94) in [PR 1268](https://github.com/gradio-app/gradio/pull/1268)
+- maybe fix auth in iframes by [@pngwn](https://github.com/pngwn) in [PR 1261](https://github.com/gradio-app/gradio/pull/1261)
+- Improves "Getting Started" guide by [@abidlabs](https://github.com/abidlabs) in [PR 1269](https://github.com/gradio-app/gradio/pull/1269)
+- Add embedded demos to website by [@aliabid94](https://github.com/aliabid94) in [PR 1270](https://github.com/gradio-app/gradio/pull/1270)
+- Label hotfixes by [@abidlabs](https://github.com/abidlabs) in [PR 1281](https://github.com/gradio-app/gradio/pull/1281)
+- General tweaks by [@pngwn](https://github.com/pngwn) in [PR 1276](https://github.com/gradio-app/gradio/pull/1276)
+- only affect links within the document by [@pngwn](https://github.com/pngwn) in [PR 1282](https://github.com/gradio-app/gradio/pull/1282)
+- release 3.0b9 by [@abidlabs](https://github.com/abidlabs) in [PR 1283](https://github.com/gradio-app/gradio/pull/1283)
+- Dm by [@pngwn](https://github.com/pngwn) in [PR 1284](https://github.com/gradio-app/gradio/pull/1284)
+- Website fixes by [@aliabd](https://github.com/aliabd) in [PR 1286](https://github.com/gradio-app/gradio/pull/1286)
+- Create Streamables by [@aliabid94](https://github.com/aliabid94) in [PR 1279](https://github.com/gradio-app/gradio/pull/1279)
+- ensure table works on mobile by [@pngwn](https://github.com/pngwn) in [PR 1277](https://github.com/gradio-app/gradio/pull/1277)
+- changes by [@aliabid94](https://github.com/aliabid94) in [PR 1287](https://github.com/gradio-app/gradio/pull/1287)
+- demo alignment on landing page by [@aliabd](https://github.com/aliabd) in [PR 1288](https://github.com/gradio-app/gradio/pull/1288)
+- New meta img by [@aliabd](https://github.com/aliabd) in [PR 1289](https://github.com/gradio-app/gradio/pull/1289)
+- updated PyPi version to 3.0 by [@abidlabs](https://github.com/abidlabs) in [PR 1290](https://github.com/gradio-app/gradio/pull/1290)
+- Fix site by [@aliabid94](https://github.com/aliabid94) in [PR 1291](https://github.com/gradio-app/gradio/pull/1291)
+- Mobile responsive guides by [@aliabd](https://github.com/aliabd) in [PR 1293](https://github.com/gradio-app/gradio/pull/1293)
+- Update readme by [@abidlabs](https://github.com/abidlabs) in [PR 1292](https://github.com/gradio-app/gradio/pull/1292)
+- gif by [@abidlabs](https://github.com/abidlabs) in [PR 1296](https://github.com/gradio-app/gradio/pull/1296)
+- Allow decoding headerless b64 string [@1lint](https://github.com/1lint) in [PR 4031](https://github.com/gradio-app/gradio/pull/4031)
+
+### Contributors Shoutout:
+
+- [@JefferyChiang](https://github.com/JefferyChiang) made their first contribution in [PR 1004](https://github.com/gradio-app/gradio/pull/1004)
+- [@NimaBoscarino](https://github.com/NimaBoscarino) made their first contribution in [PR 1000](https://github.com/gradio-app/gradio/pull/1000)
+- [@ronvoluted](https://github.com/ronvoluted) made their first contribution in [PR 1050](https://github.com/gradio-app/gradio/pull/1050)
+- [@radames](https://github.com/radames) made their first contribution in [PR 1074](https://github.com/gradio-app/gradio/pull/1074)
+- [@freddyaboulton](https://github.com/freddyaboulton) made their first contribution in [PR 1085](https://github.com/gradio-app/gradio/pull/1085)
+- [@liteli1987gmail](https://github.com/liteli1987gmail) & [@chenglu](https://github.com/chenglu) made their first contribution in [PR 4767](https://github.com/gradio-app/gradio/pull/4767)
\ No newline at end of file
diff --git a/gradio/__init__.py b/gradio/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a29ad49d17bfbb6cab2b5b58faeb63b3984ad19
--- /dev/null
+++ b/gradio/__init__.py
@@ -0,0 +1,103 @@
+import json
+
+import gradio._simple_templates
+import gradio.components as components
+import gradio.image_utils
+import gradio.layouts as layouts
+import gradio.processing_utils
+import gradio.templates
+import gradio.themes as themes
+from gradio.blocks import Blocks
+from gradio.chat_interface import ChatInterface
+from gradio.cli import deploy
+from gradio.components import (
+ HTML,
+ JSON,
+ AnnotatedImage,
+ Annotatedimage,
+ Audio,
+ BarPlot,
+ Button,
+ Chatbot,
+ Checkbox,
+ CheckboxGroup,
+ Checkboxgroup,
+ ClearButton,
+ Code,
+ ColorPicker,
+ DataFrame,
+ Dataframe,
+ Dataset,
+ Dropdown,
+ DuplicateButton,
+ File,
+ FileExplorer,
+ Gallery,
+ Highlight,
+ HighlightedText,
+ Highlightedtext,
+ Image,
+ ImageEditor,
+ Json,
+ Label,
+ LinePlot,
+ LoginButton,
+ LogoutButton,
+ Markdown,
+ Model3D,
+ Number,
+ ParamViewer,
+ Plot,
+ Radio,
+ ScatterPlot,
+ Slider,
+ State,
+ Text,
+ Textbox,
+ UploadButton,
+ Video,
+ component,
+)
+from gradio.components.audio import WaveformOptions
+from gradio.components.image_editor import Brush, Eraser
+from gradio.data_classes import FileData
+from gradio.events import EventData, LikeData, SelectData, on
+from gradio.exceptions import Error
+from gradio.external import load
+from gradio.flagging import (
+ CSVLogger,
+ FlaggingCallback,
+ HuggingFaceDatasetSaver,
+ SimpleCSVLogger,
+)
+from gradio.helpers import (
+ Info,
+ Progress,
+ Warning,
+ make_waveform,
+ skip,
+ update,
+)
+from gradio.helpers import create_examples as Examples # noqa: N812
+from gradio.interface import Interface, TabbedInterface, close_all
+from gradio.ipython_ext import load_ipython_extension
+from gradio.layouts import Accordion, Column, Group, Row, Tab, TabItem, Tabs
+from gradio.oauth import OAuthProfile, OAuthToken
+from gradio.routes import Request, mount_gradio_app
+from gradio.templates import (
+ Files,
+ ImageMask,
+ List,
+ Matrix,
+ Mic,
+ Microphone,
+ Numpy,
+ Paint,
+ PlayableVideo,
+ Sketchpad,
+ TextArea,
+)
+from gradio.themes import Base as Theme
+from gradio.utils import get_package_version
+
+__version__ = get_package_version()
diff --git a/gradio/_simple_templates/__init__.py b/gradio/_simple_templates/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c61b4e4b15ae686dd6d7370b054835a792ffca4
--- /dev/null
+++ b/gradio/_simple_templates/__init__.py
@@ -0,0 +1,4 @@
+from .simpledropdown import SimpleDropdown
+from .simpletextbox import SimpleTextbox
+
+__all__ = ["SimpleDropdown", "SimpleTextbox"]
diff --git a/gradio/_simple_templates/simpledropdown.py b/gradio/_simple_templates/simpledropdown.py
new file mode 100644
index 0000000000000000000000000000000000000000..15d7631db6d77c03c8a7ade63132c148f85b3b60
--- /dev/null
+++ b/gradio/_simple_templates/simpledropdown.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+import warnings
+from typing import Any, Callable
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+
+class SimpleDropdown(FormComponent):
+ """
+ Creates a very simple dropdown listing choices from which entries can be selected.
+ Preprocessing: Preprocessing: passes the value of the selected dropdown entry as a {str}.
+ Postprocessing: expects a {str} corresponding to the value of the dropdown entry to be selected.
+ Examples-format: a {str} representing the drop down value to select.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ EVENTS = [Events.change, Events.input, Events.select]
+
+ def __init__(
+ self,
+ choices: list[str | int | float | tuple[str, str | int | float]] | None = None,
+ *,
+ value: str | int | float | Callable | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ choices: A list of string options to choose from. An option can also be a tuple of the form (name, value), where name is the displayed name of the dropdown choice and value is the value to be passed to the function, or returned by the function.
+ value: default value selected in dropdown. If None, no value is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, choices in this dropdown will be selectable; if False, selection will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: bool = True,
+ """
+ self.choices = (
+ # Although we expect choices to be a list of lists, it can be a list of tuples if the Gradio app
+ # is loaded with gr.load() since Python tuples are converted to lists in JSON.
+ [tuple(c) if isinstance(c, (tuple, list)) else (str(c), c) for c in choices]
+ if choices
+ else []
+ )
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ render=render,
+ )
+
+ def api_info(self) -> dict[str, Any]:
+ return {
+ "type": "string",
+ "enum": [c[1] for c in self.choices],
+ }
+
+ def example_inputs(self) -> Any:
+ return self.choices[0][1] if self.choices else None
+
+ def preprocess(self, x: str | int | float | None) -> str | int | float | None:
+ """
+ Parameters:
+ x: selected choice
+ Returns:
+ selected choice
+ """
+ return x
+
+ def _warn_if_invalid_choice(self, y):
+ if y not in [value for _, value in self.choices]:
+ warnings.warn(
+ f"The value passed into gr.Dropdown() is not in the list of choices. Please update the list of choices to include: {y}."
+ )
+
+ def postprocess(self, y):
+ if y is None:
+ return None
+ self._warn_if_invalid_choice(y)
+ return y
+
+ def process_example(self, input_data):
+ return next((c[0] for c in self.choices if c[1] == input_data), None)
diff --git a/gradio/_simple_templates/simpletextbox.py b/gradio/_simple_templates/simpletextbox.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec8fb60e7e6f006e5bab52f08eabd7b5d275ea19
--- /dev/null
+++ b/gradio/_simple_templates/simpletextbox.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+
+class SimpleTextbox(FormComponent):
+ """
+ Creates a very simple textbox for user to enter string input or display string output.
+ Preprocessing: passes textbox value as a {str} into the function.
+ Postprocessing: expects a {str} returned from function and sets textbox value to it.
+ Examples-format: a {str} representing the textbox input.
+ """
+
+ EVENTS = [
+ Events.change,
+ Events.input,
+ Events.submit,
+ ]
+
+ def __init__(
+ self,
+ value: str | Callable | None = "",
+ *,
+ placeholder: str | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ rtl: bool = False,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: default text to provide in textbox. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ placeholder: placeholder hint to provide behind textbox.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will be rendered as an editable textbox; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ rtl: If True and `type` is "text", sets the direction of the text to right-to-left (cursor appears on the left of the text). Default is False, which renders cursor on the right.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.placeholder = placeholder
+ self.rtl = rtl
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ render=render,
+ )
+
+ def preprocess(self, x: str | None) -> str | None:
+ """
+ Preprocesses input (converts it to a string) before passing it to the function.
+ Parameters:
+ x: text
+ Returns:
+ text
+ """
+ return None if x is None else str(x)
+
+ def postprocess(self, y: str | None) -> str | None:
+ """
+ Postproccess the function output y by converting it to a str before passing it to the frontend.
+ Parameters:
+ y: function output to postprocess.
+ Returns:
+ text
+ """
+ return None if y is None else str(y)
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
+
+ def example_inputs(self) -> Any:
+ return "Hello!!"
diff --git a/gradio/analytics.py b/gradio/analytics.py
new file mode 100644
index 0000000000000000000000000000000000000000..626914a333de8fb1ade1a55a5f6bebfdbf27aebc
--- /dev/null
+++ b/gradio/analytics.py
@@ -0,0 +1,253 @@
+""" Functions related to analytics and telemetry. """
+from __future__ import annotations
+
+import asyncio
+import json
+import os
+import threading
+import urllib.parse
+import warnings
+from typing import Any
+
+import httpx
+from packaging.version import Version
+
+import gradio
+from gradio import wasm_utils
+from gradio.context import Context
+from gradio.utils import get_package_version
+
+# For testability, we import the pyfetch function into this module scope and define a fallback coroutine object to be patched in tests.
+try:
+ from pyodide.http import pyfetch as pyodide_pyfetch # type: ignore
+except ImportError:
+
+ async def pyodide_pyfetch(*args, **kwargs):
+ raise NotImplementedError(
+ "pyodide.http.pyfetch is not available in this environment."
+ )
+
+
+ANALYTICS_URL = "https://api.gradio.app/"
+PKG_VERSION_URL = "https://api.gradio.app/pkg-version"
+
+
+def analytics_enabled() -> bool:
+ """
+ Returns: True if analytics are enabled, False otherwise.
+ """
+ return os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True"
+
+
+def _do_analytics_request(url: str, data: dict[str, Any]) -> None:
+ if wasm_utils.IS_WASM:
+ asyncio.ensure_future(
+ _do_wasm_analytics_request(
+ url=url,
+ data=data,
+ )
+ )
+ else:
+ threading.Thread(
+ target=_do_normal_analytics_request,
+ kwargs={
+ "url": url,
+ "data": data,
+ },
+ ).start()
+
+
+def _do_normal_analytics_request(url: str, data: dict[str, Any]) -> None:
+ data["ip_address"] = get_local_ip_address()
+ try:
+ httpx.post(url, data=data, timeout=5)
+ except (httpx.ConnectError, httpx.ReadTimeout):
+ pass # do not push analytics if no network
+
+
+async def _do_wasm_analytics_request(url: str, data: dict[str, Any]) -> None:
+ data["ip_address"] = await get_local_ip_address_wasm()
+
+ # We use urllib.parse.urlencode to encode the data as a form.
+ # Ref: https://docs.python.org/3/library/urllib.request.html#urllib-examples
+ body = urllib.parse.urlencode(data).encode("ascii")
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded",
+ }
+
+ try:
+ await asyncio.wait_for(
+ pyodide_pyfetch(url, method="POST", headers=headers, body=body),
+ timeout=5,
+ )
+ except asyncio.TimeoutError:
+ pass # do not push analytics if no network
+
+
+def version_check():
+ try:
+ current_pkg_version = get_package_version()
+ latest_pkg_version = httpx.get(url=PKG_VERSION_URL, timeout=3).json()["version"]
+ if Version(latest_pkg_version) > Version(current_pkg_version):
+ print(
+ f"IMPORTANT: You are using gradio version {current_pkg_version}, "
+ f"however version {latest_pkg_version} is available, please upgrade."
+ )
+ print("--------")
+ except json.decoder.JSONDecodeError:
+ warnings.warn("unable to parse version details from package URL.")
+ except KeyError:
+ warnings.warn("package URL does not contain version info.")
+ except Exception:
+ pass
+
+
+def get_local_ip_address() -> str:
+ """
+ Gets the public IP address or returns the string "No internet connection" if unable
+ to obtain it or the string "Analytics disabled" if a user has disabled analytics.
+ Does not make a new request if the IP address has already been obtained in the
+ same Python session.
+ """
+ if not analytics_enabled():
+ return "Analytics disabled"
+
+ if Context.ip_address is None:
+ try:
+ ip_address = httpx.get(
+ "https://checkip.amazonaws.com/", timeout=3
+ ).text.strip()
+ except (httpx.ConnectError, httpx.ReadTimeout):
+ ip_address = "No internet connection"
+ Context.ip_address = ip_address
+ else:
+ ip_address = Context.ip_address
+ return ip_address
+
+
+async def get_local_ip_address_wasm() -> str:
+ """The Wasm-compatible version of get_local_ip_address()."""
+ if not analytics_enabled():
+ return "Analytics disabled"
+
+ if Context.ip_address is None:
+ try:
+ response = await asyncio.wait_for(
+ pyodide_pyfetch(
+ # The API used by the normal version (`get_local_ip_address()`), `https://checkip.amazonaws.com/``, blocks CORS requests, so here we use a different API.
+ "https://api.ipify.org"
+ ),
+ timeout=5,
+ )
+ response_text: str = await response.string() # type: ignore
+ ip_address = response_text.strip()
+ except (asyncio.TimeoutError, OSError):
+ ip_address = "No internet connection"
+ Context.ip_address = ip_address
+ else:
+ ip_address = Context.ip_address
+ return ip_address
+
+
+def initiated_analytics(data: dict[str, Any]) -> None:
+ if not analytics_enabled():
+ return
+
+ _do_analytics_request(
+ url=f"{ANALYTICS_URL}gradio-initiated-analytics/",
+ data=data,
+ )
+
+
+def launched_analytics(blocks: gradio.Blocks, data: dict[str, Any]) -> None:
+ if not analytics_enabled():
+ return
+
+ (
+ blocks_telemetry,
+ inputs_telemetry,
+ outputs_telemetry,
+ targets_telemetry,
+ events_telemetry,
+ ) = (
+ [],
+ [],
+ [],
+ [],
+ [],
+ )
+
+ from gradio.blocks import BlockContext
+
+ for x in list(blocks.blocks.values()):
+ blocks_telemetry.append(x.get_block_name()) if isinstance(
+ x, BlockContext
+ ) else blocks_telemetry.append(str(x))
+
+ for x in blocks.dependencies:
+ targets_telemetry = targets_telemetry + [
+ # Sometimes the target can be the Blocks object itself, so we need to check if its in blocks.blocks
+ str(blocks.blocks[y[0]])
+ for y in x["targets"]
+ if y[0] in blocks.blocks
+ ]
+ events_telemetry = events_telemetry + [
+ y[1] for y in x["targets"] if y[0] in blocks.blocks
+ ]
+ inputs_telemetry = inputs_telemetry + [
+ str(blocks.blocks[y]) for y in x["inputs"] if y in blocks.blocks
+ ]
+ outputs_telemetry = outputs_telemetry + [
+ str(blocks.blocks[y]) for y in x["outputs"] if y in blocks.blocks
+ ]
+ additional_data = {
+ "version": get_package_version(),
+ "is_kaggle": blocks.is_kaggle,
+ "is_sagemaker": blocks.is_sagemaker,
+ "using_auth": blocks.auth is not None,
+ "dev_mode": blocks.dev_mode,
+ "show_api": blocks.show_api,
+ "show_error": blocks.show_error,
+ "title": blocks.title,
+ "inputs": blocks.input_components
+ if blocks.mode == "interface"
+ else inputs_telemetry,
+ "outputs": blocks.output_components
+ if blocks.mode == "interface"
+ else outputs_telemetry,
+ "targets": targets_telemetry,
+ "blocks": blocks_telemetry,
+ "events": events_telemetry,
+ "is_wasm": wasm_utils.IS_WASM,
+ }
+
+ data.update(additional_data)
+
+ _do_analytics_request(url=f"{ANALYTICS_URL}gradio-launched-telemetry/", data=data)
+
+
+def integration_analytics(data: dict[str, Any]) -> None:
+ if not analytics_enabled():
+ return
+
+ _do_analytics_request(
+ url=f"{ANALYTICS_URL}gradio-integration-analytics/",
+ data=data,
+ )
+
+
+def error_analytics(message: str) -> None:
+ """
+ Send error analytics if there is network
+ Parameters:
+ message: Details about error
+ """
+ if not analytics_enabled():
+ return
+
+ data = {"error": message}
+
+ _do_analytics_request(
+ url=f"{ANALYTICS_URL}gradio-error-analytics/",
+ data=data,
+ )
diff --git a/gradio/blocks.py b/gradio/blocks.py
new file mode 100644
index 0000000000000000000000000000000000000000..afd63661702a57a0e3b6c64e35fe7285a258364a
--- /dev/null
+++ b/gradio/blocks.py
@@ -0,0 +1,2362 @@
+from __future__ import annotations
+
+import copy
+import hashlib
+import inspect
+import json
+import os
+import random
+import secrets
+import string
+import sys
+import tempfile
+import threading
+import time
+import warnings
+import webbrowser
+from collections import defaultdict
+from pathlib import Path
+from types import ModuleType
+from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Literal, Sequence, cast
+from urllib.parse import urlparse, urlunparse
+
+import anyio
+import httpx
+from anyio import CapacityLimiter
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import (
+ analytics,
+ components,
+ networking,
+ processing_utils,
+ queueing,
+ routes,
+ strings,
+ themes,
+ utils,
+ wasm_utils,
+)
+from gradio.blocks_events import BlocksEvents, BlocksMeta
+from gradio.context import Context
+from gradio.data_classes import FileData, GradioModel, GradioRootModel
+from gradio.events import (
+ EventData,
+ EventListener,
+ EventListenerMethod,
+)
+from gradio.exceptions import (
+ DuplicateBlockError,
+ InvalidApiNameError,
+ InvalidBlockError,
+ InvalidComponentError,
+)
+from gradio.helpers import create_tracker, skip, special_args
+from gradio.state_holder import SessionState
+from gradio.themes import Default as DefaultTheme
+from gradio.themes import ThemeClass as Theme
+from gradio.tunneling import (
+ BINARY_FILENAME,
+ BINARY_FOLDER,
+ BINARY_PATH,
+ BINARY_URL,
+ CURRENT_TUNNELS,
+)
+from gradio.utils import (
+ TupleNoPrint,
+ check_function_inputs_match,
+ component_or_layout_class,
+ get_cancel_function,
+ get_continuous_fn,
+ get_package_version,
+)
+
+try:
+ import spaces # type: ignore
+except Exception:
+ spaces = None
+
+set_documentation_group("blocks")
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from fastapi.applications import FastAPI
+
+ from gradio.components.base import Component
+
+BUILT_IN_THEMES: dict[str, Theme] = {
+ t.name: t
+ for t in [
+ themes.Base(),
+ themes.Default(),
+ themes.Monochrome(),
+ themes.Soft(),
+ themes.Glass(),
+ ]
+}
+
+
+class Block:
+ def __init__(
+ self,
+ *,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ visible: bool = True,
+ proxy_url: str | None = None,
+ ):
+ self._id = Context.id
+ Context.id += 1
+ self.visible = visible
+ self.elem_id = elem_id
+ self.elem_classes = (
+ [elem_classes] if isinstance(elem_classes, str) else elem_classes
+ )
+ self.proxy_url = proxy_url
+ self.share_token = secrets.token_urlsafe(32)
+ self.parent: BlockContext | None = None
+ self.is_rendered: bool = False
+ self._constructor_args: list[dict]
+ self.state_session_capacity = 10000
+ self.temp_files: set[str] = set()
+ self.GRADIO_CACHE = str(
+ Path(
+ os.environ.get("GRADIO_TEMP_DIR")
+ or str(Path(tempfile.gettempdir()) / "gradio")
+ ).resolve()
+ )
+
+ if render:
+ self.render()
+
+ @property
+ def skip_api(self):
+ return False
+
+ @property
+ def constructor_args(self) -> dict[str, Any]:
+ """Get the arguments passed to the component's initializer.
+
+ Only set classes whose metaclass is ComponentMeta
+ """
+ # the _constructor_args list is appended based on the mro of the class
+ # so the first entry is for the bottom of the hierarchy
+ return self._constructor_args[0] if self._constructor_args else {}
+
+ @property
+ def events(
+ self,
+ ) -> list[EventListener]:
+ return getattr(self, "EVENTS", [])
+
+ def render(self):
+ """
+ Adds self into appropriate BlockContext
+ """
+ if Context.root_block is not None and self._id in Context.root_block.blocks:
+ raise DuplicateBlockError(
+ f"A block with id: {self._id} has already been rendered in the current Blocks."
+ )
+ if Context.block is not None:
+ Context.block.add(self)
+ if Context.root_block is not None:
+ Context.root_block.blocks[self._id] = self
+ self.is_rendered = True
+ if isinstance(self, components.Component):
+ Context.root_block.temp_file_sets.append(self.temp_files)
+ return self
+
+ def unrender(self):
+ """
+ Removes self from BlockContext if it has been rendered (otherwise does nothing).
+ Removes self from the layout and collection of blocks, but does not delete any event triggers.
+ """
+ if Context.block is not None:
+ try:
+ Context.block.children.remove(self)
+ except ValueError:
+ pass
+ if Context.root_block is not None:
+ try:
+ del Context.root_block.blocks[self._id]
+ self.is_rendered = False
+ except KeyError:
+ pass
+ return self
+
+ def get_block_name(self) -> str:
+ """
+ Gets block's class name.
+
+ If it is template component it gets the parent's class name.
+
+ @return: class name
+ """
+ return (
+ self.__class__.__base__.__name__.lower()
+ if hasattr(self, "is_template")
+ else self.__class__.__name__.lower()
+ )
+
+ def get_expected_parent(self) -> type[BlockContext] | None:
+ return None
+
+ def get_config(self):
+ config = {}
+ signature = inspect.signature(self.__class__.__init__)
+ for parameter in signature.parameters.values():
+ if hasattr(self, parameter.name):
+ value = getattr(self, parameter.name)
+ config[parameter.name] = utils.convert_to_dict_if_dataclass(value)
+ for e in self.events:
+ to_add = e.config_data()
+ if to_add:
+ config = {**to_add, **config}
+ config.pop("render", None)
+ config = {**config, "proxy_url": self.proxy_url, "name": self.get_block_name()}
+ if (_selectable := getattr(self, "_selectable", None)) is not None:
+ config["_selectable"] = _selectable
+ return config
+
+ @classmethod
+ def recover_kwargs(
+ cls, props: dict[str, Any], additional_keys: list[str] | None = None
+ ):
+ """
+ Recovers kwargs from a dict of props.
+ """
+ additional_keys = additional_keys or []
+ signature = inspect.signature(cls.__init__)
+ kwargs = {}
+ for parameter in signature.parameters.values():
+ if parameter.name in props and parameter.name not in additional_keys:
+ kwargs[parameter.name] = props[parameter.name]
+ return kwargs
+
+ def move_resource_to_block_cache(
+ self, url_or_file_path: str | Path | None
+ ) -> str | None:
+ """Moves a file or downloads a file from a url to a block's cache directory, adds
+ to to the block's temp_files, and returns the path to the file in cache. This
+ ensures that the file is accessible to the Block and can be served to users.
+ """
+ if url_or_file_path is None:
+ return None
+ if isinstance(url_or_file_path, Path):
+ url_or_file_path = str(url_or_file_path)
+
+ if client_utils.is_http_url_like(url_or_file_path):
+ temp_file_path = processing_utils.save_url_to_cache(
+ url_or_file_path, cache_dir=self.GRADIO_CACHE
+ )
+
+ self.temp_files.add(temp_file_path)
+ else:
+ url_or_file_path = str(utils.abspath(url_or_file_path))
+ if not utils.is_in_or_equal(url_or_file_path, self.GRADIO_CACHE):
+ temp_file_path = processing_utils.save_file_to_cache(
+ url_or_file_path, cache_dir=self.GRADIO_CACHE
+ )
+ else:
+ temp_file_path = url_or_file_path
+ self.temp_files.add(temp_file_path)
+
+ return temp_file_path
+
+
+class BlockContext(Block):
+ def __init__(
+ self,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ visible: bool = True,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ visible: If False, this will be hidden but included in the Blocks config file (its visibility can later be updated).
+ render: If False, this will not be included in the Blocks config file at all.
+ """
+ self.children: list[Block] = []
+ Block.__init__(
+ self,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ visible=visible,
+ render=render,
+ )
+
+ TEMPLATE_DIR = "./templates/"
+ FRONTEND_DIR = "../../frontend/"
+
+ @property
+ def skip_api(self):
+ return True
+
+ @classmethod
+ def get_component_class_id(cls) -> str:
+ module_name = cls.__module__
+ module_path = sys.modules[module_name].__file__
+ module_hash = hashlib.md5(f"{cls.__name__}_{module_path}".encode()).hexdigest()
+ return module_hash
+
+ @property
+ def component_class_id(self):
+ return self.get_component_class_id()
+
+ def add_child(self, child: Block):
+ self.children.append(child)
+
+ def __enter__(self):
+ self.parent = Context.block
+ Context.block = self
+ return self
+
+ def add(self, child: Block):
+ child.parent = self
+ self.children.append(child)
+
+ def fill_expected_parents(self):
+ children = []
+ pseudo_parent = None
+ for child in self.children:
+ expected_parent = child.get_expected_parent()
+ if not expected_parent or isinstance(self, expected_parent):
+ pseudo_parent = None
+ children.append(child)
+ else:
+ if pseudo_parent is not None and isinstance(
+ pseudo_parent, expected_parent
+ ):
+ pseudo_parent.add_child(child)
+ else:
+ pseudo_parent = expected_parent(render=False)
+ pseudo_parent.parent = self
+ children.append(pseudo_parent)
+ pseudo_parent.add_child(child)
+ if Context.root_block:
+ Context.root_block.blocks[pseudo_parent._id] = pseudo_parent
+ child.parent = pseudo_parent
+ self.children = children
+
+ def __exit__(self, exc_type: type[BaseException] | None = None, *args):
+ Context.block = self.parent
+ if exc_type is not None:
+ return
+ if getattr(self, "allow_expected_parents", True):
+ self.fill_expected_parents()
+
+ def postprocess(self, y):
+ """
+ Any postprocessing needed to be performed on a block context.
+ """
+ return y
+
+
+class BlockFunction:
+ def __init__(
+ self,
+ fn: Callable | None,
+ inputs: list[Component],
+ outputs: list[Component],
+ preprocess: bool,
+ postprocess: bool,
+ inputs_as_dict: bool,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ concurrency_id: str | None = None,
+ tracks_progress: bool = False,
+ ):
+ self.fn = fn
+ self.inputs = inputs
+ self.outputs = outputs
+ self.preprocess = preprocess
+ self.postprocess = postprocess
+ self.tracks_progress = tracks_progress
+ self.concurrency_limit: int | None | Literal["default"] = concurrency_limit
+ self.concurrency_id = concurrency_id or str(id(fn))
+ self.batch = batch
+ self.max_batch_size = max_batch_size
+ self.total_runtime = 0
+ self.total_runs = 0
+ self.inputs_as_dict = inputs_as_dict
+ self.name = getattr(fn, "__name__", "fn") if fn is not None else None
+ self.spaces_auto_wrap()
+
+ def spaces_auto_wrap(self):
+ if spaces is None:
+ return
+ if utils.get_space() is None:
+ return
+ self.fn = spaces.gradio_auto_wrap(self.fn)
+
+ def __str__(self):
+ return str(
+ {
+ "fn": self.name,
+ "preprocess": self.preprocess,
+ "postprocess": self.postprocess,
+ }
+ )
+
+ def __repr__(self):
+ return str(self)
+
+
+def postprocess_update_dict(
+ block: Component | BlockContext, update_dict: dict, postprocess: bool = True
+):
+ """
+ Converts a dictionary of updates into a format that can be sent to the frontend to update the component.
+ E.g. {"value": "2", "visible": True, "invalid_arg": "hello"}
+ Into -> {"__type__": "update", "value": 2.0, "visible": True}
+ Parameters:
+ block: The Block that is being updated with this update dictionary.
+ update_dict: The original update dictionary
+ postprocess: Whether to postprocess the "value" key of the update dictionary.
+ """
+ value = update_dict.pop("value", components._Keywords.NO_VALUE)
+ update_dict = {k: getattr(block, k) for k in update_dict if hasattr(block, k)}
+ if value is not components._Keywords.NO_VALUE:
+ if postprocess:
+ update_dict["value"] = block.postprocess(value)
+ if isinstance(update_dict["value"], (GradioModel, GradioRootModel)):
+ update_dict["value"] = update_dict["value"].model_dump()
+ else:
+ update_dict["value"] = value
+ update_dict["__type__"] = "update"
+ return update_dict
+
+
+def convert_component_dict_to_list(
+ outputs_ids: list[int], predictions: dict
+) -> list | dict:
+ """
+ Converts a dictionary of component updates into a list of updates in the order of
+ the outputs_ids and including every output component. Leaves other types of dictionaries unchanged.
+ E.g. {"textbox": "hello", "number": {"__type__": "generic_update", "value": "2"}}
+ Into -> ["hello", {"__type__": "generic_update"}, {"__type__": "generic_update", "value": "2"}]
+ """
+ keys_are_blocks = [isinstance(key, Block) for key in predictions]
+ if all(keys_are_blocks):
+ reordered_predictions = [skip() for _ in outputs_ids]
+ for component, value in predictions.items():
+ if component._id not in outputs_ids:
+ raise ValueError(
+ f"Returned component {component} not specified as output of function."
+ )
+ output_index = outputs_ids.index(component._id)
+ reordered_predictions[output_index] = value
+ predictions = utils.resolve_singleton(reordered_predictions)
+ elif any(keys_are_blocks):
+ raise ValueError(
+ "Returned dictionary included some keys as Components. Either all keys must be Components to assign Component values, or return a List of values to assign output values in order."
+ )
+ return predictions
+
+
+@document("launch", "queue", "integrate", "load")
+class Blocks(BlockContext, BlocksEvents, metaclass=BlocksMeta):
+ """
+ Blocks is Gradio's low-level API that allows you to create more custom web
+ applications and demos than Interfaces (yet still entirely in Python).
+
+
+ Compared to the Interface class, Blocks offers more flexibility and control over:
+ (1) the layout of components (2) the events that
+ trigger the execution of functions (3) data flows (e.g. inputs can trigger outputs,
+ which can trigger the next level of outputs). Blocks also offers ways to group
+ together related demos such as with tabs.
+
+
+ The basic usage of Blocks is as follows: create a Blocks object, then use it as a
+ context (with the "with" statement), and then define layouts, components, or events
+ within the Blocks context. Finally, call the launch() method to launch the demo.
+
+ Example:
+ import gradio as gr
+ def update(name):
+ return f"Welcome to Gradio, {name}!"
+
+ with gr.Blocks() as demo:
+ gr.Markdown("Start typing below and then click **Run** to see the output.")
+ with gr.Row():
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+ btn = gr.Button("Run")
+ btn.click(fn=update, inputs=inp, outputs=out)
+
+ demo.launch()
+ Demos: blocks_hello, blocks_flipper, blocks_speech_text_sentiment, generate_english_german
+ Guides: blocks-and-event-listeners, controlling-layout, state-in-blocks, custom-CSS-and-JS, using-blocks-like-functions
+ """
+
+ def __init__(
+ self,
+ theme: Theme | str | None = None,
+ analytics_enabled: bool | None = None,
+ mode: str = "blocks",
+ title: str = "Gradio",
+ css: str | None = None,
+ js: str | None = None,
+ head: str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ theme: A Theme object or a string representing a theme. If a string, will look for a built-in theme with that name (e.g. "soft" or "default"), or will attempt to load a theme from the HF Hub (e.g. "gradio/monochrome"). If None, will use the Default theme.
+ analytics_enabled: Whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable or default to True.
+ mode: A human-friendly name for the kind of Blocks or Interface being created. Used internally for analytics.
+ title: The tab title to display when this is opened in a browser window.
+ css: Custom css as a string or path to a css file. This css will be included in the demo webpage.
+ js: Custom js or path to js file to run when demo is first loaded. This javascript will be included in the demo webpage.
+ head: Custom html to insert into the head of the demo webpage. This can be used to add custom meta tags, scripts, stylesheets, etc. to the page.
+ """
+ self.limiter = None
+ if theme is None:
+ theme = DefaultTheme()
+ elif isinstance(theme, str):
+ if theme.lower() in BUILT_IN_THEMES:
+ theme = BUILT_IN_THEMES[theme.lower()]
+ else:
+ try:
+ theme = Theme.from_hub(theme)
+ except Exception as e:
+ warnings.warn(f"Cannot load {theme}. Caught Exception: {str(e)}")
+ theme = DefaultTheme()
+ if not isinstance(theme, Theme):
+ warnings.warn("Theme should be a class loaded from gradio.themes")
+ theme = DefaultTheme()
+ self.theme: Theme = theme
+ self.theme_css = theme._get_theme_css()
+ self.stylesheets = theme._stylesheets
+ self.encrypt = False
+ self.share = False
+ self.enable_queue = True
+ self.max_threads = 40
+ self.pending_streams = defaultdict(dict)
+ self.show_error = True
+ self.head = head
+ if css is not None and os.path.exists(css):
+ with open(css) as css_file:
+ self.css = css_file.read()
+ else:
+ self.css = css
+ if js is not None and os.path.exists(js):
+ with open(js) as js_file:
+ self.js = js_file.read()
+ else:
+ self.js = js
+
+ # For analytics_enabled and allow_flagging: (1) first check for
+ # parameter, (2) check for env variable, (3) default to True/"manual"
+ self.analytics_enabled = (
+ analytics_enabled
+ if analytics_enabled is not None
+ else analytics.analytics_enabled()
+ )
+ if self.analytics_enabled:
+ if not wasm_utils.IS_WASM:
+ t = threading.Thread(target=analytics.version_check)
+ t.start()
+ else:
+ os.environ["HF_HUB_DISABLE_TELEMETRY"] = "True"
+ super().__init__(render=False, **kwargs)
+ self.blocks: dict[int, Component | Block] = {}
+ self.fns: list[BlockFunction] = []
+ self.dependencies = []
+ self.mode = mode
+
+ self.is_running = False
+ self.local_url = None
+ self.share_url = None
+ self.width = None
+ self.height = None
+ self.api_open = utils.get_space() is None
+
+ self.space_id = utils.get_space()
+ self.favicon_path = None
+ self.auth = None
+ self.dev_mode = bool(os.getenv("GRADIO_WATCH_DIRS", False))
+ self.app_id = random.getrandbits(64)
+ self.temp_file_sets = []
+ self.title = title
+ self.show_api = not wasm_utils.IS_WASM
+
+ # Only used when an Interface is loaded from a config
+ self.predict = None
+ self.input_components = None
+ self.output_components = None
+ self.__name__ = None
+ self.api_mode = None
+
+ self.progress_tracking = None
+ self.ssl_verify = True
+
+ self.allowed_paths = []
+ self.blocked_paths = []
+ self.root_path = os.environ.get("GRADIO_ROOT_PATH", "")
+ self.proxy_urls = set()
+
+ if self.analytics_enabled:
+ is_custom_theme = not any(
+ self.theme.to_dict() == built_in_theme.to_dict()
+ for built_in_theme in BUILT_IN_THEMES.values()
+ )
+ data = {
+ "mode": self.mode,
+ "custom_css": self.css is not None,
+ "theme": self.theme.name,
+ "is_custom_theme": is_custom_theme,
+ "version": get_package_version(),
+ }
+ analytics.initiated_analytics(data)
+
+ self.queue()
+
+ def get_component(self, id: int) -> Component | BlockContext:
+ comp = self.blocks[id]
+ assert isinstance(comp, (components.Component, BlockContext)), f"{comp}"
+ return comp
+
+ @property
+ def _is_running_in_reload_thread(self):
+ from gradio.cli.commands.reload import reload_thread
+
+ return getattr(reload_thread, "running_reload", False)
+
+ @classmethod
+ def from_config(
+ cls,
+ config: dict,
+ fns: list[Callable],
+ proxy_url: str,
+ ) -> Blocks:
+ """
+ Factory method that creates a Blocks from a config and list of functions. Used
+ internally by the gradio.external.load() method.
+
+ Parameters:
+ config: a dictionary containing the configuration of the Blocks.
+ fns: a list of functions that are used in the Blocks. Must be in the same order as the dependencies in the config.
+ proxy_url: an external url to use as a root URL when serving files for components in the Blocks.
+ """
+ config = copy.deepcopy(config)
+ components_config = config["components"]
+ for component_config in components_config:
+ # for backwards compatibility, extract style into props
+ if "style" in component_config["props"]:
+ component_config["props"].update(component_config["props"]["style"])
+ del component_config["props"]["style"]
+ theme = config.get("theme", "default")
+ original_mapping: dict[int, Block] = {}
+ proxy_urls = {proxy_url}
+
+ def get_block_instance(id: int) -> Block:
+ for block_config in components_config:
+ if block_config["id"] == id:
+ break
+ else:
+ raise ValueError(f"Cannot find block with id {id}")
+ cls = component_or_layout_class(block_config["type"])
+
+ # If a Gradio app B is loaded into a Gradio app A, and B itself loads a
+ # Gradio app C, then the proxy_urls of the components in A need to be the
+ # URL of C, not B. The else clause below handles this case.
+ if block_config["props"].get("proxy_url") is None:
+ block_config["props"]["proxy_url"] = f"{proxy_url}/"
+ postprocessed_value = block_config["props"].pop("value", None)
+
+ constructor_args = cls.recover_kwargs(block_config["props"])
+ block = cls(**constructor_args)
+ if postprocessed_value is not None:
+ block.value = postprocessed_value # type: ignore
+
+ block_proxy_url = block_config["props"]["proxy_url"]
+ block.proxy_url = block_proxy_url
+ proxy_urls.add(block_proxy_url)
+ if (
+ _selectable := block_config["props"].pop("_selectable", None)
+ ) is not None:
+ block._selectable = _selectable # type: ignore
+
+ return block
+
+ def iterate_over_children(children_list):
+ for child_config in children_list:
+ id = child_config["id"]
+ block = get_block_instance(id)
+
+ original_mapping[id] = block
+
+ children = child_config.get("children")
+ if children is not None:
+ if not isinstance(block, BlockContext):
+ raise ValueError(
+ f"Invalid config, Block with id {id} has children but is not a BlockContext."
+ )
+ with block:
+ iterate_over_children(children)
+
+ derived_fields = ["types"]
+
+ with Blocks(theme=theme) as blocks:
+ # ID 0 should be the root Blocks component
+ original_mapping[0] = Context.root_block or blocks
+
+ iterate_over_children(config["layout"]["children"])
+
+ first_dependency = None
+
+ # add the event triggers
+ for dependency, fn in zip(config["dependencies"], fns):
+ # We used to add a "fake_event" to the config to cache examples
+ # without removing it. This was causing bugs in calling gr.load
+ # We fixed the issue by removing "fake_event" from the config in examples.py
+ # but we still need to skip these events when loading the config to support
+ # older demos
+ if "trigger" in dependency and dependency["trigger"] == "fake_event":
+ continue
+ for field in derived_fields:
+ dependency.pop(field, None)
+
+ # older versions had a separate trigger field, but now it is part of the
+ # targets field
+ _targets = dependency.pop("targets")
+ trigger = dependency.pop("trigger", None)
+ targets = [
+ getattr(
+ original_mapping[
+ target if isinstance(target, int) else target[0]
+ ],
+ trigger if isinstance(target, int) else target[1],
+ )
+ for target in _targets
+ ]
+ dependency.pop("backend_fn")
+ dependency.pop("documentation", None)
+ dependency["inputs"] = [
+ original_mapping[i] for i in dependency["inputs"]
+ ]
+ dependency["outputs"] = [
+ original_mapping[o] for o in dependency["outputs"]
+ ]
+ dependency.pop("status_tracker", None)
+ dependency["preprocess"] = False
+ dependency["postprocess"] = False
+ targets = [
+ EventListenerMethod(
+ t.__self__ if t.has_trigger else None, t.event_name
+ )
+ for t in targets
+ ]
+ dependency = blocks.set_event_trigger(
+ targets=targets, fn=fn, **dependency
+ )[0]
+ if first_dependency is None:
+ first_dependency = dependency
+
+ # Allows some use of Interface-specific methods with loaded Spaces
+ if first_dependency and Context.root_block:
+ blocks.predict = [fns[0]]
+ blocks.input_components = [
+ Context.root_block.blocks[i] for i in first_dependency["inputs"]
+ ]
+ blocks.output_components = [
+ Context.root_block.blocks[o] for o in first_dependency["outputs"]
+ ]
+ blocks.__name__ = "Interface"
+ blocks.api_mode = True
+ blocks.proxy_urls = proxy_urls
+ return blocks
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ num_backend_fns = len([d for d in self.dependencies if d["backend_fn"]])
+ repr = f"Gradio Blocks instance: {num_backend_fns} backend functions"
+ repr += f"\n{'-' * len(repr)}"
+ for d, dependency in enumerate(self.dependencies):
+ if dependency["backend_fn"]:
+ repr += f"\nfn_index={d}"
+ repr += "\n inputs:"
+ for input_id in dependency["inputs"]:
+ block = self.blocks[input_id]
+ repr += f"\n |-{block}"
+ repr += "\n outputs:"
+ for output_id in dependency["outputs"]:
+ block = self.blocks[output_id]
+ repr += f"\n |-{block}"
+ return repr
+
+ @property
+ def expects_oauth(self):
+ """Return whether the app expects user to authenticate via OAuth."""
+ return any(
+ isinstance(block, (components.LoginButton, components.LogoutButton))
+ for block in self.blocks.values()
+ )
+
+ def set_event_trigger(
+ self,
+ targets: Sequence[EventListenerMethod],
+ fn: Callable | None,
+ inputs: Component | list[Component] | set[Component] | None,
+ outputs: Component | list[Component] | None,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ scroll_to_output: bool = False,
+ show_progress: Literal["full", "minimal", "hidden"] = "full",
+ api_name: str | None | Literal[False] = None,
+ js: str | None = None,
+ no_target: bool = False,
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ cancels: list[int] | None = None,
+ every: float | None = None,
+ collects_event_data: bool | None = None,
+ trigger_after: int | None = None,
+ trigger_only_on_success: bool = False,
+ trigger_mode: Literal["once", "multiple", "always_last"] | None = "once",
+ concurrency_limit: int | None | Literal["default"] = "default",
+ concurrency_id: str | None = None,
+ show_api: bool = True,
+ ) -> tuple[dict[str, Any], int]:
+ """
+ Adds an event to the component's dependencies.
+ Parameters:
+ targets: a list of EventListenerMethod objects that define the event trigger
+ fn: Callable function
+ inputs: input list
+ outputs: output list
+ preprocess: whether to run the preprocess methods of components
+ postprocess: whether to run the postprocess methods of components
+ scroll_to_output: whether to scroll to output of dependency on trigger
+ show_progress: whether to show progress animation while running.
+ api_name: defines how the endpoint appears in the API docs. Can be a string, None, or False. If set to a string, the endpoint will be exposed in the API docs with the given name. If None (default), the name of the function will be used as the API endpoint. If False, the endpoint will not be exposed in the API docs and downstream apps (including those that `gr.load` this app) will not be able to use this event.
+ js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components
+ no_target: if True, sets "targets" to [], used for Blocks "load" event
+ queue: If True, will place the request on the queue, if the queue has been enabled. If False, will not put this event on the queue, even if the queue has been enabled. If None, will use the queue setting of the gradio app.
+ batch: whether this function takes in a batch of inputs
+ max_batch_size: the maximum batch size to send to the function
+ cancels: a list of other events to cancel when this event is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ collects_event_data: whether to collect event data for this event
+ trigger_after: if set, this event will be triggered after 'trigger_after' function index
+ trigger_only_on_success: if True, this event will only be triggered if the previous event was successful (only applies if `trigger_after` is set)
+ trigger_mode: If "once" (default for all events except `.change()`) would not allow any submissions while an event is pending. If set to "multiple", unlimited submissions are allowed while pending, and "always_last" (default for `.change()` event) would allow a second submission after the pending event is complete.
+ concurrency_limit: If set, this is the maximum number of this event that can be running simultaneously. Can be set to None to mean no concurrency_limit (any number of this event can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `queue()`, which itself is 1 by default).
+ concurrency_id: If set, this is the id of the concurrency group. Events with the same concurrency_id will be limited by the lowest set concurrency_limit.
+ show_api: whether to show this event in the "view API" page of the Gradio app, or in the ".view_api()" method of the Gradio clients. Unlike setting api_name to False, setting show_api to False will still allow downstream apps to use this event. If fn is None, show_api will automatically be set to False.
+ Returns: dependency information, dependency index
+ """
+ # Support for singular parameter
+ _targets = [
+ (
+ target.block._id if target.block and not no_target else None,
+ target.event_name,
+ )
+ for target in targets
+ ]
+ if isinstance(inputs, set):
+ inputs_as_dict = True
+ inputs = sorted(inputs, key=lambda x: x._id)
+ else:
+ inputs_as_dict = False
+ if inputs is None:
+ inputs = []
+ elif not isinstance(inputs, list):
+ inputs = [inputs]
+
+ if isinstance(outputs, set):
+ outputs = sorted(outputs, key=lambda x: x._id)
+ else:
+ if outputs is None:
+ outputs = []
+ elif not isinstance(outputs, list):
+ outputs = [outputs]
+
+ if fn is not None and not cancels:
+ check_function_inputs_match(fn, inputs, inputs_as_dict)
+ if every is not None and every <= 0:
+ raise ValueError("Parameter every must be positive or None")
+ if every and batch:
+ raise ValueError(
+ f"Cannot run event in a batch and every {every} seconds. "
+ "Either batch is True or every is non-zero but not both."
+ )
+
+ if every and fn:
+ fn = get_continuous_fn(fn, every)
+ elif every:
+ raise ValueError("Cannot set a value for `every` without a `fn`.")
+ if every and concurrency_limit is not None:
+ if concurrency_limit == "default":
+ concurrency_limit = None
+ else:
+ raise ValueError(
+ "Cannot set a value for `concurrency_limit` with `every`."
+ )
+
+ if _targets[0][1] == "change" and trigger_mode is None:
+ trigger_mode = "always_last"
+ elif trigger_mode is None:
+ trigger_mode = "once"
+ elif trigger_mode not in ["once", "multiple", "always_last"]:
+ raise ValueError(
+ f"Invalid value for parameter `trigger_mode`: {trigger_mode}. Please choose from: {['once', 'multiple', 'always_last']}"
+ )
+
+ _, progress_index, event_data_index = (
+ special_args(fn) if fn else (None, None, None)
+ )
+ self.fns.append(
+ BlockFunction(
+ fn,
+ inputs,
+ outputs,
+ preprocess,
+ postprocess,
+ inputs_as_dict=inputs_as_dict,
+ concurrency_limit=concurrency_limit,
+ concurrency_id=concurrency_id,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ tracks_progress=progress_index is not None,
+ )
+ )
+
+ # If api_name is None or empty string, use the function name
+ if api_name is None or isinstance(api_name, str) and api_name.strip() == "":
+ if fn is not None:
+ if not hasattr(fn, "__name__"):
+ if hasattr(fn, "__class__") and hasattr(fn.__class__, "__name__"):
+ name = fn.__class__.__name__
+ else:
+ name = "unnamed"
+ else:
+ name = fn.__name__
+ api_name = "".join(
+ [s for s in name if s not in set(string.punctuation) - {"-", "_"}]
+ )
+ elif js is not None:
+ api_name = "js_fn"
+ show_api = False
+ else:
+ api_name = "unnamed"
+ show_api = False
+
+ if api_name is not False:
+ api_name = utils.append_unique_suffix(
+ api_name, [dep["api_name"] for dep in self.dependencies]
+ )
+ else:
+ show_api = False
+
+ # The `show_api` parameter is False if: (1) the user explicitly sets it (2) the user sets `api_name` to False
+ # or (3) the user sets `fn` to None (there's no backend function)
+
+ if collects_event_data is None:
+ collects_event_data = event_data_index is not None
+
+ dependency = {
+ "targets": _targets,
+ "inputs": [block._id for block in inputs],
+ "outputs": [block._id for block in outputs],
+ "backend_fn": fn is not None,
+ "js": js,
+ "queue": False if fn is None else queue,
+ "api_name": api_name,
+ "scroll_to_output": False if utils.get_space() else scroll_to_output,
+ "show_progress": show_progress,
+ "every": every,
+ "batch": batch,
+ "max_batch_size": max_batch_size,
+ "cancels": cancels or [],
+ "types": {
+ "continuous": bool(every),
+ "generator": inspect.isgeneratorfunction(fn)
+ or inspect.isasyncgenfunction(fn)
+ or bool(every),
+ },
+ "collects_event_data": collects_event_data,
+ "trigger_after": trigger_after,
+ "trigger_only_on_success": trigger_only_on_success,
+ "trigger_mode": trigger_mode,
+ "show_api": show_api,
+ }
+ self.dependencies.append(dependency)
+ return dependency, len(self.dependencies) - 1
+
+ def render(self):
+ if Context.root_block is not None:
+ if self._id in Context.root_block.blocks:
+ raise DuplicateBlockError(
+ f"A block with id: {self._id} has already been rendered in the current Blocks."
+ )
+ overlapping_ids = set(Context.root_block.blocks).intersection(self.blocks)
+ for id in overlapping_ids:
+ # State components are allowed to be reused between Blocks
+ if not isinstance(self.blocks[id], components.State):
+ raise DuplicateBlockError(
+ "At least one block in this Blocks has already been rendered."
+ )
+
+ Context.root_block.blocks.update(self.blocks)
+ Context.root_block.fns.extend(self.fns)
+ dependency_offset = len(Context.root_block.dependencies)
+ for i, dependency in enumerate(self.dependencies):
+ api_name = dependency["api_name"]
+ if api_name is not None and api_name is not False:
+ api_name_ = utils.append_unique_suffix(
+ api_name,
+ [dep["api_name"] for dep in Context.root_block.dependencies],
+ )
+ if api_name != api_name_:
+ dependency["api_name"] = api_name_
+ dependency["cancels"] = [
+ c + dependency_offset for c in dependency["cancels"]
+ ]
+ if dependency.get("trigger_after") is not None:
+ dependency["trigger_after"] += dependency_offset
+ # Recreate the cancel function so that it has the latest
+ # dependency fn indices. This is necessary to properly cancel
+ # events in the backend
+ if dependency["cancels"]:
+ updated_cancels = [
+ Context.root_block.dependencies[i]
+ for i in dependency["cancels"]
+ ]
+ new_fn = BlockFunction(
+ get_cancel_function(updated_cancels)[0],
+ [],
+ [],
+ False,
+ True,
+ False,
+ )
+ Context.root_block.fns[dependency_offset + i] = new_fn
+ Context.root_block.dependencies.append(dependency)
+ Context.root_block.temp_file_sets.extend(self.temp_file_sets)
+ Context.root_block.proxy_urls.update(self.proxy_urls)
+
+ if Context.block is not None:
+ Context.block.children.extend(self.children)
+ return self
+
+ def is_callable(self, fn_index: int = 0) -> bool:
+ """Checks if a particular Blocks function is callable (i.e. not stateful or a generator)."""
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ if inspect.isasyncgenfunction(block_fn.fn):
+ return False
+ if inspect.isgeneratorfunction(block_fn.fn):
+ return False
+ for input_id in dependency["inputs"]:
+ block = self.blocks[input_id]
+ if getattr(block, "stateful", False):
+ return False
+ for output_id in dependency["outputs"]:
+ block = self.blocks[output_id]
+ if getattr(block, "stateful", False):
+ return False
+
+ return True
+
+ def __call__(self, *inputs, fn_index: int = 0, api_name: str | None = None):
+ """
+ Allows Blocks objects to be called as functions. Supply the parameters to the
+ function as positional arguments. To choose which function to call, use the
+ fn_index parameter, which must be a keyword argument.
+
+ Parameters:
+ *inputs: the parameters to pass to the function
+ fn_index: the index of the function to call (defaults to 0, which for Interfaces, is the default prediction function)
+ api_name: The api_name of the dependency to call. Will take precedence over fn_index.
+ """
+ if api_name is not None:
+ inferred_fn_index = next(
+ (
+ i
+ for i, d in enumerate(self.dependencies)
+ if d.get("api_name") == api_name
+ ),
+ None,
+ )
+ if inferred_fn_index is None:
+ raise InvalidApiNameError(
+ f"Cannot find a function with api_name {api_name}"
+ )
+ fn_index = inferred_fn_index
+ if not (self.is_callable(fn_index)):
+ raise ValueError(
+ "This function is not callable because it is either stateful or is a generator. Please use the .launch() method instead to create an interactive user interface."
+ )
+
+ inputs = list(inputs)
+ processed_inputs = self.serialize_data(fn_index, inputs)
+ batch = self.dependencies[fn_index]["batch"]
+ if batch:
+ processed_inputs = [[inp] for inp in processed_inputs]
+
+ outputs = client_utils.synchronize_async(
+ self.process_api,
+ fn_index=fn_index,
+ inputs=processed_inputs,
+ request=None,
+ state={},
+ )
+ outputs = outputs["data"]
+
+ if batch:
+ outputs = [out[0] for out in outputs]
+
+ outputs = self.deserialize_data(fn_index, outputs)
+ processed_outputs = utils.resolve_singleton(outputs)
+
+ return processed_outputs
+
+ async def call_function(
+ self,
+ fn_index: int,
+ processed_input: list[Any],
+ iterator: AsyncIterator[Any] | None = None,
+ requests: routes.Request | list[routes.Request] | None = None,
+ event_id: str | None = None,
+ event_data: EventData | None = None,
+ in_event_listener: bool = False,
+ ):
+ """
+ Calls function with given index and preprocessed input, and measures process time.
+ Parameters:
+ fn_index: index of function to call
+ processed_input: preprocessed input to pass to function
+ iterator: iterator to use if function is a generator
+ requests: requests to pass to function
+ event_id: id of event in queue
+ event_data: data associated with event trigger
+ """
+ block_fn = self.fns[fn_index]
+ if not block_fn.fn:
+ raise IndexError(f"function with index {fn_index} not defined.")
+ is_generating = False
+ request = requests[0] if isinstance(requests, list) else requests
+ start = time.time()
+
+ fn = utils.get_function_with_locals(
+ fn=block_fn.fn,
+ blocks=self,
+ event_id=event_id,
+ in_event_listener=in_event_listener,
+ request=request,
+ )
+
+ if iterator is None: # If not a generator function that has already run
+ if block_fn.inputs_as_dict:
+ processed_input = [dict(zip(block_fn.inputs, processed_input))]
+
+ processed_input, progress_index, _ = special_args(
+ block_fn.fn, processed_input, request, event_data
+ )
+ progress_tracker = (
+ processed_input[progress_index] if progress_index is not None else None
+ )
+
+ if progress_tracker is not None and progress_index is not None:
+ progress_tracker, fn = create_tracker(fn, progress_tracker.track_tqdm)
+ processed_input[progress_index] = progress_tracker
+
+ if inspect.iscoroutinefunction(fn):
+ prediction = await fn(*processed_input)
+ else:
+ prediction = await anyio.to_thread.run_sync(
+ fn, *processed_input, limiter=self.limiter
+ )
+ else:
+ prediction = None
+
+ if inspect.isgeneratorfunction(fn) or inspect.isasyncgenfunction(fn):
+ try:
+ if iterator is None:
+ iterator = cast(AsyncIterator[Any], prediction)
+ if inspect.isgenerator(iterator):
+ iterator = utils.SyncToAsyncIterator(iterator, self.limiter)
+ prediction = await utils.async_iteration(iterator)
+ is_generating = True
+ except StopAsyncIteration:
+ n_outputs = len(self.dependencies[fn_index].get("outputs"))
+ prediction = (
+ components._Keywords.FINISHED_ITERATING
+ if n_outputs == 1
+ else (components._Keywords.FINISHED_ITERATING,) * n_outputs
+ )
+ iterator = None
+
+ duration = time.time() - start
+
+ return {
+ "prediction": prediction,
+ "duration": duration,
+ "is_generating": is_generating,
+ "iterator": iterator,
+ }
+
+ def serialize_data(self, fn_index: int, inputs: list[Any]) -> list[Any]:
+ dependency = self.dependencies[fn_index]
+ processed_input = []
+
+ def format_file(s):
+ return FileData(path=s).model_dump()
+
+ for i, input_id in enumerate(dependency["inputs"]):
+ try:
+ block = self.blocks[input_id]
+ except KeyError as e:
+ raise InvalidBlockError(
+ f"Input component with id {input_id} used in {dependency['trigger']}() event is not defined in this gr.Blocks context. You are allowed to nest gr.Blocks contexts, but there must be a gr.Blocks context that contains all components and events."
+ ) from e
+ if not isinstance(block, components.Component):
+ raise InvalidComponentError(
+ f"{block.__class__} Component with id {input_id} not a valid input component."
+ )
+ api_info = block.api_info()
+ if client_utils.value_is_file(api_info):
+ serialized_input = client_utils.traverse(
+ inputs[i],
+ format_file,
+ lambda s: client_utils.is_filepath(s) or client_utils.is_url(s),
+ )
+ else:
+ serialized_input = inputs[i]
+ processed_input.append(serialized_input)
+
+ return processed_input
+
+ def deserialize_data(self, fn_index: int, outputs: list[Any]) -> list[Any]:
+ dependency = self.dependencies[fn_index]
+ predictions = []
+
+ for o, output_id in enumerate(dependency["outputs"]):
+ try:
+ block = self.blocks[output_id]
+ except KeyError as e:
+ raise InvalidBlockError(
+ f"Output component with id {output_id} used in {dependency['trigger']}() event not found in this gr.Blocks context. You are allowed to nest gr.Blocks contexts, but there must be a gr.Blocks context that contains all components and events."
+ ) from e
+ if not isinstance(block, components.Component):
+ raise InvalidComponentError(
+ f"{block.__class__} Component with id {output_id} not a valid output component."
+ )
+
+ deserialized = client_utils.traverse(
+ outputs[o], lambda s: s["path"], client_utils.is_file_obj
+ )
+ predictions.append(deserialized)
+
+ return predictions
+
+ def validate_inputs(self, fn_index: int, inputs: list[Any]):
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ dep_inputs = dependency["inputs"]
+
+ # This handles incorrect inputs when args are changed by a JS function
+ # Only check not enough args case, ignore extra arguments (for now)
+ # TODO: make this stricter?
+ if len(inputs) < len(dep_inputs):
+ name = (
+ f" ({block_fn.name})"
+ if block_fn.name and block_fn.name != ""
+ else ""
+ )
+
+ wanted_args = []
+ received_args = []
+ for input_id in dep_inputs:
+ block = self.blocks[input_id]
+ wanted_args.append(str(block))
+ for inp in inputs:
+ v = f'"{inp}"' if isinstance(inp, str) else str(inp)
+ received_args.append(v)
+
+ wanted = ", ".join(wanted_args)
+ received = ", ".join(received_args)
+
+ # JS func didn't pass enough arguments
+ raise ValueError(
+ f"""An event handler{name} didn't receive enough input values (needed: {len(dep_inputs)}, got: {len(inputs)}).
+Check if the event handler calls a Javascript function, and make sure its return value is correct.
+Wanted inputs:
+ [{wanted}]
+Received inputs:
+ [{received}]"""
+ )
+
+ def preprocess_data(
+ self, fn_index: int, inputs: list[Any], state: SessionState | None
+ ):
+ state = state or SessionState(self)
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ self.validate_inputs(fn_index, inputs)
+
+ if block_fn.preprocess:
+ processed_input = []
+ for i, input_id in enumerate(dependency["inputs"]):
+ try:
+ block = self.blocks[input_id]
+ except KeyError as e:
+ raise InvalidBlockError(
+ f"Input component with id {input_id} used in {dependency['trigger']}() event not found in this gr.Blocks context. You are allowed to nest gr.Blocks contexts, but there must be a gr.Blocks context that contains all components and events."
+ ) from e
+ if not isinstance(block, components.Component):
+ raise InvalidComponentError(
+ f"{block.__class__} Component with id {input_id} not a valid input component."
+ )
+ if getattr(block, "stateful", False):
+ processed_input.append(state[input_id])
+ else:
+ if input_id in state:
+ block = state[input_id]
+ inputs_cached = processing_utils.move_files_to_cache(
+ inputs[i], block
+ )
+ if getattr(block, "data_model", None) and inputs_cached is not None:
+ if issubclass(block.data_model, GradioModel): # type: ignore
+ inputs_cached = block.data_model(**inputs_cached) # type: ignore
+ elif issubclass(block.data_model, GradioRootModel): # type: ignore
+ inputs_cached = block.data_model(root=inputs_cached) # type: ignore
+ processed_input.append(block.preprocess(inputs_cached))
+ else:
+ processed_input = inputs
+ return processed_input
+
+ def validate_outputs(self, fn_index: int, predictions: Any | list[Any]):
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ dep_outputs = dependency["outputs"]
+
+ if not isinstance(predictions, (list, tuple)):
+ predictions = [predictions]
+
+ if len(predictions) < len(dep_outputs):
+ name = (
+ f" ({block_fn.name})"
+ if block_fn.name and block_fn.name != ""
+ else ""
+ )
+
+ wanted_args = []
+ received_args = []
+ for output_id in dep_outputs:
+ block = self.blocks[output_id]
+ wanted_args.append(str(block))
+ for pred in predictions:
+ v = f'"{pred}"' if isinstance(pred, str) else str(pred)
+ received_args.append(v)
+
+ wanted = ", ".join(wanted_args)
+ received = ", ".join(received_args)
+
+ raise ValueError(
+ f"""An event handler{name} didn't receive enough output values (needed: {len(dep_outputs)}, received: {len(predictions)}).
+Wanted outputs:
+ [{wanted}]
+Received outputs:
+ [{received}]"""
+ )
+
+ def postprocess_data(
+ self, fn_index: int, predictions: list | dict, state: SessionState | None
+ ):
+ state = state or SessionState(self)
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+ batch = dependency["batch"]
+
+ if isinstance(predictions, dict) and len(predictions) > 0:
+ predictions = convert_component_dict_to_list(
+ dependency["outputs"], predictions
+ )
+
+ if len(dependency["outputs"]) == 1 and not (batch):
+ predictions = [
+ predictions,
+ ]
+
+ self.validate_outputs(fn_index, predictions) # type: ignore
+
+ output = []
+ for i, output_id in enumerate(dependency["outputs"]):
+ try:
+ if predictions[i] is components._Keywords.FINISHED_ITERATING:
+ output.append(None)
+ continue
+ except (IndexError, KeyError) as err:
+ raise ValueError(
+ "Number of output components does not match number "
+ f"of values returned from from function {block_fn.name}"
+ ) from err
+
+ try:
+ block = self.blocks[output_id]
+ except KeyError as e:
+ raise InvalidBlockError(
+ f"Output component with id {output_id} used in {dependency['trigger']}() event not found in this gr.Blocks context. You are allowed to nest gr.Blocks contexts, but there must be a gr.Blocks context that contains all components and events."
+ ) from e
+
+ if getattr(block, "stateful", False):
+ if not utils.is_update(predictions[i]):
+ state[output_id] = predictions[i]
+ output.append(None)
+ else:
+ prediction_value = predictions[i]
+ if utils.is_update(
+ prediction_value
+ ): # if update is passed directly (deprecated), remove Nones
+ prediction_value = utils.delete_none(
+ prediction_value, skip_value=True
+ )
+
+ if isinstance(prediction_value, Block):
+ prediction_value = prediction_value.constructor_args.copy()
+ prediction_value["__type__"] = "update"
+ if utils.is_update(prediction_value):
+ if output_id in state:
+ kwargs = state[output_id].constructor_args.copy()
+ else:
+ kwargs = self.blocks[output_id].constructor_args.copy()
+ kwargs.update(prediction_value)
+ kwargs.pop("value", None)
+ kwargs.pop("__type__")
+ kwargs["render"] = False
+ state[output_id] = self.blocks[output_id].__class__(**kwargs)
+
+ prediction_value = postprocess_update_dict(
+ block=state[output_id],
+ update_dict=prediction_value,
+ postprocess=block_fn.postprocess,
+ )
+ elif block_fn.postprocess:
+ if not isinstance(block, components.Component):
+ raise InvalidComponentError(
+ f"{block.__class__} Component with id {output_id} not a valid output component."
+ )
+ prediction_value = block.postprocess(prediction_value)
+ outputs_cached = processing_utils.move_files_to_cache(
+ prediction_value,
+ block, # type: ignore
+ postprocess=True,
+ )
+ output.append(outputs_cached)
+
+ return output
+
+ def handle_streaming_outputs(
+ self,
+ fn_index: int,
+ data: list,
+ session_hash: str | None,
+ run: int | None,
+ ) -> list:
+ if session_hash is None or run is None:
+ return data
+ if run not in self.pending_streams[session_hash]:
+ self.pending_streams[session_hash][run] = {}
+ stream_run = self.pending_streams[session_hash][run]
+
+ for i, output_id in enumerate(self.dependencies[fn_index]["outputs"]):
+ block = self.blocks[output_id]
+ if isinstance(block, components.StreamingOutput) and block.streaming:
+ first_chunk = output_id not in stream_run
+ binary_data, output_data = block.stream_output(
+ data[i], f"{session_hash}/{run}/{output_id}", first_chunk
+ )
+ if first_chunk:
+ stream_run[output_id] = []
+ self.pending_streams[session_hash][run][output_id].append(binary_data)
+ data[i] = output_data
+ return data
+
+ async def process_api(
+ self,
+ fn_index: int,
+ inputs: list[Any],
+ state: SessionState | None = None,
+ request: routes.Request | list[routes.Request] | None = None,
+ iterator: AsyncIterator | None = None,
+ session_hash: str | None = None,
+ event_id: str | None = None,
+ event_data: EventData | None = None,
+ in_event_listener: bool = True,
+ ) -> dict[str, Any]:
+ """
+ Processes API calls from the frontend. First preprocesses the data,
+ then runs the relevant function, then postprocesses the output.
+ Parameters:
+ fn_index: Index of function to run.
+ inputs: input data received from the frontend
+ state: data stored from stateful components for session (key is input block id)
+ request: the gr.Request object containing information about the network request (e.g. IP address, headers, query parameters, username)
+ iterators: the in-progress iterators for each generator function (key is function index)
+ event_id: id of event that triggered this API call
+ event_data: data associated with the event trigger itself
+ Returns: None
+ """
+ block_fn = self.fns[fn_index]
+ batch = self.dependencies[fn_index]["batch"]
+
+ if batch:
+ max_batch_size = self.dependencies[fn_index]["max_batch_size"]
+ batch_sizes = [len(inp) for inp in inputs]
+ batch_size = batch_sizes[0]
+ if inspect.isasyncgenfunction(block_fn.fn) or inspect.isgeneratorfunction(
+ block_fn.fn
+ ):
+ raise ValueError("Gradio does not support generators in batch mode.")
+ if not all(x == batch_size for x in batch_sizes):
+ raise ValueError(
+ f"All inputs to a batch function must have the same length but instead have sizes: {batch_sizes}."
+ )
+ if batch_size > max_batch_size:
+ raise ValueError(
+ f"Batch size ({batch_size}) exceeds the max_batch_size for this function ({max_batch_size})"
+ )
+
+ inputs = [
+ self.preprocess_data(fn_index, list(i), state) for i in zip(*inputs)
+ ]
+ result = await self.call_function(
+ fn_index,
+ list(zip(*inputs)),
+ None,
+ request,
+ event_id,
+ event_data,
+ in_event_listener,
+ )
+ preds = result["prediction"]
+ data = [
+ self.postprocess_data(fn_index, list(o), state) for o in zip(*preds)
+ ]
+ data = list(zip(*data))
+ is_generating, iterator = None, None
+ else:
+ old_iterator = iterator
+ if old_iterator:
+ inputs = []
+ else:
+ inputs = self.preprocess_data(fn_index, inputs, state)
+ was_generating = old_iterator is not None
+ result = await self.call_function(
+ fn_index,
+ inputs,
+ old_iterator,
+ request,
+ event_id,
+ event_data,
+ in_event_listener,
+ )
+ data = self.postprocess_data(fn_index, result["prediction"], state)
+ is_generating, iterator = result["is_generating"], result["iterator"]
+ if is_generating or was_generating:
+ data = self.handle_streaming_outputs(
+ fn_index,
+ data,
+ session_hash=session_hash,
+ run=id(old_iterator) if was_generating else id(iterator),
+ )
+
+ block_fn.total_runtime += result["duration"]
+ block_fn.total_runs += 1
+ return {
+ "data": data,
+ "is_generating": is_generating,
+ "iterator": iterator,
+ "duration": result["duration"],
+ "average_duration": block_fn.total_runtime / block_fn.total_runs,
+ }
+
+ def create_limiter(self):
+ self.limiter = (
+ None
+ if self.max_threads == 40
+ else CapacityLimiter(total_tokens=self.max_threads)
+ )
+
+ def get_config(self):
+ return {"type": "column"}
+
+ def get_config_file(self):
+ config = {
+ "version": routes.VERSION,
+ "mode": self.mode,
+ "app_id": self.app_id,
+ "dev_mode": self.dev_mode,
+ "analytics_enabled": self.analytics_enabled,
+ "components": [],
+ "css": self.css,
+ "js": self.js,
+ "head": self.head,
+ "title": self.title or "Gradio",
+ "space_id": self.space_id,
+ "enable_queue": True, # launch attributes
+ "show_error": getattr(self, "show_error", False),
+ "show_api": self.show_api,
+ "is_colab": utils.colab_check(),
+ "stylesheets": self.stylesheets,
+ "theme": self.theme.name,
+ "protocol": "sse_v1",
+ }
+
+ def get_layout(block):
+ if not isinstance(block, BlockContext):
+ return {"id": block._id}
+ children_layout = []
+ for child in block.children:
+ children_layout.append(get_layout(child))
+ return {"id": block._id, "children": children_layout}
+
+ config["layout"] = get_layout(self)
+
+ for _id, block in self.blocks.items():
+ props = block.get_config() if hasattr(block, "get_config") else {}
+ block_config = {
+ "id": _id,
+ "type": block.get_block_name(),
+ "props": utils.delete_none(props),
+ }
+ block_config["skip_api"] = block.skip_api
+ block_config["component_class_id"] = getattr(
+ block, "component_class_id", None
+ )
+
+ if not block.skip_api:
+ block_config["api_info"] = block.api_info() # type: ignore
+ block_config["example_inputs"] = block.example_inputs() # type: ignore
+ config["components"].append(block_config)
+ config["dependencies"] = self.dependencies
+ return config
+
+ def __enter__(self):
+ if Context.block is None:
+ Context.root_block = self
+ self.parent = Context.block
+ Context.block = self
+ self.exited = False
+ return self
+
+ def __exit__(self, exc_type: type[BaseException] | None = None, *args):
+ if exc_type is not None:
+ Context.block = None
+ Context.root_block = None
+ return
+ super().fill_expected_parents()
+ Context.block = self.parent
+ # Configure the load events before root_block is reset
+ self.attach_load_events()
+ if self.parent is None:
+ Context.root_block = None
+ else:
+ self.parent.children.extend(self.children)
+ self.config = self.get_config_file()
+ self.app = routes.App.create_app(self)
+ self.progress_tracking = any(block_fn.tracks_progress for block_fn in self.fns)
+ self.exited = True
+
+ def clear(self):
+ """Resets the layout of the Blocks object."""
+ self.blocks = {}
+ self.fns = []
+ self.dependencies = []
+ self.children = []
+ return self
+
+ @document()
+ def queue(
+ self,
+ status_update_rate: float | Literal["auto"] = "auto",
+ api_open: bool | None = None,
+ max_size: int | None = None,
+ concurrency_count: int | None = None,
+ *,
+ default_concurrency_limit: int | None | Literal["not_set"] = "not_set",
+ ):
+ """
+ By enabling the queue you can control when users know their position in the queue, and set a limit on maximum number of events allowed.
+ Parameters:
+ status_update_rate: If "auto", Queue will send status estimations to all clients whenever a job is finished. Otherwise Queue will send status at regular intervals set by this parameter as the number of seconds.
+ api_open: If True, the REST routes of the backend will be open, allowing requests made directly to those endpoints to skip the queue.
+ max_size: The maximum number of events the queue will store at any given moment. If the queue is full, new events will not be added and a user will receive a message saying that the queue is full. If None, the queue size will be unlimited.
+ concurrency_count: Deprecated. Set the concurrency_limit directly on event listeners e.g. btn.click(fn, ..., concurrency_limit=10) or gr.Interface(concurrency_limit=10). If necessary, the total number of workers can be configured via `max_threads` in launch().
+ default_concurrency_limit: The default value of `concurrency_limit` to use for event listeners that don't specify a value. Can be set by environment variable GRADIO_DEFAULT_CONCURRENCY_LIMIT. Defaults to 1 if not set otherwise.
+ Example: (Blocks)
+ with gr.Blocks() as demo:
+ button = gr.Button(label="Generate Image")
+ button.click(fn=image_generator, inputs=gr.Textbox(), outputs=gr.Image())
+ demo.queue(max_size=10)
+ demo.launch()
+ Example: (Interface)
+ demo = gr.Interface(image_generator, gr.Textbox(), gr.Image())
+ demo.queue(max_size=20)
+ demo.launch()
+ """
+ if concurrency_count:
+ raise DeprecationWarning(
+ "concurrency_count has been deprecated. Set the concurrency_limit directly on event listeners e.g. btn.click(fn, ..., concurrency_limit=10) or gr.Interface(concurrency_limit=10). If necessary, the total number of workers can be configured via `max_threads` in launch()."
+ )
+ if api_open is not None:
+ self.api_open = api_open
+ if utils.is_zero_gpu_space():
+ max_size = 1 if max_size is None else max_size
+ self._queue = queueing.Queue(
+ live_updates=status_update_rate == "auto",
+ concurrency_count=self.max_threads,
+ update_intervals=status_update_rate if status_update_rate != "auto" else 1,
+ max_size=max_size,
+ block_fns=self.fns,
+ default_concurrency_limit=default_concurrency_limit,
+ )
+ self.config = self.get_config_file()
+ self.app = routes.App.create_app(self)
+ return self
+
+ def validate_queue_settings(self):
+ for dep in self.dependencies:
+ for i in dep["cancels"]:
+ if not self.queue_enabled_for_fn(i):
+ raise ValueError(
+ "Queue needs to be enabled! "
+ "You may get this error by either 1) passing a function that uses the yield keyword "
+ "into an interface without enabling the queue or 2) defining an event that cancels "
+ "another event without enabling the queue. Both can be solved by calling .queue() "
+ "before .launch()"
+ )
+ if dep["batch"] and dep["queue"] is False:
+ raise ValueError("In order to use batching, the queue must be enabled.")
+
+ def launch(
+ self,
+ inline: bool | None = None,
+ inbrowser: bool = False,
+ share: bool | None = None,
+ debug: bool = False,
+ max_threads: int = 40,
+ auth: Callable | tuple[str, str] | list[tuple[str, str]] | None = None,
+ auth_message: str | None = None,
+ prevent_thread_lock: bool = False,
+ show_error: bool = False,
+ server_name: str | None = None,
+ server_port: int | None = None,
+ *,
+ height: int = 500,
+ width: int | str = "100%",
+ favicon_path: str | None = None,
+ ssl_keyfile: str | None = None,
+ ssl_certfile: str | None = None,
+ ssl_keyfile_password: str | None = None,
+ ssl_verify: bool = True,
+ quiet: bool = False,
+ show_api: bool = True,
+ allowed_paths: list[str] | None = None,
+ blocked_paths: list[str] | None = None,
+ root_path: str | None = None,
+ app_kwargs: dict[str, Any] | None = None,
+ state_session_capacity: int = 10000,
+ share_server_address: str | None = None,
+ share_server_protocol: Literal["http", "https"] | None = None,
+ _frontend: bool = True,
+ ) -> tuple[FastAPI, str, str]:
+ """
+ Launches a simple web server that serves the demo. Can also be used to create a
+ public link used by anyone to access the demo from their browser by setting share=True.
+
+ Parameters:
+ inline: whether to display in the interface inline in an iframe. Defaults to True in python notebooks; False otherwise.
+ inbrowser: whether to automatically launch the interface in a new tab on the default browser.
+ share: whether to create a publicly shareable link for the interface. Creates an SSH tunnel to make your UI accessible from anywhere. If not provided, it is set to False by default every time, except when running in Google Colab. When localhost is not accessible (e.g. Google Colab), setting share=False is not supported.
+ debug: if True, blocks the main thread from running. If running in Google Colab, this is needed to print the errors in the cell output.
+ auth: If provided, username and password (or list of username-password tuples) required to access interface. Can also provide function that takes username and password and returns True if valid login.
+ auth_message: If provided, HTML message provided on login page.
+ prevent_thread_lock: If True, the interface will block the main thread while the server is running.
+ show_error: If True, any errors in the interface will be displayed in an alert modal and printed in the browser console log
+ server_port: will start gradio app on this port (if available). Can be set by environment variable GRADIO_SERVER_PORT. If None, will search for an available port starting at 7860.
+ server_name: to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME. If None, will use "127.0.0.1".
+ max_threads: the maximum number of total threads that the Gradio app can generate in parallel. The default is inherited from the starlette library (currently 40).
+ width: The width in pixels of the iframe element containing the interface (used if inline=True)
+ height: The height in pixels of the iframe element containing the interface (used if inline=True)
+ favicon_path: If a path to a file (.png, .gif, or .ico) is provided, it will be used as the favicon for the web page.
+ ssl_keyfile: If a path to a file is provided, will use this as the private key file to create a local server running on https.
+ ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
+ ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
+ ssl_verify: If False, skips certificate validation which allows self-signed certificates to be used.
+ quiet: If True, suppresses most print statements.
+ show_api: If True, shows the api docs in the footer of the app. Default True.
+ allowed_paths: List of complete filepaths or parent directories that gradio is allowed to serve (in addition to the directory containing the gradio python file). Must be absolute paths. Warning: if you provide directories, any files in these directories or their subdirectories are accessible to all users of your app.
+ blocked_paths: List of complete filepaths or parent directories that gradio is not allowed to serve (i.e. users of your app are not allowed to access). Must be absolute paths. Warning: takes precedence over `allowed_paths` and all other directories exposed by Gradio by default.
+ root_path: The root path (or "mount point") of the application, if it's not served from the root ("/") of the domain. Often used when the application is behind a reverse proxy that forwards requests to the application. For example, if the application is served at "https://example.com/myapp", the `root_path` should be set to "/myapp". Can be set by environment variable GRADIO_ROOT_PATH. Defaults to "".
+ app_kwargs: Additional keyword arguments to pass to the underlying FastAPI app as a dictionary of parameter keys and argument values. For example, `{"docs_url": "/docs"}`
+ state_session_capacity: The maximum number of sessions whose information to store in memory. If the number of sessions exceeds this number, the oldest sessions will be removed. Reduce capacity to reduce memory usage when using gradio.State or returning updated components from functions. Defaults to 10000.
+ share_server_address: Use this to specify a custom FRP server and port for sharing Gradio apps (only applies if share=True). If not provided, will use the default FRP server at https://gradio.live. See https://github.com/huggingface/frp for more information.
+ share_server_protocol: Use this to specify the protocol to use for the share links. Defaults to "https", unless a custom share_server_address is provided, in which case it defaults to "http". If you are using a custom share_server_address and want to use https, you must set this to "https".
+ Returns:
+ app: FastAPI app object that is running the demo
+ local_url: Locally accessible link to the demo
+ share_url: Publicly accessible link to the demo (if share=True, otherwise None)
+ Example: (Blocks)
+ import gradio as gr
+ def reverse(text):
+ return text[::-1]
+ with gr.Blocks() as demo:
+ button = gr.Button(value="Reverse")
+ button.click(reverse, gr.Textbox(), gr.Textbox())
+ demo.launch(share=True, auth=("username", "password"))
+ Example: (Interface)
+ import gradio as gr
+ def reverse(text):
+ return text[::-1]
+ demo = gr.Interface(reverse, "text", "text")
+ demo.launch(share=True, auth=("username", "password"))
+ """
+ if self._is_running_in_reload_thread:
+ # We have already launched the demo
+ return None, None, None # type: ignore
+
+ if not self.exited:
+ self.__exit__()
+
+ if (
+ auth
+ and not callable(auth)
+ and not isinstance(auth[0], tuple)
+ and not isinstance(auth[0], list)
+ ):
+ self.auth = [auth]
+ else:
+ self.auth = auth
+ self.auth_message = auth_message
+ self.show_error = show_error
+ self.height = height
+ self.width = width
+ self.favicon_path = favicon_path
+ self.ssl_verify = ssl_verify
+ self.state_session_capacity = state_session_capacity
+ if root_path is None:
+ self.root_path = os.environ.get("GRADIO_ROOT_PATH", "")
+ else:
+ self.root_path = root_path
+
+ self.show_api = show_api
+
+ self.allowed_paths = allowed_paths or []
+ self.blocked_paths = blocked_paths or []
+
+ if not isinstance(self.allowed_paths, list):
+ raise ValueError("`allowed_paths` must be a list of directories.")
+ if not isinstance(self.blocked_paths, list):
+ raise ValueError("`blocked_paths` must be a list of directories.")
+
+ self.validate_queue_settings()
+
+ self.config = self.get_config_file()
+ self.max_threads = max_threads
+ self._queue.max_thread_count = max_threads
+
+ if self.is_running:
+ if not isinstance(self.local_url, str):
+ raise ValueError(f"Invalid local_url: {self.local_url}")
+ if not (quiet):
+ print(
+ "Rerunning server... use `close()` to stop if you need to change `launch()` parameters.\n----"
+ )
+ else:
+ if wasm_utils.IS_WASM:
+ server_name = "xxx"
+ server_port = 99999
+ local_url = ""
+ server = None
+
+ # In the Wasm environment, we only need the app object
+ # which the frontend app will directly communicate with through the Worker API,
+ # and we don't need to start a server.
+ # So we just create the app object and register it here,
+ # and avoid using `networking.start_server` that would start a server that don't work in the Wasm env.
+ from gradio.routes import App
+
+ app = App.create_app(self, app_kwargs=app_kwargs)
+ wasm_utils.register_app(app)
+ else:
+ (
+ server_name,
+ server_port,
+ local_url,
+ app,
+ server,
+ ) = networking.start_server(
+ self,
+ server_name,
+ server_port,
+ ssl_keyfile,
+ ssl_certfile,
+ ssl_keyfile_password,
+ app_kwargs=app_kwargs,
+ )
+ self.server_name = server_name
+ self.local_url = local_url
+ self.server_port = server_port
+ self.server_app = (
+ self.app
+ ) = app # server_app is included for backwards compatibility
+ self.server = server
+ self.is_running = True
+ self.is_colab = utils.colab_check()
+ self.is_kaggle = utils.kaggle_check()
+ self.share_server_address = share_server_address
+ self.share_server_protocol = share_server_protocol or (
+ "http" if share_server_address is not None else "https"
+ )
+
+ self.protocol = (
+ "https"
+ if self.local_url.startswith("https") or self.is_colab
+ else "http"
+ )
+ if not wasm_utils.IS_WASM and not self.is_colab:
+ print(
+ strings.en["RUNNING_LOCALLY_SEPARATED"].format(
+ self.protocol, self.server_name, self.server_port
+ )
+ )
+
+ self._queue.set_server_app(self.server_app)
+
+ if not wasm_utils.IS_WASM:
+ # Cannot run async functions in background other than app's scope.
+ # Workaround by triggering the app endpoint
+ httpx.get(f"{self.local_url}startup-events", verify=ssl_verify)
+ else:
+ # NOTE: One benefit of the code above dispatching `startup_events()` via a self HTTP request is
+ # that `self._queue.start()` is called in another thread which is managed by the HTTP server, `uvicorn`
+ # so all the asyncio tasks created by the queue runs in an event loop in that thread and
+ # will be cancelled just by stopping the server.
+ # In contrast, in the Wasm env, we can't do that because `threading` is not supported and all async tasks will run in the same event loop, `pyodide.webloop.WebLoop` in the main thread.
+ # So we need to manually cancel them. See `self.close()`..
+ self.startup_events()
+
+ utils.launch_counter()
+ self.is_sagemaker = utils.sagemaker_check()
+ if share is None:
+ if self.is_colab:
+ if not quiet:
+ print(
+ "Setting queue=True in a Colab notebook requires sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ elif self.is_kaggle:
+ if not quiet:
+ print(
+ "Kaggle notebooks require sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ elif self.is_sagemaker:
+ if not quiet:
+ print(
+ "Sagemaker notebooks may require sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ else:
+ self.share = False
+ else:
+ self.share = share
+
+ # If running in a colab or not able to access localhost,
+ # a shareable link must be created.
+ if (
+ _frontend
+ and not wasm_utils.IS_WASM
+ and not networking.url_ok(self.local_url)
+ and not self.share
+ ):
+ raise ValueError(
+ "When localhost is not accessible, a shareable link must be created. Please set share=True or check your proxy settings to allow access to localhost."
+ )
+
+ if self.is_colab and not quiet:
+ if debug:
+ print(strings.en["COLAB_DEBUG_TRUE"])
+ else:
+ print(strings.en["COLAB_DEBUG_FALSE"])
+ if not self.share:
+ print(strings.en["COLAB_WARNING"].format(self.server_port))
+
+ if self.share:
+ if self.space_id:
+ warnings.warn(
+ "Setting share=True is not supported on Hugging Face Spaces"
+ )
+ self.share = False
+ if wasm_utils.IS_WASM:
+ warnings.warn(
+ "Setting share=True is not supported in the Wasm environment"
+ )
+ self.share = False
+
+ if self.share:
+ try:
+ if self.share_url is None:
+ share_url = networking.setup_tunnel(
+ local_host=self.server_name,
+ local_port=self.server_port,
+ share_token=self.share_token,
+ share_server_address=self.share_server_address,
+ )
+ parsed_url = urlparse(share_url)
+ self.share_url = urlunparse(
+ (self.share_server_protocol,) + parsed_url[1:]
+ )
+ print(strings.en["SHARE_LINK_DISPLAY"].format(self.share_url))
+ if not (quiet):
+ print(strings.en["SHARE_LINK_MESSAGE"])
+ except (RuntimeError, httpx.ConnectError):
+ if self.analytics_enabled:
+ analytics.error_analytics("Not able to set up tunnel")
+ self.share_url = None
+ self.share = False
+ if Path(BINARY_PATH).exists():
+ print(strings.en["COULD_NOT_GET_SHARE_LINK"])
+ else:
+ print(
+ strings.en["COULD_NOT_GET_SHARE_LINK_MISSING_FILE"].format(
+ BINARY_PATH,
+ BINARY_URL,
+ BINARY_FILENAME,
+ BINARY_FOLDER,
+ )
+ )
+ else:
+ if not quiet and not wasm_utils.IS_WASM:
+ print(strings.en["PUBLIC_SHARE_TRUE"])
+ self.share_url = None
+
+ if inbrowser and not wasm_utils.IS_WASM:
+ link = self.share_url if self.share and self.share_url else self.local_url
+ webbrowser.open(link)
+
+ # Check if running in a Python notebook in which case, display inline
+ if inline is None:
+ inline = utils.ipython_check()
+ if inline:
+ try:
+ from IPython.display import HTML, Javascript, display # type: ignore
+
+ if self.share and self.share_url:
+ while not networking.url_ok(self.share_url):
+ time.sleep(0.25)
+ artifact = HTML(
+ f'
'
+ )
+
+ elif self.is_colab:
+ # modified from /usr/local/lib/python3.7/dist-packages/google/colab/output/_util.py within Colab environment
+ code = """(async (port, path, width, height, cache, element) => {
+ if (!google.colab.kernel.accessAllowed && !cache) {
+ return;
+ }
+ element.appendChild(document.createTextNode(''));
+ const url = await google.colab.kernel.proxyPort(port, {cache});
+
+ const external_link = document.createElement('div');
+ external_link.innerHTML = `
+
+ `;
+ element.appendChild(external_link);
+
+ const iframe = document.createElement('iframe');
+ iframe.src = new URL(path, url).toString();
+ iframe.height = height;
+ iframe.allow = "autoplay; camera; microphone; clipboard-read; clipboard-write;"
+ iframe.width = width;
+ iframe.style.border = 0;
+ element.appendChild(iframe);
+ })""" + "({port}, {path}, {width}, {height}, {cache}, window.element)".format(
+ port=json.dumps(self.server_port),
+ path=json.dumps("/"),
+ width=json.dumps(self.width),
+ height=json.dumps(self.height),
+ cache=json.dumps(False),
+ )
+
+ artifact = Javascript(code)
+ else:
+ artifact = HTML(
+ f'
'
+ )
+ self.artifact = artifact
+ display(artifact)
+ except ImportError:
+ pass
+
+ if getattr(self, "analytics_enabled", False):
+ data = {
+ "launch_method": "browser" if inbrowser else "inline",
+ "is_google_colab": self.is_colab,
+ "is_sharing_on": self.share,
+ "share_url": self.share_url,
+ "enable_queue": True,
+ "server_name": server_name,
+ "server_port": server_port,
+ "is_space": self.space_id is not None,
+ "mode": self.mode,
+ }
+ analytics.launched_analytics(self, data)
+
+ # Block main thread if debug==True
+ if debug or int(os.getenv("GRADIO_DEBUG", 0)) == 1 and not wasm_utils.IS_WASM:
+ self.block_thread()
+ # Block main thread if running in a script to stop script from exiting
+ is_in_interactive_mode = bool(getattr(sys, "ps1", sys.flags.interactive))
+
+ if (
+ not prevent_thread_lock
+ and not is_in_interactive_mode
+ # In the Wasm env, we don't have to block the main thread because the server won't be shut down after the execution finishes.
+ # Moreover, we MUST NOT do it because there is only one thread in the Wasm env and blocking it will stop the subsequent code from running.
+ and not wasm_utils.IS_WASM
+ ):
+ self.block_thread()
+
+ return TupleNoPrint((self.server_app, self.local_url, self.share_url)) # type: ignore
+
+ def integrate(
+ self,
+ comet_ml=None,
+ wandb: ModuleType | None = None,
+ mlflow: ModuleType | None = None,
+ ) -> None:
+ """
+ A catch-all method for integrating with other libraries. This method should be run after launch()
+ Parameters:
+ comet_ml: If a comet_ml Experiment object is provided, will integrate with the experiment and appear on Comet dashboard
+ wandb: If the wandb module is provided, will integrate with it and appear on WandB dashboard
+ mlflow: If the mlflow module is provided, will integrate with the experiment and appear on ML Flow dashboard
+ """
+ analytics_integration = ""
+ if comet_ml is not None:
+ analytics_integration = "CometML"
+ comet_ml.log_other("Created from", "Gradio")
+ if self.share_url is not None:
+ comet_ml.log_text(f"gradio: {self.share_url}")
+ comet_ml.end()
+ elif self.local_url:
+ comet_ml.log_text(f"gradio: {self.local_url}")
+ comet_ml.end()
+ else:
+ raise ValueError("Please run `launch()` first.")
+ if wandb is not None:
+ analytics_integration = "WandB"
+ if self.share_url is not None:
+ wandb.log(
+ {
+ "Gradio panel": wandb.Html(
+ ''
+ )
+ }
+ )
+ else:
+ print(
+ "The WandB integration requires you to "
+ "`launch(share=True)` first."
+ )
+ if mlflow is not None:
+ analytics_integration = "MLFlow"
+ if self.share_url is not None:
+ mlflow.log_param("Gradio Interface Share Link", self.share_url)
+ else:
+ mlflow.log_param("Gradio Interface Local Link", self.local_url)
+ if self.analytics_enabled and analytics_integration:
+ data = {"integration": analytics_integration}
+ analytics.integration_analytics(data)
+
+ def close(self, verbose: bool = True) -> None:
+ """
+ Closes the Interface that was launched and frees the port.
+ """
+ try:
+ if wasm_utils.IS_WASM:
+ # NOTE:
+ # Normally, queue-related async tasks (e.g. continuous events created by `gr.Blocks.load(..., every=interval)`, whose async tasks are started at the `/queue/data` endpoint function)
+ # are running in an event loop in the server thread,
+ # so they will be cancelled by `self.server.close()` below.
+ # However, in the Wasm env, we don't have the `server` and
+ # all async tasks are running in the same event loop, `pyodide.webloop.WebLoop` in the main thread,
+ # so we have to cancel them explicitly so that these tasks won't run after a new app is launched.
+ self._queue._cancel_asyncio_tasks()
+ self.server_app._cancel_asyncio_tasks()
+ self._queue.close()
+ if self.server:
+ self.server.close()
+ self.is_running = False
+ # So that the startup events (starting the queue)
+ # happen the next time the app is launched
+ self.app.startup_events_triggered = False
+ if verbose:
+ print(f"Closing server running on port: {self.server_port}")
+ except (AttributeError, OSError): # can't close if not running
+ pass
+
+ def block_thread(
+ self,
+ ) -> None:
+ """Block main thread until interrupted by user."""
+ try:
+ while True:
+ time.sleep(0.1)
+ except (KeyboardInterrupt, OSError):
+ print("Keyboard interruption in main thread... closing server.")
+ if self.server:
+ self.server.close()
+ for tunnel in CURRENT_TUNNELS:
+ tunnel.kill()
+
+ def attach_load_events(self):
+ """Add a load event for every component whose initial value should be randomized."""
+ if Context.root_block:
+ for component in Context.root_block.blocks.values():
+ if (
+ isinstance(component, components.Component)
+ and component.load_event_to_attach
+ ):
+ load_fn, every = component.load_event_to_attach
+ # Use set_event_trigger to avoid ambiguity between load class/instance method
+
+ dep = self.set_event_trigger(
+ [EventListenerMethod(self, "load")],
+ load_fn,
+ None,
+ component,
+ no_target=True,
+ # If every is None, for sure skip the queue
+ # else, let the enable_queue parameter take precedence
+ # this will raise a nice error message is every is used
+ # without queue
+ queue=False if every is None else None,
+ every=every,
+ )[0]
+ component.load_event = dep
+
+ def startup_events(self):
+ """Events that should be run when the app containing this block starts up."""
+ self._queue.start()
+ # So that processing can resume in case the queue was stopped
+ self._queue.stopped = False
+ self.create_limiter()
+
+ def queue_enabled_for_fn(self, fn_index: int):
+ return self.dependencies[fn_index]["queue"] is not False
+
+ def get_api_info(self):
+ """
+ Gets the information needed to generate the API docs from a Blocks.
+ """
+ config = self.config
+ api_info = {"named_endpoints": {}, "unnamed_endpoints": {}}
+
+ for dependency in config["dependencies"]:
+ if (
+ not dependency["backend_fn"]
+ or not dependency["show_api"]
+ or dependency["api_name"] is False
+ ):
+ continue
+
+ dependency_info = {"parameters": [], "returns": []}
+ skip_endpoint = False
+
+ inputs = dependency["inputs"]
+ for i in inputs:
+ for component in config["components"]:
+ if component["id"] == i:
+ break
+ else:
+ skip_endpoint = True # if component not found, skip endpoint
+ break
+ type = component["type"]
+ if self.blocks[component["id"]].skip_api:
+ continue
+ label = component["props"].get("label", f"parameter_{i}")
+ # The config has the most specific API info (taking into account the parameters
+ # of the component), so we use that if it exists. Otherwise, we fallback to the
+ # Serializer's API info.
+ comp = self.get_component(component["id"])
+ assert isinstance(comp, components.Component)
+ info = comp.api_info()
+ example = comp.example_inputs()
+ python_type = client_utils.json_schema_to_python_type(info)
+ dependency_info["parameters"].append(
+ {
+ "label": label,
+ "type": info,
+ "python_type": {
+ "type": python_type,
+ "description": info.get("description", ""),
+ },
+ "component": type.capitalize(),
+ "example_input": example,
+ }
+ )
+
+ outputs = dependency["outputs"]
+ for o in outputs:
+ for component in config["components"]:
+ if component["id"] == o:
+ break
+ else:
+ skip_endpoint = True # if component not found, skip endpoint
+ break
+ type = component["type"]
+ if self.blocks[component["id"]].skip_api:
+ continue
+ label = component["props"].get("label", f"value_{o}")
+ comp = self.get_component(component["id"])
+ assert isinstance(comp, components.Component)
+ info = comp.api_info()
+ example = comp.example_inputs()
+ python_type = client_utils.json_schema_to_python_type(info)
+ dependency_info["returns"].append(
+ {
+ "label": label,
+ "type": info,
+ "python_type": {
+ "type": python_type,
+ "description": info.get("description", ""),
+ },
+ "component": type.capitalize(),
+ }
+ )
+
+ if not skip_endpoint:
+ api_info["named_endpoints"][
+ f"/{dependency['api_name']}"
+ ] = dependency_info
+
+ return api_info
diff --git a/gradio/blocks_events.py b/gradio/blocks_events.py
new file mode 100644
index 0000000000000000000000000000000000000000..9da3f14ab2f1dbdbc357fe1bb0776430a0bbb7ec
--- /dev/null
+++ b/gradio/blocks_events.py
@@ -0,0 +1,30 @@
+from __future__ import annotations
+
+from gradio.component_meta import create_or_modify_pyi
+from gradio.events import EventListener, Events
+
+BLOCKS_EVENTS: list[EventListener | str] = [Events.load]
+
+
+class BlocksMeta(type):
+ def __new__(cls, name, bases, attrs):
+ for event in BLOCKS_EVENTS:
+ trigger = (
+ event
+ if isinstance(event, EventListener)
+ else EventListener(event_name=event)
+ ).copy()
+ trigger.set_doc(component=name)
+ attrs[event] = trigger.listener
+ component_class = super().__new__(cls, name, bases, attrs)
+ create_or_modify_pyi(BlocksEvents, "BlocksEvents", BLOCKS_EVENTS)
+ return component_class
+
+
+class BlocksEvents:
+ """
+ This class is used to hold the events for the Blocks component. It is populated dynamically
+ by the BlocksMeta metaclass.
+ """
+
+ pass
diff --git a/gradio/chat_interface.py b/gradio/chat_interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..e092b53a91524828d0d3c0f03a73c3e6bc12d13a
--- /dev/null
+++ b/gradio/chat_interface.py
@@ -0,0 +1,570 @@
+"""
+This file defines a useful high-level abstraction to build Gradio chatbots: ChatInterface.
+"""
+
+
+from __future__ import annotations
+
+import inspect
+from typing import AsyncGenerator, Callable, Literal, Union, cast
+
+import anyio
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import Blocks
+from gradio.components import (
+ Button,
+ Chatbot,
+ Component,
+ Markdown,
+ State,
+ Textbox,
+ get_component_instance,
+)
+from gradio.events import Dependency, on
+from gradio.helpers import create_examples as Examples # noqa: N812
+from gradio.helpers import special_args
+from gradio.layouts import Accordion, Column, Group, Row
+from gradio.routes import Request
+from gradio.themes import ThemeClass as Theme
+from gradio.utils import SyncToAsyncIterator, async_iteration
+
+set_documentation_group("chatinterface")
+
+
+@document()
+class ChatInterface(Blocks):
+ """
+ ChatInterface is Gradio's high-level abstraction for creating chatbot UIs, and allows you to create
+ a web-based demo around a chatbot model in a few lines of code. Only one parameter is required: fn, which
+ takes a function that governs the response of the chatbot based on the user input and chat history. Additional
+ parameters can be used to control the appearance and behavior of the demo.
+
+ Example:
+ import gradio as gr
+
+ def echo(message, history):
+ return message
+
+ demo = gr.ChatInterface(fn=echo, examples=["hello", "hola", "merhaba"], title="Echo Bot")
+ demo.launch()
+ Demos: chatinterface_random_response, chatinterface_streaming_echo
+ Guides: creating-a-chatbot-fast, sharing-your-app
+ """
+
+ def __init__(
+ self,
+ fn: Callable,
+ *,
+ chatbot: Chatbot | None = None,
+ textbox: Textbox | None = None,
+ additional_inputs: str | Component | list[str | Component] | None = None,
+ additional_inputs_accordion_name: str | None = None,
+ additional_inputs_accordion: str | Accordion | None = None,
+ examples: list[str] | None = None,
+ cache_examples: bool | None = None,
+ title: str | None = None,
+ description: str | None = None,
+ theme: Theme | str | None = None,
+ css: str | None = None,
+ js: str | None = None,
+ head: str | None = None,
+ analytics_enabled: bool | None = None,
+ submit_btn: str | None | Button = "Submit",
+ stop_btn: str | None | Button = "Stop",
+ retry_btn: str | None | Button = "🔄 Retry",
+ undo_btn: str | None | Button = "↩️ Undo",
+ clear_btn: str | None | Button = "🗑️ Clear",
+ autofocus: bool = True,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ ):
+ """
+ Parameters:
+ fn: The function to wrap the chat interface around. Should accept two parameters: a string input message and list of two-element lists of the form [[user_message, bot_message], ...] representing the chat history, and return a string response. See the Chatbot documentation for more information on the chat history format.
+ chatbot: An instance of the gr.Chatbot component to use for the chat interface, if you would like to customize the chatbot properties. If not provided, a default gr.Chatbot component will be created.
+ textbox: An instance of the gr.Textbox component to use for the chat interface, if you would like to customize the textbox properties. If not provided, a default gr.Textbox component will be created.
+ additional_inputs: An instance or list of instances of gradio components (or their string shortcuts) to use as additional inputs to the chatbot. If components are not already rendered in a surrounding Blocks, then the components will be displayed under the chatbot, in an accordion.
+ additional_inputs_accordion_name: Deprecated. Will be removed in a future version of Gradio. Use the `additional_inputs_accordion` parameter instead.
+ additional_inputs_accordion: If a string is provided, this is the label of the `gr.Accordion` to use to contain additional inputs. A `gr.Accordion` object can be provided as well to configure other properties of the container holding the additional inputs. Defaults to a `gr.Accordion(label="Additional Inputs", open=False)`. This parameter is only used if `additional_inputs` is provided.
+ examples: Sample inputs for the function; if provided, appear below the chatbot and can be clicked to populate the chatbot input.
+ cache_examples: If True, caches examples in the server for fast runtime in examples. The default option in HuggingFace Spaces is True. The default option elsewhere is False.
+ title: a title for the interface; if provided, appears above chatbot in large font. Also used as the tab title when opened in a browser window.
+ description: a description for the interface; if provided, appears above the chatbot and beneath the title in regular font. Accepts Markdown and HTML content.
+ theme: Theme to use, loaded from gradio.themes.
+ css: Custom css as a string or path to a css file. This css will be included in the demo webpage.
+ js: Custom js or path to js file to run when demo is first loaded. This javascript will be included in the demo webpage.
+ head: Custom html to insert into the head of the demo webpage. This can be used to add custom meta tags, scripts, stylesheets, etc. to the page.
+ analytics_enabled: Whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable if defined, or default to True.
+ submit_btn: Text to display on the submit button. If None, no button will be displayed. If a Button object, that button will be used.
+ stop_btn: Text to display on the stop button, which replaces the submit_btn when the submit_btn or retry_btn is clicked and response is streaming. Clicking on the stop_btn will halt the chatbot response. If set to None, stop button functionality does not appear in the chatbot. If a Button object, that button will be used as the stop button.
+ retry_btn: Text to display on the retry button. If None, no button will be displayed. If a Button object, that button will be used.
+ undo_btn: Text to display on the delete last button. If None, no button will be displayed. If a Button object, that button will be used.
+ clear_btn: Text to display on the clear button. If None, no button will be displayed. If a Button object, that button will be used.
+ autofocus: If True, autofocuses to the textbox when the page loads.
+ concurrency_limit: If set, this is the maximum number of chatbot submissions that can be running simultaneously. Can be set to None to mean no limit (any number of chatbot submissions can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `.queue()`, which is 1 by default).
+ """
+ super().__init__(
+ analytics_enabled=analytics_enabled,
+ mode="chat_interface",
+ css=css,
+ title=title or "Gradio",
+ theme=theme,
+ js=js,
+ head=head,
+ )
+ self.concurrency_limit = concurrency_limit
+ self.fn = fn
+ self.is_async = inspect.iscoroutinefunction(
+ self.fn
+ ) or inspect.isasyncgenfunction(self.fn)
+ self.is_generator = inspect.isgeneratorfunction(
+ self.fn
+ ) or inspect.isasyncgenfunction(self.fn)
+ self.examples = examples
+ if self.space_id and cache_examples is None:
+ self.cache_examples = True
+ else:
+ self.cache_examples = cache_examples or False
+ self.buttons: list[Button | None] = []
+
+ if additional_inputs:
+ if not isinstance(additional_inputs, list):
+ additional_inputs = [additional_inputs]
+ self.additional_inputs = [
+ get_component_instance(i)
+ for i in additional_inputs # type: ignore
+ ]
+ else:
+ self.additional_inputs = []
+ if additional_inputs_accordion_name is not None:
+ print(
+ "The `additional_inputs_accordion_name` parameter is deprecated and will be removed in a future version of Gradio. Use the `additional_inputs_accordion` parameter instead."
+ )
+ self.additional_inputs_accordion_params = {
+ "label": additional_inputs_accordion_name
+ }
+ if additional_inputs_accordion is None:
+ self.additional_inputs_accordion_params = {
+ "label": "Additional Inputs",
+ "open": False,
+ }
+ elif isinstance(additional_inputs_accordion, str):
+ self.additional_inputs_accordion_params = {
+ "label": additional_inputs_accordion
+ }
+ elif isinstance(additional_inputs_accordion, Accordion):
+ self.additional_inputs_accordion_params = (
+ additional_inputs_accordion.recover_kwargs(
+ additional_inputs_accordion.get_config()
+ )
+ )
+ else:
+ raise ValueError(
+ f"The `additional_inputs_accordion` parameter must be a string or gr.Accordion, not {type(additional_inputs_accordion)}"
+ )
+
+ with self:
+ if title:
+ Markdown(
+ f"{self.title} "
+ )
+ if description:
+ Markdown(description)
+
+ with Column(variant="panel"):
+ if chatbot:
+ self.chatbot = chatbot.render()
+ else:
+ self.chatbot = Chatbot(label="Chatbot")
+
+ with Group():
+ with Row():
+ if textbox:
+ textbox.container = False
+ textbox.show_label = False
+ textbox_ = textbox.render()
+ assert isinstance(textbox_, Textbox)
+ self.textbox = textbox_
+ else:
+ self.textbox = Textbox(
+ container=False,
+ show_label=False,
+ label="Message",
+ placeholder="Type a message...",
+ scale=7,
+ autofocus=autofocus,
+ )
+ if submit_btn is not None:
+ if isinstance(submit_btn, Button):
+ submit_btn.render()
+ elif isinstance(submit_btn, str):
+ submit_btn = Button(
+ submit_btn,
+ variant="primary",
+ scale=1,
+ min_width=150,
+ )
+ else:
+ raise ValueError(
+ f"The submit_btn parameter must be a gr.Button, string, or None, not {type(submit_btn)}"
+ )
+ if stop_btn is not None:
+ if isinstance(stop_btn, Button):
+ stop_btn.visible = False
+ stop_btn.render()
+ elif isinstance(stop_btn, str):
+ stop_btn = Button(
+ stop_btn,
+ variant="stop",
+ visible=False,
+ scale=1,
+ min_width=150,
+ )
+ else:
+ raise ValueError(
+ f"The stop_btn parameter must be a gr.Button, string, or None, not {type(stop_btn)}"
+ )
+ self.buttons.extend([submit_btn, stop_btn]) # type: ignore
+
+ with Row():
+ for btn in [retry_btn, undo_btn, clear_btn]:
+ if btn is not None:
+ if isinstance(btn, Button):
+ btn.render()
+ elif isinstance(btn, str):
+ btn = Button(btn, variant="secondary")
+ else:
+ raise ValueError(
+ f"All the _btn parameters must be a gr.Button, string, or None, not {type(btn)}"
+ )
+ self.buttons.append(btn) # type: ignore
+
+ self.fake_api_btn = Button("Fake API", visible=False)
+ self.fake_response_textbox = Textbox(
+ label="Response", visible=False
+ )
+ (
+ self.submit_btn,
+ self.stop_btn,
+ self.retry_btn,
+ self.undo_btn,
+ self.clear_btn,
+ ) = self.buttons
+
+ if examples:
+ if self.is_generator:
+ examples_fn = self._examples_stream_fn
+ else:
+ examples_fn = self._examples_fn
+
+ self.examples_handler = Examples(
+ examples=examples,
+ inputs=[self.textbox] + self.additional_inputs,
+ outputs=self.chatbot,
+ fn=examples_fn,
+ )
+
+ any_unrendered_inputs = any(
+ not inp.is_rendered for inp in self.additional_inputs
+ )
+ if self.additional_inputs and any_unrendered_inputs:
+ with Accordion(**self.additional_inputs_accordion_params): # type: ignore
+ for input_component in self.additional_inputs:
+ if not input_component.is_rendered:
+ input_component.render()
+
+ # The example caching must happen after the input components have rendered
+ if cache_examples:
+ client_utils.synchronize_async(self.examples_handler.cache)
+
+ self.saved_input = State()
+ self.chatbot_state = (
+ State(self.chatbot.value) if self.chatbot.value else State([])
+ )
+
+ self._setup_events()
+ self._setup_api()
+
+ def _setup_events(self) -> None:
+ submit_fn = self._stream_fn if self.is_generator else self._submit_fn
+ submit_triggers = (
+ [self.textbox.submit, self.submit_btn.click]
+ if self.submit_btn
+ else [self.textbox.submit]
+ )
+ submit_event = (
+ on(
+ submit_triggers,
+ self._clear_and_save_textbox,
+ [self.textbox],
+ [self.textbox, self.saved_input],
+ show_api=False,
+ queue=False,
+ )
+ .then(
+ self._display_input,
+ [self.saved_input, self.chatbot_state],
+ [self.chatbot, self.chatbot_state],
+ show_api=False,
+ queue=False,
+ )
+ .then(
+ submit_fn,
+ [self.saved_input, self.chatbot_state] + self.additional_inputs,
+ [self.chatbot, self.chatbot_state],
+ show_api=False,
+ concurrency_limit=cast(
+ Union[int, Literal["default"], None], self.concurrency_limit
+ ),
+ )
+ )
+ self._setup_stop_events(submit_triggers, submit_event)
+
+ if self.retry_btn:
+ retry_event = (
+ self.retry_btn.click(
+ self._delete_prev_fn,
+ [self.chatbot_state],
+ [self.chatbot, self.saved_input, self.chatbot_state],
+ show_api=False,
+ queue=False,
+ )
+ .then(
+ self._display_input,
+ [self.saved_input, self.chatbot_state],
+ [self.chatbot, self.chatbot_state],
+ show_api=False,
+ queue=False,
+ )
+ .then(
+ submit_fn,
+ [self.saved_input, self.chatbot_state] + self.additional_inputs,
+ [self.chatbot, self.chatbot_state],
+ show_api=False,
+ concurrency_limit=cast(
+ Union[int, Literal["default"], None], self.concurrency_limit
+ ),
+ )
+ )
+ self._setup_stop_events([self.retry_btn.click], retry_event)
+
+ if self.undo_btn:
+ self.undo_btn.click(
+ self._delete_prev_fn,
+ [self.chatbot_state],
+ [self.chatbot, self.saved_input, self.chatbot_state],
+ show_api=False,
+ queue=False,
+ ).then(
+ lambda x: x,
+ [self.saved_input],
+ [self.textbox],
+ show_api=False,
+ queue=False,
+ )
+
+ if self.clear_btn:
+ self.clear_btn.click(
+ lambda: ([], [], None),
+ None,
+ [self.chatbot, self.chatbot_state, self.saved_input],
+ queue=False,
+ show_api=False,
+ )
+
+ def _setup_stop_events(
+ self, event_triggers: list[Callable], event_to_cancel: Dependency
+ ) -> None:
+ if self.stop_btn and self.is_generator:
+ if self.submit_btn:
+ for event_trigger in event_triggers:
+ event_trigger(
+ lambda: (
+ Button(visible=False),
+ Button(visible=True),
+ ),
+ None,
+ [self.submit_btn, self.stop_btn],
+ show_api=False,
+ queue=False,
+ )
+ event_to_cancel.then(
+ lambda: (Button(visible=True), Button(visible=False)),
+ None,
+ [self.submit_btn, self.stop_btn],
+ show_api=False,
+ queue=False,
+ )
+ else:
+ for event_trigger in event_triggers:
+ event_trigger(
+ lambda: Button(visible=True),
+ None,
+ [self.stop_btn],
+ show_api=False,
+ queue=False,
+ )
+ event_to_cancel.then(
+ lambda: Button(visible=False),
+ None,
+ [self.stop_btn],
+ show_api=False,
+ queue=False,
+ )
+ self.stop_btn.click(
+ None,
+ None,
+ None,
+ cancels=event_to_cancel,
+ show_api=False,
+ )
+
+ def _setup_api(self) -> None:
+ api_fn = self._api_stream_fn if self.is_generator else self._api_submit_fn
+
+ self.fake_api_btn.click(
+ api_fn,
+ [self.textbox, self.chatbot_state] + self.additional_inputs,
+ [self.textbox, self.chatbot_state],
+ api_name="chat",
+ concurrency_limit=cast(
+ Union[int, Literal["default"], None], self.concurrency_limit
+ ),
+ )
+
+ def _clear_and_save_textbox(self, message: str) -> tuple[str, str]:
+ return "", message
+
+ def _display_input(
+ self, message: str, history: list[list[str | None]]
+ ) -> tuple[list[list[str | None]], list[list[str | None]]]:
+ history.append([message, None])
+ return history, history
+
+ async def _submit_fn(
+ self,
+ message: str,
+ history_with_input: list[list[str | None]],
+ request: Request,
+ *args,
+ ) -> tuple[list[list[str | None]], list[list[str | None]]]:
+ history = history_with_input[:-1]
+ inputs, _, _ = special_args(
+ self.fn, inputs=[message, history, *args], request=request
+ )
+
+ if self.is_async:
+ response = await self.fn(*inputs)
+ else:
+ response = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+
+ history.append([message, response])
+ return history, history
+
+ async def _stream_fn(
+ self,
+ message: str,
+ history_with_input: list[list[str | None]],
+ request: Request,
+ *args,
+ ) -> AsyncGenerator:
+ history = history_with_input[:-1]
+ inputs, _, _ = special_args(
+ self.fn, inputs=[message, history, *args], request=request
+ )
+
+ if self.is_async:
+ generator = self.fn(*inputs)
+ else:
+ generator = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+ generator = SyncToAsyncIterator(generator, self.limiter)
+ try:
+ first_response = await async_iteration(generator)
+ update = history + [[message, first_response]]
+ yield update, update
+ except StopIteration:
+ update = history + [[message, None]]
+ yield update, update
+ async for response in generator:
+ update = history + [[message, response]]
+ yield update, update
+
+ async def _api_submit_fn(
+ self, message: str, history: list[list[str | None]], request: Request, *args
+ ) -> tuple[str, list[list[str | None]]]:
+ inputs, _, _ = special_args(
+ self.fn, inputs=[message, history, *args], request=request
+ )
+
+ if self.is_async:
+ response = await self.fn(*inputs)
+ else:
+ response = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+ history.append([message, response])
+ return response, history
+
+ async def _api_stream_fn(
+ self, message: str, history: list[list[str | None]], request: Request, *args
+ ) -> AsyncGenerator:
+ inputs, _, _ = special_args(
+ self.fn, inputs=[message, history, *args], request=request
+ )
+
+ if self.is_async:
+ generator = self.fn(*inputs)
+ else:
+ generator = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+ generator = SyncToAsyncIterator(generator, self.limiter)
+ try:
+ first_response = await async_iteration(generator)
+ yield first_response, history + [[message, first_response]]
+ except StopIteration:
+ yield None, history + [[message, None]]
+ async for response in generator:
+ yield response, history + [[message, response]]
+
+ async def _examples_fn(self, message: str, *args) -> list[list[str | None]]:
+ inputs, _, _ = special_args(self.fn, inputs=[message, [], *args], request=None)
+
+ if self.is_async:
+ response = await self.fn(*inputs)
+ else:
+ response = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+ return [[message, response]]
+
+ async def _examples_stream_fn(
+ self,
+ message: str,
+ *args,
+ ) -> AsyncGenerator:
+ inputs, _, _ = special_args(self.fn, inputs=[message, [], *args], request=None)
+
+ if self.is_async:
+ generator = self.fn(*inputs)
+ else:
+ generator = await anyio.to_thread.run_sync(
+ self.fn, *inputs, limiter=self.limiter
+ )
+ generator = SyncToAsyncIterator(generator, self.limiter)
+ async for response in generator:
+ yield [[message, response]]
+
+ def _delete_prev_fn(
+ self, history: list[list[str | None]]
+ ) -> tuple[list[list[str | None]], str, list[list[str | None]]]:
+ try:
+ message, _ = history.pop()
+ except IndexError:
+ message = ""
+ return history, message or "", history
diff --git a/gradio/cli/__init__.py b/gradio/cli/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1fca2de36be27dd42cd23053121f9849126ee502
--- /dev/null
+++ b/gradio/cli/__init__.py
@@ -0,0 +1,4 @@
+from .cli import cli, deploy
+from .commands import custom_component
+
+__all__ = ["cli", "deploy", "custom_component"]
diff --git a/gradio/cli/cli.py b/gradio/cli/cli.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3eaa8e0b7190139a6a48f16b0f5daeef16dadf1
--- /dev/null
+++ b/gradio/cli/cli.py
@@ -0,0 +1,39 @@
+import sys
+
+import typer
+from gradio_client.cli import deploy_discord # type: ignore
+from rich.console import Console
+
+from .commands import custom_component, deploy, print_environment_info, reload
+
+app = typer.Typer()
+app.command("environment", help="Print Gradio environment information.")(
+ print_environment_info
+)
+app.command(
+ "deploy",
+ help="Deploy a Gradio app to Spaces. Must be called within the directory you would like to deploy.",
+)(deploy)
+app.command("deploy-discord", help="Deploy a Gradio app to Discord.")(
+ deploy_discord.main
+)
+
+
+def cli():
+ args = sys.argv[1:]
+ if len(args) == 0:
+ raise ValueError("No file specified.")
+ if args[0] in {"deploy", "environment", "deploy-discord"}:
+ app()
+ elif args[0] in {"cc", "component"}:
+ sys.argv = sys.argv[1:]
+ custom_component()
+ elif args[0] in {"build", "dev", "create", "show", "publish", "install"}:
+ try:
+ error = f"gradio {args[0]} is not a valid command. Did you mean `gradio cc {args[0]}` or `gradio component {args[0]}`?."
+ raise ValueError(error)
+ except ValueError:
+ console = Console()
+ console.print_exception()
+ else:
+ typer.run(reload)
diff --git a/gradio/cli/commands/__init__.py b/gradio/cli/commands/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e4b20dbfc7bbe22b1ee1fe4805735e76b64056eb
--- /dev/null
+++ b/gradio/cli/commands/__init__.py
@@ -0,0 +1,6 @@
+from .cli_env_info import print_environment_info
+from .components import app as custom_component
+from .deploy_space import deploy
+from .reload import main as reload
+
+__all__ = ["deploy", "reload", "print_environment_info", "custom_component"]
diff --git a/gradio/cli/commands/cli_env_info.py b/gradio/cli/commands/cli_env_info.py
new file mode 100644
index 0000000000000000000000000000000000000000..5156f3a4494088e6d0f74e7f44ef5110873944b6
--- /dev/null
+++ b/gradio/cli/commands/cli_env_info.py
@@ -0,0 +1,41 @@
+""" This file is the part of 'gradio/cli.py' for printing the environment info
+for the cli command 'gradio environment'
+"""
+import platform
+from importlib import metadata
+
+from rich import print
+
+
+def print_environment_info():
+ """Print Gradio environment information."""
+ print("Gradio Environment Information:\n------------------------------")
+ print("Operating System:", platform.system())
+
+ for package_name in ["gradio", "gradio_client"]:
+ try:
+ package_version = metadata.version(package_name)
+ print(f"{package_name} version:", package_version)
+ except metadata.PackageNotFoundError:
+ print(f"{package_name} package is not installed.")
+ print("\n------------------------------------------------")
+ for package_name in ["gradio", "gradio_client"]:
+ try:
+ dist = metadata.distribution(package_name)
+ print(f"{package_name} dependencies in your environment:\n")
+ if dist.requires is not None:
+ for req in dist.requires:
+ req_base_name = (
+ req.split(">")[0]
+ .split("<")[0]
+ .split("~")[0]
+ .split("[")[0]
+ .split("!")[0]
+ )
+ try:
+ print(f"{req_base_name}: {metadata.version(req_base_name)}")
+ except metadata.PackageNotFoundError:
+ print(f"{req_base_name} is not installed.")
+ print("\n")
+ except metadata.PackageNotFoundError:
+ print(f"{package_name} package is not installed.")
diff --git a/gradio/cli/commands/components/__init__.py b/gradio/cli/commands/components/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..34f275ed3c9d7894766f1b188d9d5e13327f24bb
--- /dev/null
+++ b/gradio/cli/commands/components/__init__.py
@@ -0,0 +1,3 @@
+from .app import app
+
+__all__ = ["app"]
diff --git a/gradio/cli/commands/components/_create_utils.py b/gradio/cli/commands/components/_create_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef401ef615438e9d8bce847ceceddb1b662ca333
--- /dev/null
+++ b/gradio/cli/commands/components/_create_utils.py
@@ -0,0 +1,378 @@
+from __future__ import annotations
+
+import dataclasses
+import inspect
+import json
+import re
+import shutil
+import textwrap
+from pathlib import Path
+from typing import Literal
+
+import gradio
+
+
+def _in_test_dir():
+ """Check if the current working directory ends with gradio/js/preview/test."""
+ return Path.cwd().parts[-4:] == ("gradio", "js", "preview", "test")
+
+
+default_demo_code = """
+example = {name}().example_inputs()
+
+demo = gr.Interface(
+ lambda x:x,
+ {name}(), # interactive version of your component
+ {name}(), # static version of your component
+ # examples=[[example]], # uncomment this line to view the "example version" of your component
+)
+"""
+
+static_only_demo_code = """
+example = {name}().example_inputs()
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ {name}(label="Blank"), # blank component
+ {name}(value=example, label="Populated"), # populated component
+"""
+
+layout_demo_code = """
+with gr.Blocks() as demo:
+ with {name}():
+ gr.Textbox(value="foo", interactive=True)
+ gr.Number(value=10, interactive=True)
+"""
+
+fallback_code = """
+with gr.Blocks() as demo:
+ gr.Markdown("# Change the value (keep it JSON) and the front-end will update automatically.")
+ {name}(value={{"message": "Hello from Gradio!"}}, label="Static")
+"""
+
+
+PATTERN_RE = r"gradio-template-\w+"
+PATTERN = "gradio-template-{template}"
+
+
+@dataclasses.dataclass
+class ComponentFiles:
+ template: str
+ demo_code: str = default_demo_code
+ python_file_name: str = ""
+ js_dir: str = ""
+
+ def __post_init__(self):
+ self.js_dir = self.js_dir or self.template.lower()
+ self.python_file_name = self.python_file_name or f"{self.template.lower()}.py"
+
+
+OVERRIDES = {
+ "AnnotatedImage": ComponentFiles(
+ template="AnnotatedImage",
+ python_file_name="annotated_image.py",
+ demo_code=static_only_demo_code,
+ ),
+ "HighlightedText": ComponentFiles(
+ template="HighlightedText",
+ python_file_name="highlighted_text.py",
+ demo_code=static_only_demo_code,
+ ),
+ "Chatbot": ComponentFiles(template="Chatbot", demo_code=static_only_demo_code),
+ "Gallery": ComponentFiles(template="Gallery", demo_code=static_only_demo_code),
+ "HTML": ComponentFiles(template="HTML", demo_code=static_only_demo_code),
+ "Label": ComponentFiles(template="Label", demo_code=static_only_demo_code),
+ "Markdown": ComponentFiles(template="Markdown", demo_code=static_only_demo_code),
+ "Fallback": ComponentFiles(template="Fallback", demo_code=fallback_code),
+ "Plot": ComponentFiles(template="Plot", demo_code=static_only_demo_code),
+ "BarPlot": ComponentFiles(
+ template="BarPlot",
+ python_file_name="bar_plot.py",
+ js_dir="plot",
+ demo_code=static_only_demo_code,
+ ),
+ "ClearButton": ComponentFiles(
+ template="ClearButton",
+ python_file_name="clear_button.py",
+ js_dir="button",
+ demo_code=static_only_demo_code,
+ ),
+ "ColorPicker": ComponentFiles(
+ template="ColorPicker", python_file_name="color_picker.py"
+ ),
+ "DuplicateButton": ComponentFiles(
+ template="DuplicateButton",
+ python_file_name="duplicate_button.py",
+ js_dir="button",
+ demo_code=static_only_demo_code,
+ ),
+ "FileExplorer": ComponentFiles(
+ template="FileExplorer",
+ python_file_name="file_explorer.py",
+ js_dir="fileexplorer",
+ demo_code=textwrap.dedent(
+ """
+ import os
+
+ with gr.Blocks() as demo:
+ {name}(value=os.path.dirname(__file__).split(os.sep))
+ """
+ ),
+ ),
+ "LinePlot": ComponentFiles(
+ template="LinePlot",
+ python_file_name="line_plot.py",
+ js_dir="plot",
+ demo_code=static_only_demo_code,
+ ),
+ "LogoutButton": ComponentFiles(
+ template="LogoutButton",
+ python_file_name="logout_button.py",
+ js_dir="button",
+ demo_code=static_only_demo_code,
+ ),
+ "LoginButton": ComponentFiles(
+ template="LoginButton",
+ python_file_name="login_button.py",
+ js_dir="button",
+ demo_code=static_only_demo_code,
+ ),
+ "ScatterPlot": ComponentFiles(
+ template="ScatterPlot",
+ python_file_name="scatter_plot.py",
+ js_dir="plot",
+ demo_code=static_only_demo_code,
+ ),
+ "UploadButton": ComponentFiles(
+ template="UploadButton",
+ python_file_name="upload_button.py",
+ demo_code=static_only_demo_code,
+ ),
+ "JSON": ComponentFiles(
+ template="JSON",
+ python_file_name="json_component.py",
+ demo_code=static_only_demo_code,
+ ),
+ "Row": ComponentFiles(
+ template="Row",
+ demo_code=layout_demo_code,
+ ),
+ "Column": ComponentFiles(
+ template="Column",
+ demo_code=layout_demo_code,
+ ),
+ "Tabs": ComponentFiles(
+ template="Tabs",
+ demo_code=textwrap.dedent(
+ """
+ with gr.Blocks() as demo:
+ with {name}():
+ with gr.Tab("Tab 1"):
+ gr.Textbox(value="foo", interactive=True)
+ with gr.Tab("Tab 2"):
+ gr.Number(value=10, interactive=True)
+ """
+ ),
+ ),
+ "Group": ComponentFiles(
+ template="Group",
+ demo_code=layout_demo_code,
+ ),
+ "Accordion": ComponentFiles(
+ template="Accordion",
+ demo_code=textwrap.dedent(
+ """
+ with gr.Blocks() as demo:
+ with {name}(label="Accordion"):
+ gr.Textbox(value="foo", interactive=True)
+ gr.Number(value=10, interactive=True)
+ """
+ ),
+ ),
+ "Model3D": ComponentFiles(
+ template="Model3D",
+ js_dir="model3D",
+ demo_code=textwrap.dedent(
+ """
+ with gr.Blocks() as demo:
+ {name}()
+ """
+ ),
+ ),
+}
+
+
+def _get_component_code(template: str | None) -> ComponentFiles:
+ template = template or "Fallback"
+ if template in OVERRIDES:
+ return OVERRIDES[template]
+ else:
+ return ComponentFiles(
+ python_file_name=f"{template.lower()}.py",
+ js_dir=template.lower(),
+ template=template,
+ )
+
+
+def _get_js_dependency_version(name: str, local_js_dir: Path) -> str:
+ package_json = json.loads(
+ Path(local_js_dir / name.split("/")[1] / "package.json").read_text()
+ )
+ return package_json["version"]
+
+
+def _modify_js_deps(
+ package_json: dict,
+ key: Literal["dependencies", "devDependencies"],
+ gradio_dir: Path,
+):
+ for dep in package_json.get(key, []):
+ # if curent working directory is the gradio repo, use the local version of the dependency'
+ if not _in_test_dir() and dep.startswith("@gradio/"):
+ package_json[key][dep] = _get_js_dependency_version(
+ dep, gradio_dir / "_frontend_code"
+ )
+ return package_json
+
+
+def delete_contents(directory: str | Path) -> None:
+ """Delete all contents of a directory, but not the directory itself."""
+ path = Path(directory)
+ for child in path.glob("*"):
+ if child.is_file():
+ child.unlink()
+ elif child.is_dir():
+ shutil.rmtree(child)
+
+
+def _create_frontend(
+ name: str, component: ComponentFiles, directory: Path, package_name: str
+):
+ frontend = directory / "frontend"
+ frontend.mkdir(exist_ok=True)
+
+ p = Path(inspect.getfile(gradio)).parent
+
+ def ignore(s, names):
+ ignored = []
+ for n in names:
+ if (
+ n.startswith("CHANGELOG")
+ or n.startswith("README.md")
+ or ".test." in n
+ or ".stories." in n
+ or ".spec." in n
+ ):
+ ignored.append(n)
+ return ignored
+
+ shutil.copytree(
+ str(p / "_frontend_code" / component.js_dir),
+ frontend,
+ dirs_exist_ok=True,
+ ignore=ignore,
+ )
+ source_package_json = json.loads(Path(frontend / "package.json").read_text())
+ source_package_json["name"] = package_name
+ source_package_json = _modify_js_deps(source_package_json, "dependencies", p)
+ source_package_json = _modify_js_deps(source_package_json, "devDependencies", p)
+ (frontend / "package.json").write_text(json.dumps(source_package_json, indent=2))
+
+
+def _replace_old_class_name(old_class_name: str, new_class_name: str, content: str):
+ pattern = rf"(?<=\b)(?>", package_name).replace(
+ "<>", PATTERN.format(template=component.template)
+ )
+ pyproject_dest.write_text(pyproject_contents)
+
+ demo_dir = directory / "demo"
+ demo_dir.mkdir(exist_ok=True, parents=True)
+
+ (demo_dir / "app.py").write_text(
+ f"""
+import gradio as gr
+from {package_name} import {name}
+
+{component.demo_code.format(name=name)}
+
+if __name__ == "__main__":
+ demo.launch()
+"""
+ )
+ (demo_dir / "__init__.py").touch()
+
+ init = backend / "__init__.py"
+ init.write_text(
+ f"""
+from .{name.lower()} import {name}
+
+__all__ = ['{name}']
+"""
+ )
+
+ p = Path(inspect.getfile(gradio)).parent
+ python_file = backend / f"{name.lower()}.py"
+
+ shutil.copy(
+ str(p / module / component.python_file_name),
+ str(python_file),
+ )
+
+ source_pyi_file = p / module / component.python_file_name.replace(".py", ".pyi")
+ pyi_file = backend / f"{name.lower()}.pyi"
+ if source_pyi_file.exists():
+ shutil.copy(str(source_pyi_file), str(pyi_file))
+
+ content = python_file.read_text()
+ python_file.write_text(_replace_old_class_name(component.template, name, content))
+ if pyi_file.exists():
+ pyi_content = pyi_file.read_text()
+ pyi_file.write_text(
+ _replace_old_class_name(component.template, name, pyi_content)
+ )
diff --git a/gradio/cli/commands/components/_docs_assets.py b/gradio/cli/commands/components/_docs_assets.py
new file mode 100644
index 0000000000000000000000000000000000000000..524fd937fef997fd85bb6d0c6d854a38178776b2
--- /dev/null
+++ b/gradio/cli/commands/components/_docs_assets.py
@@ -0,0 +1,158 @@
+css = """html {
+ font-family: Inter;
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 1.5;
+ -webkit-text-size-adjust: 100%;
+ background: #fff;
+ color: #323232;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
+}
+
+:root {
+ --space: 1;
+ --vspace: calc(var(--space) * 1rem);
+ --vspace-0: calc(3 * var(--space) * 1rem);
+ --vspace-1: calc(2 * var(--space) * 1rem);
+ --vspace-2: calc(1.5 * var(--space) * 1rem);
+ --vspace-3: calc(0.5 * var(--space) * 1rem);
+}
+
+.app {
+ max-width: 748px !important;
+}
+
+.prose p {
+ margin: var(--vspace) 0;
+ line-height: var(--vspace * 2);
+ font-size: 1rem;
+}
+
+code {
+ font-family: "Inconsolata", sans-serif;
+ font-size: 16px;
+}
+
+h1,
+h1 code {
+ font-weight: 400;
+ line-height: calc(2.5 / var(--space) * var(--vspace));
+}
+
+h1 code {
+ background: none;
+ border: none;
+ letter-spacing: 0.05em;
+ padding-bottom: 5px;
+ position: relative;
+ padding: 0;
+}
+
+h2 {
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
+ line-height: 1em;
+}
+
+h3,
+h3 code {
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
+ line-height: 1em;
+}
+
+h4,
+h5,
+h6 {
+ margin: var(--vspace-3) 0 var(--vspace-3) 0;
+ line-height: var(--vspace);
+}
+
+.bigtitle,
+h1,
+h1 code {
+ font-size: calc(8px * 4.5);
+ word-break: break-word;
+}
+
+.title,
+h2,
+h2 code {
+ font-size: calc(8px * 3.375);
+ font-weight: lighter;
+ word-break: break-word;
+ border: none;
+ background: none;
+}
+
+.subheading1,
+h3,
+h3 code {
+ font-size: calc(8px * 1.8);
+ font-weight: 600;
+ border: none;
+ background: none;
+ letter-spacing: 0.1em;
+ text-transform: uppercase;
+}
+
+h2 code {
+ padding: 0;
+ position: relative;
+ letter-spacing: 0.05em;
+}
+
+blockquote {
+ font-size: calc(8px * 1.1667);
+ font-style: italic;
+ line-height: calc(1.1667 * var(--vspace));
+ margin: var(--vspace-2) var(--vspace-2);
+}
+
+.subheading2,
+h4 {
+ font-size: calc(8px * 1.4292);
+ text-transform: uppercase;
+ font-weight: 600;
+}
+
+.subheading3,
+h5 {
+ font-size: calc(8px * 1.2917);
+ line-height: calc(1.2917 * var(--vspace));
+
+ font-weight: lighter;
+ text-transform: uppercase;
+ letter-spacing: 0.15em;
+}
+
+h6 {
+ font-size: calc(8px * 1.1667);
+ font-size: 1.1667em;
+ font-weight: normal;
+ font-style: italic;
+ font-family: "le-monde-livre-classic-byol", serif !important;
+ letter-spacing: 0px !important;
+}
+
+#start .md > *:first-child {
+ margin-top: 0;
+}
+
+h2 + h3 {
+ margin-top: 0;
+}
+
+.md hr {
+ border: none;
+ border-top: 1px solid var(--block-border-color);
+ margin: var(--vspace-2) 0 var(--vspace-2) 0;
+}
+.prose ul {
+ margin: var(--vspace-2) 0 var(--vspace-1) 0;
+}
+
+.gap {
+ gap: 0;
+}
+"""
diff --git a/gradio/cli/commands/components/_docs_utils.py b/gradio/cli/commands/components/_docs_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..e49a423afde9b8cc30e89ad997bc720b4c6c2abe
--- /dev/null
+++ b/gradio/cli/commands/components/_docs_utils.py
@@ -0,0 +1,937 @@
+from __future__ import annotations
+
+import inspect
+import re
+import types
+import typing
+from subprocess import PIPE, Popen
+
+
+def find_first_non_return_key(some_dict):
+ """Finds the first key in a dictionary that is not "return"."""
+ for key, value in some_dict.items():
+ if key != "return":
+ return value
+ return None
+
+
+def format(code: str, type: str):
+ """Formats code using ruff."""
+ if type == "value":
+ code = f"value = {code}"
+
+ ruff_args = ["ruff", "format", "-", "--line-length=60"]
+
+ process = Popen(
+ ruff_args,
+ stdin=PIPE,
+ stdout=PIPE,
+ stderr=PIPE,
+ universal_newlines=True,
+ )
+
+ formatted_code, err = process.communicate(input=str(code))
+
+ if type == "value":
+ formatted_code = re.sub(
+ r"^\s*value =\s*", "", formatted_code, flags=re.MULTILINE
+ )
+
+ stripped_source = re.search(r"^\s*\((.*)\)\s*$", formatted_code, re.DOTALL)
+
+ if stripped_source:
+ return stripped_source.group(1).strip()
+ elif formatted_code.strip() == "":
+ return code
+ else:
+ return formatted_code.strip()
+
+
+def get_param_name(param):
+ """Gets the name of a parameter."""
+
+ if isinstance(param, str):
+ return f'"{param}"'
+ if inspect.isclass(param) and param.__module__ == "builtins":
+ p = getattr(param, "__name__", None)
+ if p is None and inspect.isclass(param):
+ p = f"{param.__module__}.{param.__name__}"
+ return p
+
+ if inspect.isclass(param):
+ return f"{param.__module__}.{param.__name__}"
+
+ param_name = getattr(param, "__name__", None)
+
+ if param_name is None:
+ param_name = str(param)
+
+ return param_name
+
+
+def format_none(value):
+ """Formats None and NonType values."""
+ if value is None or value is type(None) or value == "None" or value == "NoneType":
+ return "None"
+ return value
+
+
+def format_value(value):
+ """Formats a value."""
+ if value is None:
+ return "None"
+ if isinstance(value, str):
+ return f'"{value}"'
+ return str(value)
+
+
+def get_parameter_docstring(docstring: str, parameter_name: str):
+ """Gets the docstring for a parameter."""
+ pattern = rf"\b{parameter_name}\b:[ \t]*(.*?)(?=\n|$)"
+
+ match = re.search(pattern, docstring, flags=re.DOTALL)
+ if match:
+ return match.group(1).strip()
+
+ return None
+
+
+def get_return_docstring(docstring: str):
+ """Gets the docstring for a return value."""
+ pattern = r"\bReturn(?:s){0,1}\b:[ \t\n]*(.*?)(?=\n|$)"
+
+ match = re.search(pattern, docstring, flags=re.DOTALL | re.IGNORECASE)
+ if match:
+ return match.group(1).strip()
+
+ return None
+
+
+def add_value(obj: dict, key: str, value: typing.Any):
+ """Adds a value to a dictionary."""
+ type = "value" if key == "default" else "type"
+
+ obj[key] = format(value, type)
+
+ return obj
+
+
+def set_deep(dictionary: dict, keys: list[str], value: typing.Any):
+ """Sets a value in a nested dictionary for a key path that may not exist"""
+ for key in keys[:-1]:
+ dictionary = dictionary.setdefault(key, {})
+ dictionary[keys[-1]] = value
+
+
+def get_deep(dictionary: dict, keys: list[str], default=None):
+ """Gets a value from a nested dictionary without erroring if the key doesn't exist."""
+ try:
+ for key in keys:
+ dictionary = dictionary[key]
+ return dictionary
+ except KeyError:
+ return default
+
+
+def get_type_arguments(type_hint) -> tuple:
+ """Gets the type arguments for a type hint."""
+ if hasattr(type_hint, "__args__"):
+ return type_hint.__args__
+ elif hasattr(type_hint, "__extra__"):
+ return type_hint.__extra__.__args__
+ else:
+ return typing.get_args(type_hint)
+
+
+def get_container_name(arg):
+ """Gets a human readable name for a type."""
+
+ # This is a bit of a hack to get the generic type for python 3.8
+ typing_genericalias = getattr(typing, "_GenericAlias", None)
+ types_genericalias = getattr(types, "GenericAlias", None)
+ types_uniontype = getattr(types, "UnionType", None)
+ if types_genericalias is None:
+ raise ValueError(
+ """Unable to find GenericAlias type. This is likely because you are using an older version of python. Please upgrade to python 3.10 or higher."""
+ )
+
+ generic_type_tuple = (
+ (types_genericalias,)
+ if typing_genericalias is None
+ else (types_genericalias, typing_genericalias)
+ )
+
+ if inspect.isclass(arg):
+ return arg.__name__
+ if isinstance(arg, (generic_type_tuple)):
+ return arg.__origin__.__name__
+ elif types_uniontype and isinstance(arg, types_uniontype):
+ return "Union"
+ elif getattr(arg, "__origin__", None) is typing.Literal:
+ return "Literal"
+
+ else:
+ return str(arg)
+
+
+def format_type(_type: list[typing.Any], current=None):
+ """Pretty formats a possibly nested type hint."""
+
+ s = []
+ _current = None
+ for t in _type:
+ if isinstance(t, str):
+ _current = format_none(t)
+ continue
+
+ elif isinstance(t, list):
+ if len(t) == 0:
+ continue
+ s.append(f"{format_type(t, _current)}")
+ else:
+ s.append(t)
+ if len(s) == 0:
+ return _current
+ elif _current == "Literal" or _current == "Union":
+ return "| ".join(s)
+ else:
+ return f"{_current}[{','.join(s)}]"
+
+
+def get_type_hints(param, module, ignore=None):
+ """Gets the type hints for a parameter."""
+
+ def extract_args(
+ arg,
+ module_name_prefix,
+ additional_interfaces,
+ user_fn_refs: list[str],
+ append=True,
+ arg_of=None,
+ ):
+ """Recursively extracts the arguments from a type hint."""
+ arg_names = []
+ args = get_type_arguments(arg)
+
+ # These are local classes that are used in types
+ if inspect.isclass(arg) and arg.__module__.startswith(module_name_prefix):
+ # get sourcecode for the class
+
+ source_code = inspect.getsource(arg)
+ source_code = format(
+ re.sub(r"(\"\"\".*?\"\"\")", "", source_code, flags=re.DOTALL), "other"
+ )
+
+ if arg_of is not None:
+ refs = get_deep(additional_interfaces, [arg_of, "refs"])
+
+ if refs is None:
+ refs = [arg.__name__]
+ elif isinstance(refs, list) and arg.__name__ not in refs:
+ refs.append(arg.__name__)
+
+ set_deep(additional_interfaces, [arg_of, "refs"], refs)
+
+ if get_deep(additional_interfaces, [arg.__name__, "source"]) is None:
+ set_deep(additional_interfaces, [arg.__name__, "source"], source_code)
+
+ for field_type in typing.get_type_hints(arg).values():
+ # We want to recursively extract the source code for the fields but we don't want to add them to the list of arguments
+ new_args = extract_args(
+ field_type,
+ module_name_prefix,
+ additional_interfaces,
+ user_fn_refs,
+ False,
+ arg.__name__,
+ )
+
+ if len(new_args) > 0:
+ arg_names.append(new_args)
+
+ if append:
+ arg_names.append(arg.__name__)
+ if arg.__name__ not in user_fn_refs:
+ user_fn_refs.append(arg.__name__)
+ elif len(args) > 0:
+ if append:
+ arg_names.append(get_container_name(arg))
+ for inner_arg in list(args):
+ new_args = extract_args(
+ inner_arg,
+ module_name_prefix,
+ additional_interfaces,
+ user_fn_refs,
+ append,
+ arg_of,
+ )
+
+ if len(new_args) > 0:
+ arg_names.append(new_args)
+ else:
+ if append:
+ arg_names.append(get_param_name(arg))
+ return arg_names
+
+ module_name_prefix = module.__name__ + "."
+ additional_interfaces = {}
+ user_fn_refs = []
+
+ args = extract_args(
+ param,
+ module_name_prefix,
+ additional_interfaces,
+ user_fn_refs,
+ True,
+ )
+
+ formatted_type = format_type(args)
+
+ return (formatted_type, additional_interfaces, user_fn_refs)
+
+
+def extract_docstrings(module):
+ docs = {}
+ global_type_mode = "complex"
+ for name, obj in inspect.getmembers(module):
+ # filter out the builtins etc
+ if name.startswith("_"):
+ continue
+ # this could be expanded but i think is ok for now
+ if inspect.isfunction(obj) or inspect.isclass(obj):
+ docs[name] = {}
+
+ main_docstring = inspect.getdoc(obj) or ""
+ cleaned_docstring = str.join(
+ "\n",
+ [s for s in main_docstring.split("\n") if not re.match(r"^\S+:", s)],
+ )
+
+ docs[name]["description"] = cleaned_docstring
+ docs[name]["members"] = {}
+ docs["__meta__"] = {"additional_interfaces": {}}
+ for member_name, member in inspect.getmembers(obj):
+ if inspect.ismethod(member) or inspect.isfunction(member):
+ # we are are only interested in these methods
+ if (
+ member_name != "__init__"
+ and member_name != "preprocess"
+ and member_name != "postprocess"
+ ):
+ continue
+
+ docs[name]["members"][member_name] = {}
+
+ member_docstring = inspect.getdoc(member) or ""
+ type_mode = "complex"
+ try:
+ hints = typing.get_type_hints(member)
+ except Exception:
+ type_mode = "simple"
+ hints = member.__annotations__
+ global_type_mode = "simple"
+
+ signature = inspect.signature(member)
+
+ # we iterate over the parameters and get the type information
+ for param_name, param in hints.items():
+ if (
+ param_name == "return" and member_name == "postprocess"
+ ) or (param_name != "return" and member_name == "preprocess"):
+ continue
+
+ if type_mode == "simple":
+ arg_names = hints.get(param_name, "")
+ additional_interfaces = {}
+ user_fn_refs = []
+ else:
+ (
+ arg_names,
+ additional_interfaces,
+ user_fn_refs,
+ ) = get_type_hints(param, module)
+
+ # These interfaces belong to the whole module, so we add them 'globally' for later
+ docs["__meta__"]["additional_interfaces"].update(
+ additional_interfaces
+ )
+
+ docs[name]["members"][member_name][param_name] = {}
+
+ if param_name == "return":
+ docstring = get_return_docstring(member_docstring)
+ else:
+ docstring = get_parameter_docstring(
+ member_docstring, param_name
+ )
+
+ add_value(
+ docs[name]["members"][member_name][param_name],
+ "type",
+ arg_names,
+ )
+
+ if signature.parameters.get(param_name, None) is not None:
+ default_value = signature.parameters[param_name].default
+ if default_value is not inspect._empty:
+ add_value(
+ docs[name]["members"][member_name][param_name],
+ "default",
+ format_value(default_value),
+ )
+
+ docs[name]["members"][member_name][param_name][
+ "description"
+ ] = docstring
+
+ # We just want to normalise the arg name to 'value' for the preprocess and postprocess methods
+ if member_name == "postprocess" or member_name == "preprocess":
+ docs[name]["members"][member_name][
+ "value"
+ ] = find_first_non_return_key(
+ docs[name]["members"][member_name]
+ )
+ additional_refs = get_deep(
+ docs, ["__meta__", "user_fn_refs", name]
+ )
+ if additional_refs is None:
+ set_deep(
+ docs,
+ ["__meta__", "user_fn_refs", name],
+ set(user_fn_refs),
+ )
+ else:
+ additional_refs = set(additional_refs)
+ additional_refs.update(user_fn_refs)
+ set_deep(
+ docs,
+ ["__meta__", "user_fn_refs", name],
+ additional_refs,
+ )
+ if member_name == "EVENTS":
+ docs[name]["events"] = {}
+ if isinstance(member, list):
+ for event in member:
+ docs[name]["events"][str(event)] = {
+ "type": None,
+ "default": None,
+ "description": event.doc.replace(
+ "{{ component }}", name
+ ),
+ }
+ final_user_fn_refs = get_deep(docs, ["__meta__", "user_fn_refs", name])
+ if final_user_fn_refs is not None:
+ set_deep(docs, ["__meta__", "user_fn_refs", name], list(final_user_fn_refs))
+
+ return (docs, global_type_mode)
+
+
+class AdditionalInterface(typing.TypedDict):
+ refs: list[str]
+ source: str
+
+
+def make_js(
+ interfaces: dict[str, AdditionalInterface] | None = None,
+ user_fn_refs: dict[str, list[str]] | None = None,
+):
+ """Makes the javascript code for the additional interfaces."""
+ js_obj_interfaces = "{"
+ if interfaces is not None:
+ for interface_name, interface in interfaces.items():
+ js_obj_interfaces += f"""
+ {interface_name}: {interface.get("refs", None) or "[]"}, """
+ js_obj_interfaces += "}"
+
+ js_obj_user_fn_refs = "{"
+ if user_fn_refs is not None:
+ for class_name, refs in user_fn_refs.items():
+ js_obj_user_fn_refs += f"""
+ {class_name}: {refs}, """
+
+ js_obj_user_fn_refs += "}"
+
+ return rf"""function() {{
+ const refs = {js_obj_interfaces};
+ const user_fn_refs = {js_obj_user_fn_refs};
+ requestAnimationFrame(() => {{
+
+ Object.entries(user_fn_refs).forEach(([key, refs]) => {{
+ if (refs.length > 0) {{
+ const el = document.querySelector(`.${{key}}-user-fn`);
+ if (!el) return;
+ refs.forEach(ref => {{
+ el.innerHTML = el.innerHTML.replace(
+ new RegExp("\\b"+ref+"\\b", "g"),
+ `${{ref}} `
+ );
+ }})
+ }}
+ }})
+
+ Object.entries(refs).forEach(([key, refs]) => {{
+ if (refs.length > 0) {{
+ const el = document.querySelector(`.${{key}}`);
+ if (!el) return;
+ refs.forEach(ref => {{
+ el.innerHTML = el.innerHTML.replace(
+ new RegExp("\\b"+ref+"\\b", "g"),
+ `${{ref}} `
+ );
+ }})
+ }}
+ }})
+ }})
+}}
+"""
+
+
+def render_additional_interfaces(interfaces):
+ """Renders additional helper classes or types that were extracted earlier."""
+
+ source = ""
+ for interface_name, interface in interfaces.items():
+ source += f"""
+ code_{interface_name} = gr.Markdown(\"\"\"
+## `{interface_name}`
+```python
+{interface["source"]}
+```\"\"\", elem_classes=["md-custom", "{interface_name}"], header_links=True)
+"""
+ return source
+
+
+def render_additional_interfaces_markdown(interfaces):
+ """Renders additional helper classes or types that were extracted earlier."""
+
+ source = ""
+ for interface_name, interface in interfaces.items():
+ source += f"""
+## `{interface_name}`
+```python
+{interface["source"]}
+```
+"""
+ return source
+
+
+def render_version_badge(pypi_exists, local_version, name):
+ """Renders a version badge for the package. PyPi badge if it exists, otherwise a static badge."""
+ if pypi_exists:
+ return f""" """
+ else:
+ return f""" """
+
+
+def render_github_badge(repo):
+ """Renders a github badge for the package if a repo is specified."""
+ if repo is None:
+ return ""
+ else:
+ return f""" """
+
+
+def render_discuss_badge(space):
+ """Renders a discuss badge for the package if a space is specified."""
+ if space is None:
+ return ""
+ else:
+ return f""" """
+
+
+def render_class_events(events: dict, name):
+ """Renders the events for a class."""
+ if len(events) == 0:
+ return ""
+
+ else:
+ return f"""
+ gr.Markdown("### Events")
+ gr.ParamViewer(value=_docs["{name}"]["events"], linkify={["Event"]})
+
+"""
+
+
+def make_user_fn(
+ class_name,
+ user_fn_input_type,
+ user_fn_input_description,
+ user_fn_output_type,
+ user_fn_output_description,
+):
+ """Makes the user function for the class."""
+ if (
+ user_fn_input_type is None
+ and user_fn_output_type is None
+ and user_fn_input_description is None
+ and user_fn_output_description is None
+ ):
+ return ""
+
+ md = """
+ gr.Markdown(\"\"\"
+
+### User function
+
+The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
+
+- When used as an Input, the component only impacts the input signature of the user function.
+- When used as an output, the component only impacts the return signature of the user function.
+
+The code snippet below is accurate in cases where the component is used as both an input and an output.
+
+"""
+
+ md += (
+ f"- **As input:** Is passed, {format_description(user_fn_input_description)}\n"
+ if user_fn_input_description
+ else ""
+ )
+
+ md += (
+ f"- **As output:** Should return, {format_description(user_fn_output_description)}"
+ if user_fn_output_description
+ else ""
+ )
+
+ if user_fn_input_type is not None or user_fn_output_type is not None:
+ md += f"""
+
+ ```python
+def predict(
+ value: {user_fn_input_type or "Unknown"}
+) -> {user_fn_output_type or "Unknown"}:
+ return value
+```"""
+ return f"""{md}
+\"\"\", elem_classes=["md-custom", "{class_name}-user-fn"], header_links=True)
+"""
+
+
+def format_description(description):
+ description = description[0].lower() + description[1:]
+ description = description.rstrip(".") + "."
+ return description
+
+
+def make_user_fn_markdown(
+ user_fn_input_type,
+ user_fn_input_description,
+ user_fn_output_type,
+ user_fn_output_description,
+):
+ """Makes the user function for the class."""
+ if (
+ user_fn_input_type is None
+ and user_fn_output_type is None
+ and user_fn_input_description is None
+ and user_fn_output_description is None
+ ):
+ return ""
+
+ md = """
+### User function
+
+The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
+
+- When used as an Input, the component only impacts the input signature of the user function.
+- When used as an output, the component only impacts the return signature of the user function.
+
+The code snippet below is accurate in cases where the component is used as both an input and an output.
+
+"""
+
+ md += (
+ f"- **As output:** Is passed, {format_description(user_fn_input_description)}\n"
+ if user_fn_input_description
+ else ""
+ )
+
+ md += (
+ f"- **As input:** Should return, {format_description(user_fn_output_description)}"
+ if user_fn_output_description
+ else ""
+ )
+
+ if user_fn_input_type is not None or user_fn_output_type is not None:
+ md += f"""
+
+ ```python
+ def predict(
+ value: {user_fn_input_type or "Unknown"}
+ ) -> {user_fn_output_type or "Unknown"}:
+ return value
+ ```
+ """
+ return md
+
+
+def render_class_events_markdown(events):
+ """Renders the events for a class."""
+ if len(events) == 0:
+ return ""
+
+ event_table = """
+### Events
+
+| name | description |
+|:-----|:------------|
+"""
+
+ for event_name, event in events.items():
+ event_table += f"| `{event_name}` | {event['description']} |\n"
+
+ return event_table
+
+
+def render_class_docs(exports, docs):
+ """Renders the class documentation for the package."""
+ docs_classes = ""
+ for class_name in exports:
+ user_fn_input_type = get_deep(
+ docs, [class_name, "members", "preprocess", "return", "type"]
+ )
+ user_fn_input_description = get_deep(
+ docs, [class_name, "members", "preprocess", "return", "description"]
+ )
+ user_fn_output_type = get_deep(
+ docs, [class_name, "members", "postprocess", "value", "type"]
+ )
+ user_fn_output_description = get_deep(
+ docs, [class_name, "members", "postprocess", "value", "description"]
+ )
+
+ linkify = get_deep(docs, ["__meta__", "additional_interfaces"], {}) or {}
+
+ docs_classes += f"""
+ gr.Markdown(\"\"\"
+## `{class_name}`
+
+### Initialization
+\"\"\", elem_classes=["md-custom"], header_links=True)
+
+ gr.ParamViewer(value=_docs["{class_name}"]["members"]["__init__"], linkify={list(linkify.keys())})
+
+{render_class_events(docs[class_name].get("events", None), class_name)}
+
+{make_user_fn(
+ class_name,
+ user_fn_input_type,
+ user_fn_input_description,
+ user_fn_output_type,
+ user_fn_output_description,
+)}
+"""
+ return docs_classes
+
+
+html = """
+
+
+
+name
+type
+default
+description
+
+
+
+value
+list[Parameter] | None
+None
+A list of dictionaries with keys "type", "description", and "default" for each parameter.
+
+
+"""
+
+
+def render_param_table(params):
+ """Renders the parameter table for the package."""
+ table = """
+
+
+name
+type
+default
+description
+
+
+"""
+
+ # for class_name in exports:
+ # docs_classes += f"""
+ # """
+ for param_name, param in params.items():
+ table += f"""
+
+{param_name}
+
+
+```python
+{param["type"]}
+```
+
+
+{param["default"]}
+{param['description']}
+
+"""
+ return table + "
"
+
+
+def render_class_docs_markdown(exports, docs):
+ """Renders the class documentation for the package."""
+ docs_classes = ""
+ for class_name in exports:
+ user_fn_input_type = get_deep(
+ docs, [class_name, "members", "preprocess", "return", "type"]
+ )
+ user_fn_input_description = get_deep(
+ docs, [class_name, "members", "preprocess", "return", "description"]
+ )
+ user_fn_output_type = get_deep(
+ docs, [class_name, "members", "postprocess", "value", "type"]
+ )
+ user_fn_output_description = get_deep(
+ docs, [class_name, "members", "postprocess", "value", "description"]
+ )
+ docs_classes += f"""
+## `{class_name}`
+
+### Initialization
+
+{render_param_table(docs[class_name]["members"]["__init__"])}
+
+{render_class_events_markdown(docs[class_name].get("events", None))}
+
+{make_user_fn_markdown(
+ user_fn_input_type,
+ user_fn_input_description,
+ user_fn_output_type,
+ user_fn_output_description,
+)}
+"""
+ return docs_classes
+
+
+def make_space(
+ docs: dict,
+ name: str,
+ description: str,
+ local_version: str | None,
+ demo: str,
+ space: str | None,
+ repo: str | None,
+ pypi_exists: bool,
+ suppress_demo_check: bool = False,
+):
+ filtered_keys = [key for key in docs if key != "__meta__"]
+
+ if not suppress_demo_check and (
+ demo.find("if __name__ == '__main__'") == -1
+ and demo.find('if __name__ == "__main__"') == -1
+ ):
+ raise ValueError(
+ """The demo must be launched using `if __name__ == '__main__'`, otherwise the docs page will not function correctly.
+
+To fix this error, launch the demo inside of an if statement like this:
+
+if __name__ == '__main__':
+ demo.launch()
+
+To ignore this error pass `--suppress-demo-check` to the docs command."""
+ )
+
+ source = """
+import gradio as gr
+from app import demo as app
+import os
+"""
+
+ docs_classes = render_class_docs(filtered_keys, docs)
+
+ source += f"""
+_docs = {docs}
+
+abs_path = os.path.join(os.path.dirname(__file__), "css.css")
+
+with gr.Blocks(
+ css=abs_path,
+ theme=gr.themes.Default(
+ font_mono=[
+ gr.themes.GoogleFont("Inconsolata"),
+ "monospace",
+ ],
+ ),
+) as demo:
+ gr.Markdown(
+\"\"\"
+# `{name}`
+
+
+{render_version_badge(pypi_exists, local_version, name)} {render_github_badge(repo)} {render_discuss_badge(space)}
+
+
+{description}
+\"\"\", elem_classes=["md-custom"], header_links=True)
+ app.render()
+ gr.Markdown(
+\"\"\"
+## Installation
+
+```bash
+pip install {name}
+```
+
+## Usage
+
+```python
+{demo}
+```
+\"\"\", elem_classes=["md-custom"], header_links=True)
+
+{docs_classes}
+
+{render_additional_interfaces(docs["__meta__"]["additional_interfaces"])}
+ demo.load(None, js=r\"\"\"{make_js(get_deep(docs, ["__meta__", "additional_interfaces"]),get_deep( docs, ["__meta__", "user_fn_refs"]))}
+\"\"\")
+
+demo.launch()
+"""
+
+ return source
+
+
+def make_markdown(
+ docs, name, description, local_version, demo, space, repo, pypi_exists
+):
+ filtered_keys = [key for key in docs if key != "__meta__"]
+
+ source = f"""
+# `{name}`
+{render_version_badge(pypi_exists, local_version, name)} {render_github_badge(repo)} {render_discuss_badge(space)}
+
+{description}
+
+## Installation
+
+```bash
+pip install {name}
+```
+
+## Usage
+
+```python
+{demo}
+```
+"""
+
+ docs_classes = render_class_docs_markdown(filtered_keys, docs)
+
+ source += docs_classes
+
+ source += render_additional_interfaces_markdown(
+ docs["__meta__"]["additional_interfaces"]
+ )
+
+ return source
diff --git a/gradio/cli/commands/components/app.py b/gradio/cli/commands/components/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..d42252a024afc6b4753623516ab95ab2d837e688
--- /dev/null
+++ b/gradio/cli/commands/components/app.py
@@ -0,0 +1,24 @@
+from typer import Typer
+
+from .build import _build
+from .create import _create
+from .dev import _dev
+from .docs import _docs
+from .install_component import _install
+from .publish import _publish
+from .show import _show
+
+app = Typer(help="Create and publish a new Gradio component")
+
+app.command("create", help="Create a new component.")(_create)
+app.command(
+ "build",
+ help="Build the component for distribution. Must be called from the component directory.",
+)(_build)
+app.command("dev", help="Launch the custom component demo in development mode.")(_dev)
+app.command("show", help="Show the list of available templates")(_show)
+app.command("install", help="Install the custom component in the current environment")(
+ _install
+)
+app.command("publish", help="Publish a component to PyPI and HuggingFace Hub")(_publish)
+app.command("docs", help="Generate documentation for a custom components")(_docs)
diff --git a/gradio/cli/commands/components/build.py b/gradio/cli/commands/components/build.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3e58f12b2bc38e82ea777383a4bbedce20188b2
--- /dev/null
+++ b/gradio/cli/commands/components/build.py
@@ -0,0 +1,138 @@
+import importlib
+import shutil
+import subprocess
+from pathlib import Path
+
+import semantic_version
+import typer
+from tomlkit import dump, parse
+from typing_extensions import Annotated
+
+import gradio
+from gradio.cli.commands.components._docs_utils import (
+ get_deep,
+)
+from gradio.cli.commands.components.docs import run_command
+from gradio.cli.commands.display import LivePanelDisplay
+
+gradio_template_path = Path(gradio.__file__).parent / "templates" / "frontend"
+gradio_node_path = Path(gradio.__file__).parent / "node" / "dev" / "files" / "index.js"
+
+
+def _build(
+ path: Annotated[
+ Path, typer.Argument(help="The directory of the custom component.")
+ ] = Path("."),
+ build_frontend: Annotated[
+ bool, typer.Option(help="Whether to build the frontend as well.")
+ ] = True,
+ bump_version: Annotated[
+ bool, typer.Option(help="Whether to bump the version number automatically.")
+ ] = False,
+ generate_docs: Annotated[
+ bool, typer.Option(help="Whether to generate the documentation as well.")
+ ] = True,
+):
+ name = Path(path).resolve()
+ if not (name / "pyproject.toml").exists():
+ raise ValueError(f"Cannot find pyproject.toml file in {name}")
+
+ with LivePanelDisplay() as live:
+ live.update(
+ f":package: Building package in [orange3]{str(name.name)}[/]", add_sleep=0.2
+ )
+ pyproject_toml = parse((path / "pyproject.toml").read_text())
+ package_name = get_deep(pyproject_toml, ["project", "name"])
+
+ if not isinstance(package_name, str):
+ raise ValueError(
+ "Your pyproject.toml file does not have a [project] name field!"
+ )
+ try:
+ importlib.import_module(package_name) # type: ignore
+ except ModuleNotFoundError as e:
+ raise ValueError(
+ f"Your custom component package ({package_name}) is not installed! "
+ "Please install it with the gradio cc install command before buillding it."
+ ) from e
+ if bump_version:
+ pyproject_toml = parse((path / "pyproject.toml").read_text())
+ version = semantic_version.Version(
+ pyproject_toml["project"]["version"] # type: ignore
+ ).next_patch()
+ live.update(
+ f":1234: Using version [bold][magenta]{version}[/][/]. "
+ "Set [bold][magenta]--no-bump-version[/][/] to use the version in pyproject.toml file."
+ )
+ pyproject_toml["project"]["version"] = str(version) # type: ignore
+ with open(path / "pyproject.toml", "w") as f:
+ dump(pyproject_toml, f)
+ else:
+ version = pyproject_toml["project"]["version"] # type: ignore
+ live.update(
+ f":1234: Package will use version [bold][magenta]{version}[/][/] defined in pyproject.toml file. "
+ "Set [bold][magenta]--bump-version[/][/] to automatically bump the version number."
+ )
+
+ if generate_docs:
+ _demo_dir = Path("demo").resolve()
+ _demo_name = "app.py"
+ _demo_path = _demo_dir / _demo_name
+ _readme_path = name / "README.md"
+
+ run_command(
+ live=live,
+ name=package_name,
+ suppress_demo_check=False,
+ pyproject_toml=pyproject_toml,
+ generate_space=True,
+ generate_readme=True,
+ type_mode="simple",
+ _demo_path=_demo_path,
+ _demo_dir=_demo_dir,
+ _readme_path=_readme_path,
+ space_url=None,
+ _component_dir=name,
+ simple=True,
+ )
+
+ if build_frontend:
+ live.update(":art: Building frontend")
+ component_directory = path.resolve()
+
+ node = shutil.which("node")
+ if not node:
+ raise ValueError(
+ "node must be installed in order to run build command."
+ )
+
+ node_cmds = [
+ node,
+ gradio_node_path,
+ "--component-directory",
+ component_directory,
+ "--root",
+ gradio_template_path,
+ "--mode",
+ "build",
+ ]
+ pipe = subprocess.run(node_cmds, capture_output=True, text=True)
+ if pipe.returncode != 0:
+ live.update(":red_square: Build failed!")
+ live.update(pipe.stderr)
+ live.update(pipe.stdout)
+ return
+ else:
+ live.update(":white_check_mark: Build succeeded!")
+
+ cmds = [shutil.which("python"), "-m", "build", str(name)]
+ live.update(f":construction_worker: Building... [grey37]({' '.join(cmds)})[/]")
+ pipe = subprocess.run(cmds, capture_output=True, text=True)
+ if pipe.returncode != 0:
+ live.update(":red_square: Build failed!")
+ live.update(pipe.stderr)
+ else:
+ live.update(":white_check_mark: Build succeeded!")
+ live.update(
+ f":ferris_wheel: Wheel located in [orange3]{str(name / 'dist')}[/]"
+ )
diff --git a/gradio/cli/commands/components/create.py b/gradio/cli/commands/components/create.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c8897ab4633a483e24184c06fcbce696cfa46af
--- /dev/null
+++ b/gradio/cli/commands/components/create.py
@@ -0,0 +1,160 @@
+import shutil
+from pathlib import Path
+from typing import Optional
+
+import typer
+from rich import print
+from rich.panel import Panel
+from rich.prompt import Confirm, Prompt
+from tomlkit import dump, parse
+from typing_extensions import Annotated
+
+from gradio.cli.commands.components.install_component import _get_npm, _install_command
+from gradio.cli.commands.display import LivePanelDisplay
+
+from . import _create_utils
+
+
+def _create(
+ name: Annotated[
+ str,
+ typer.Argument(
+ help="Name of the component. Preferably in camel case, i.e. MyTextBox."
+ ),
+ ],
+ directory: Annotated[
+ Optional[Path],
+ typer.Option(
+ help="Directory to create the component in. Default is None. If None, will be created in directory in the current directory."
+ ),
+ ] = None,
+ package_name: Annotated[
+ Optional[str],
+ typer.Option(help="Name of the package. Default is gradio_{name.lower()}"),
+ ] = None,
+ template: Annotated[
+ str,
+ typer.Option(
+ help="Component to use as a template. Should use exact name of python class."
+ ),
+ ] = "",
+ install: Annotated[
+ bool,
+ typer.Option(
+ help="Whether to install the component in your current environment as a development install. Recommended for development."
+ ),
+ ] = True,
+ npm_install: Annotated[
+ str,
+ typer.Option(help="NPM install command to use. Default is 'npm install'."),
+ ] = "npm install",
+ overwrite: Annotated[
+ bool,
+ typer.Option(help="Whether to overwrite the existing component if it exists."),
+ ] = False,
+ configure_metadata: Annotated[
+ bool,
+ typer.Option(
+ help="Whether to interactively configure project metadata based on user input"
+ ),
+ ] = True,
+):
+ if not directory:
+ directory = Path(name.lower())
+ if not package_name:
+ package_name = f"gradio_{name.lower()}"
+
+ if directory.exists() and not overwrite:
+ raise ValueError(
+ f"The directory {directory.resolve()} already exists. "
+ "Please set --overwrite flag or pass in the name "
+ "of a directory that does not already exist via the --directory option."
+ )
+ elif directory.exists() and overwrite:
+ _create_utils.delete_contents(directory)
+
+ directory.mkdir(exist_ok=overwrite)
+
+ if _create_utils._in_test_dir():
+ npm_install = f"{shutil.which('pnpm')} i --ignore-scripts"
+ else:
+ npm_install = _get_npm(npm_install)
+
+ with LivePanelDisplay() as live:
+ live.update(
+ f":building_construction: Creating component [orange3]{name}[/] in directory [orange3]{directory}[/]",
+ add_sleep=0.2,
+ )
+ if template:
+ live.update(f":fax: Starting from template [orange3]{template}[/]")
+ else:
+ live.update(":page_facing_up: Creating a new component from scratch.")
+
+ component = _create_utils._get_component_code(template)
+
+ _create_utils._create_backend(name, component, directory, package_name)
+ live.update(":snake: Created backend code", add_sleep=0.2)
+
+ _create_utils._create_frontend(
+ name.lower(), component, directory=directory, package_name=package_name
+ )
+ live.update(":art: Created frontend code", add_sleep=0.2)
+
+ if install:
+ _install_command(directory, live, npm_install)
+
+ live._panel.stop()
+
+ if configure_metadata:
+ print(
+ Panel(
+ "It is recommended to answer the following [bold][magenta]4 questions[/][/] to finish configuring your custom component's metadata."
+ "\nYou can also answer them later by editing the [bold][magenta]pyproject.toml[/][/] file in your component directory."
+ )
+ )
+
+ answer_qs = Confirm.ask("\nDo you want to answer them now?")
+
+ if answer_qs:
+ pyproject_toml = parse((directory / "pyproject.toml").read_text())
+ name = pyproject_toml["project"]["name"] # type: ignore
+
+ description = Prompt.ask(
+ "\n:pencil: Please enter a one sentence [bold][magenta]description[/][/] for your component"
+ )
+ if description:
+ pyproject_toml["project"]["description"] = description # type: ignore
+
+ license_ = Prompt.ask(
+ "\n:bookmark_tabs: Please enter a [bold][magenta]software license[/][/] for your component. Leave blank for 'MIT'"
+ )
+ license_ = license_ or "MIT"
+ print(f":bookmark_tabs: Using license [bold][magenta]{license_}[/][/]")
+ pyproject_toml["project"]["license"] = license_ # type: ignore
+
+ requires_python = Prompt.ask(
+ "\n:snake: Please enter the [bold][magenta]allowed python[/][/] versions for your component. Leave blank for '>=3.8'"
+ )
+ requires_python = requires_python or ">=3.8"
+ print(
+ f":snake: Using requires-python of [bold][magenta]{requires_python}[/][/]"
+ )
+ pyproject_toml["project"]["requires-python"] = ( # type: ignore
+ requires_python or ">=3.8"
+ )
+
+ keywords = []
+ print(
+ "\n:label: Please add some keywords to help others discover your component."
+ )
+ while True:
+ keyword = Prompt.ask(":label: Leave blank to stop adding keywords")
+ if keyword:
+ keywords.append(keyword)
+ else:
+ break
+ current_keywords = pyproject_toml["project"].get("keywords", []) # type: ignore
+ pyproject_toml["project"]["keywords"] = current_keywords + keywords # type: ignore
+ with open(directory / "pyproject.toml", "w") as f:
+ dump(pyproject_toml, f)
+ print("\nComponent creation [bold][magenta]complete[/][/]!")
diff --git a/gradio/cli/commands/components/dev.py b/gradio/cli/commands/components/dev.py
new file mode 100644
index 0000000000000000000000000000000000000000..eacc43478da8678aacb1a05126167261ac57d527
--- /dev/null
+++ b/gradio/cli/commands/components/dev.py
@@ -0,0 +1,85 @@
+import shutil
+import subprocess
+from pathlib import Path
+
+import typer
+from rich import print
+from typing_extensions import Annotated
+
+import gradio
+
+gradio_template_path = Path(gradio.__file__).parent / "templates" / "frontend"
+gradio_node_path = Path(gradio.__file__).parent / "node" / "dev" / "files" / "index.js"
+
+
+def _dev(
+ app: Annotated[
+ Path,
+ typer.Argument(
+ help="The path to the app. By default, looks for demo/app.py in the current directory."
+ ),
+ ] = Path("demo") / "app.py",
+ component_directory: Annotated[
+ Path,
+ typer.Option(
+ help="The directory with the custom component source code. By default, uses the current directory."
+ ),
+ ] = Path("."),
+ host: Annotated[
+ str,
+ typer.Option(
+ help="The host to run the front end server on. Defaults to localhost.",
+ ),
+ ] = "localhost",
+):
+ component_directory = component_directory.resolve()
+
+ print(f":recycle: [green]Launching[/] {app} in reload mode\n")
+
+ node = shutil.which("node")
+ if not node:
+ raise ValueError("node must be installed in order to run dev mode.")
+
+ proc = subprocess.Popen(
+ [
+ node,
+ gradio_node_path,
+ "--component-directory",
+ component_directory,
+ "--root",
+ gradio_template_path,
+ "--app",
+ str(app),
+ "--mode",
+ "dev",
+ "--host",
+ host,
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ while True:
+ proc.poll()
+ text = proc.stdout.readline() # type: ignore
+ err = None
+ if proc.stderr:
+ err = proc.stderr.readline()
+
+ text = (
+ text.decode("utf-8")
+ .replace("Changes detected in:", "[orange3]Changed detected in:[/]")
+ .replace("Watching:", "[orange3]Watching:[/]")
+ .replace("Running on local URL", "[orange3]Backend Server[/]")
+ )
+
+ if "[orange3]Watching:[/]" in text:
+ text += f"'{str(component_directory / 'frontend').strip()}',"
+ if "To create a public link" in text:
+ continue
+ print(text)
+ if err:
+ print(err.decode("utf-8"))
+
+ if proc.returncode is not None:
+ print("Backend server failed to launch. Exiting.")
+ return
diff --git a/gradio/cli/commands/components/docs.py b/gradio/cli/commands/components/docs.py
new file mode 100644
index 0000000000000000000000000000000000000000..afe5a72a04e66073f3399a1b42dce0ae66525999
--- /dev/null
+++ b/gradio/cli/commands/components/docs.py
@@ -0,0 +1,189 @@
+from __future__ import annotations
+
+import importlib
+from pathlib import Path
+from typing import Any, Optional
+
+import requests
+import tomlkit as toml
+from typer import Argument, Option
+from typing_extensions import Annotated
+
+from gradio.cli.commands.display import LivePanelDisplay
+
+from ._docs_assets import css
+from ._docs_utils import extract_docstrings, get_deep, make_markdown, make_space
+
+
+def _docs(
+ path: Annotated[
+ Path, Argument(help="The directory of the custom component.")
+ ] = Path("."),
+ demo_dir: Annotated[
+ Optional[Path], Option(help="Path to the demo directory.")
+ ] = None,
+ demo_name: Annotated[Optional[str], Option(help="Name of the demo file.")] = None,
+ readme_path: Annotated[
+ Optional[Path], Option(help="Path to the README.md file.")
+ ] = None,
+ space_url: Annotated[
+ Optional[str], Option(help="URL of the Space to use for the demo.")
+ ] = None,
+ generate_space: Annotated[
+ bool,
+ Option(
+ help="Create a documentation space for the custom compone.", is_flag=True
+ ),
+ ] = True,
+ generate_readme: Annotated[
+ bool,
+ Option(help="Create a README.md file for the custom component.", is_flag=True),
+ ] = True,
+ suppress_demo_check: Annotated[
+ bool,
+ Option(
+ help="Suppress demo warnings and errors.",
+ is_flag=True,
+ ),
+ ] = False,
+):
+ """Runs the documentation generator."""
+
+ _component_dir = Path(path).resolve()
+ _demo_dir = Path(demo_dir).resolve() if demo_dir else Path("demo").resolve()
+ _demo_name = demo_name if demo_name else "app.py"
+ _demo_path = _demo_dir / _demo_name
+ _readme_path = (
+ Path(readme_path).resolve() if readme_path else _component_dir / "README.md"
+ )
+
+ if not generate_space and not generate_readme:
+ raise ValueError("Must generate at least one of space or readme")
+
+ with LivePanelDisplay() as live:
+ live.update(
+ f":page_facing_up: Generating documentation for [orange3]{str(_component_dir.name)}[/]",
+ add_sleep=0.2,
+ )
+ live.update(
+ f":eyes: Reading project metadata from [orange3]{_component_dir}/pyproject.toml[/]\n"
+ )
+
+ if not (_component_dir / "pyproject.toml").exists():
+ raise ValueError(
+ f"Cannot find pyproject.toml file in [orange3]{_component_dir}[/]"
+ )
+
+ with open(_component_dir / "pyproject.toml") as f:
+ data = toml.loads(f.read())
+
+ name = get_deep(data, ["project", "name"])
+
+ if not isinstance(name, str):
+ raise ValueError("Name not found in pyproject.toml")
+
+ run_command(
+ live=live,
+ name=name,
+ suppress_demo_check=suppress_demo_check,
+ pyproject_toml=data,
+ generate_space=generate_space,
+ generate_readme=generate_readme,
+ type_mode="simple",
+ _demo_path=_demo_path,
+ _demo_dir=_demo_dir,
+ _readme_path=_readme_path,
+ space_url=space_url,
+ _component_dir=_component_dir,
+ )
+
+
+def run_command(
+ live: LivePanelDisplay,
+ name: str,
+ pyproject_toml: dict[str, Any],
+ suppress_demo_check: bool,
+ generate_space: bool,
+ generate_readme: bool,
+ type_mode: str,
+ _demo_path: Path,
+ _demo_dir: Path,
+ _readme_path: Path,
+ space_url: str | None,
+ _component_dir: Path,
+ simple: bool = False,
+):
+ with open(_demo_path) as f:
+ demo = f.read()
+
+ pypi_exists = requests.get(f"https://pypi.org/pypi/{name}/json").status_code
+
+ pypi_exists = pypi_exists == 200 or False
+
+ local_version = get_deep(pyproject_toml, ["project", "version"])
+ description = str(get_deep(pyproject_toml, ["project", "description"]) or "")
+ repo = get_deep(pyproject_toml, ["project", "urls", "repository"])
+ space = (
+ space_url
+ if space_url
+ else get_deep(pyproject_toml, ["project", "urls", "space"])
+ )
+
+ if not local_version and not pypi_exists:
+ raise ValueError(
+ f"Cannot find version in pyproject.toml or on PyPI for [orange3]{name}[/].\nIf you have just published to PyPI, please wait a few minutes and try again."
+ )
+ module = importlib.import_module(name)
+ (docs, type_mode) = extract_docstrings(module)
+
+ if generate_space:
+ if not simple:
+ live.update(":computer: [blue]Generating space.[/]")
+
+ source = make_space(
+ docs=docs,
+ name=name,
+ description=description,
+ local_version=local_version
+ if local_version is None
+ else str(local_version),
+ demo=demo,
+ space=space if space is None else str(space),
+ repo=repo if repo is None else str(repo),
+ pypi_exists=pypi_exists,
+ suppress_demo_check=suppress_demo_check,
+ )
+
+ with open(_demo_dir / "space.py", "w") as f:
+ f.write(source)
+ if not simple:
+ live.update(
+ f":white_check_mark: Space created in [orange3]{_demo_dir}/space.py[/]\n"
+ )
+ with open(_demo_dir / "css.css", "w") as f:
+ f.write(css)
+
+ if generate_readme:
+ if not simple:
+ live.update(":pencil: [blue]Generating README.[/]")
+ readme = make_markdown(
+ docs, name, description, local_version, demo, space, repo, pypi_exists
+ )
+
+ with open(_readme_path, "w") as f:
+ f.write(readme)
+ if not simple:
+ live.update(
+ f":white_check_mark: README generated in [orange3]{_readme_path}[/]"
+ )
+ if simple:
+ short_readme_path = Path(_readme_path).relative_to(_component_dir)
+ short_demo_path = Path(_demo_dir / "space.py").relative_to(_component_dir)
+ live.update(
+ f":white_check_mark: Documention generated in [orange3]{short_demo_path}[/] and [orange3]{short_readme_path}[/]. Pass --no-generate-docs to disable auto documentation."
+ )
+
+ if type_mode == "simple":
+ live.update(
+ "\n:orange_circle: [red]The docs were generated in simple mode. Updating python to a version greater than 3.9 will result in richer documentation.[/]"
+ )
diff --git a/gradio/cli/commands/components/files/gitignore b/gradio/cli/commands/components/files/gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..60188eefb61faf29c12a14228941da079044292f
--- /dev/null
+++ b/gradio/cli/commands/components/files/gitignore
@@ -0,0 +1,9 @@
+.eggs/
+dist/
+*.pyc
+__pycache__/
+*.py[cod]
+*$py.class
+__tmp/*
+*.pyi
+node_modules
\ No newline at end of file
diff --git a/gradio/cli/commands/components/files/pyproject_.toml b/gradio/cli/commands/components/files/pyproject_.toml
new file mode 100644
index 0000000000000000000000000000000000000000..e71fae672f0c271c70284684080221de14a2b33c
--- /dev/null
+++ b/gradio/cli/commands/components/files/pyproject_.toml
@@ -0,0 +1,45 @@
+[build-system]
+requires = [
+ "hatchling",
+ "hatch-requirements-txt",
+ "hatch-fancy-pypi-readme>=22.5.0",
+]
+build-backend = "hatchling.build"
+
+[project]
+name = "<>"
+version = "0.0.1"
+description = "Python library for easily interacting with trained machine learning models"
+readme = "README.md"
+license = "Apache-2.0"
+requires-python = ">=3.8"
+authors = [{ name = "YOUR NAME", email = "YOUREMAIL@domain.com" }]
+keywords = [
+ "gradio-custom-component",
+ "<>"
+]
+# Add dependencies here
+dependencies = ["gradio>=4.0,<5.0"]
+classifiers = [
+ 'Development Status :: 3 - Alpha',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Topic :: Scientific/Engineering',
+ 'Topic :: Scientific/Engineering :: Artificial Intelligence',
+ 'Topic :: Scientific/Engineering :: Visualization',
+]
+
+[project.optional-dependencies]
+dev = ["build", "twine"]
+
+[tool.hatch.build]
+artifacts = ["/backend/<>/templates", "*.pyi"]
+
+[tool.hatch.build.targets.wheel]
+packages = ["/backend/<>"]
diff --git a/gradio/cli/commands/components/install_component.py b/gradio/cli/commands/components/install_component.py
new file mode 100644
index 0000000000000000000000000000000000000000..f10636d31de7bc6f6b9befa1affabf9bd957a479
--- /dev/null
+++ b/gradio/cli/commands/components/install_component.py
@@ -0,0 +1,63 @@
+import shutil
+import subprocess
+from pathlib import Path
+
+from rich.markup import escape
+from typer import Argument, Option
+from typing_extensions import Annotated
+
+from gradio.cli.commands.display import LivePanelDisplay
+from gradio.utils import set_directory
+
+
+def _get_npm(npm_install: str):
+ npm_install = npm_install.strip()
+ if npm_install == "npm install":
+ npm = shutil.which("npm")
+ if not npm:
+ raise ValueError(
+ "By default, the install command uses npm to install "
+ "the frontend dependencies. Please install npm or pass your own install command "
+ "via the --npm-install option."
+ )
+ npm_install = f"{npm} install"
+ return npm_install
+
+
+def _install_command(directory: Path, live: LivePanelDisplay, npm_install: str):
+ cmds = [shutil.which("pip"), "install", "-e", f"{str(directory)}[dev]"]
+ live.update(
+ f":construction_worker: Installing python... [grey37]({escape(' '.join(cmds))})[/]"
+ )
+ pipe = subprocess.run(cmds, capture_output=True, text=True)
+
+ if pipe.returncode != 0:
+ live.update(":red_square: Python installation [bold][red]failed[/][/]")
+ live.update(pipe.stderr)
+ else:
+ live.update(":white_check_mark: Python install succeeded!")
+
+ live.update(
+ f":construction_worker: Installing javascript... [grey37]({npm_install})[/]"
+ )
+ with set_directory(directory / "frontend"):
+ pipe = subprocess.run(npm_install.split(), capture_output=True, text=True)
+ if pipe.returncode != 0:
+ live.update(":red_square: NPM install [bold][red]failed[/][/]")
+ live.update(pipe.stdout)
+ live.update(pipe.stderr)
+ else:
+ live.update(":white_check_mark: NPM install succeeded!")
+
+
+def _install(
+ directory: Annotated[
+ Path, Argument(help="The directory containing the custom components.")
+ ] = Path("."),
+ npm_install: Annotated[
+ str, Option(help="NPM install command to use. Default is 'npm install'.")
+ ] = "npm install",
+):
+ npm_install = _get_npm(npm_install)
+ with LivePanelDisplay() as live:
+ _install_command(directory, live, npm_install)
diff --git a/gradio/cli/commands/components/publish.py b/gradio/cli/commands/components/publish.py
new file mode 100644
index 0000000000000000000000000000000000000000..c38ec6da9f86bcd9cc109ee4f3ba4911ad0e8b82
--- /dev/null
+++ b/gradio/cli/commands/components/publish.py
@@ -0,0 +1,350 @@
+import random
+import re
+import shutil
+import tempfile
+from pathlib import Path
+from typing import List, Optional
+
+import httpx
+import semantic_version
+from huggingface_hub import HfApi
+from rich import print
+from rich.console import Console
+from rich.panel import Panel
+from rich.prompt import Confirm, Prompt
+from tomlkit import parse
+from typer import Argument, Option
+from typing_extensions import Annotated
+
+colors = ["red", "yellow", "green", "blue", "indigo", "purple", "pink", "gray"]
+
+PYPI_REGISTER_URL = "https://pypi.org/account/register/"
+
+README_CONTENTS = """
+---
+tags: [gradio-custom-component{template}]
+title: {package_name} V{version}
+colorFrom: {color_from}
+colorTo: {color_to}
+sdk: docker
+pinned: false
+license: apache-2.0
+---
+"""
+
+
+def make_dockerfile(demo):
+ return f"""
+FROM python:3.9
+
+WORKDIR /code
+
+COPY --link --chown=1000 . .
+
+RUN mkdir -p /tmp/cache/
+RUN chmod a+rwx -R /tmp/cache/
+ENV TRANSFORMERS_CACHE=/tmp/cache/
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+ENV PYTHONUNBUFFERED=1 \
+ GRADIO_ALLOW_FLAGGING=never \
+ GRADIO_NUM_PORTS=1 \
+ GRADIO_SERVER_NAME=0.0.0.0 \
+ GRADIO_SERVER_PORT=7860 \
+ SYSTEM=spaces
+
+CMD ["python", "{demo}"]
+"""
+
+
+def _ignore(s, names):
+ ignored = []
+ for n in names:
+ if "__pycache__" in n or n.startswith("dist") or n.startswith("node_modules"):
+ ignored.append(n)
+ return ignored
+
+
+def _get_version_from_file(dist_file: Path) -> Optional[str]:
+ match = re.search(r"-(\d+\.\d+\.\d+[a-zA-Z]*\d*)-", dist_file.name)
+ if match:
+ return match.group(1)
+
+
+def _get_max_version(distribution_files: List[Path]) -> Optional[str]:
+ versions = []
+ for p in distribution_files:
+ version = _get_version_from_file(p)
+ # If anything goes wrong, just return None so we upload all files
+ # better safe than sorry
+ if version:
+ try:
+ versions.append(semantic_version.Version(version))
+ except ValueError:
+ return None
+ return str(max(versions)) if versions else None
+
+
+def _publish(
+ dist_dir: Annotated[
+ Path,
+ Argument(help=f"Path to the wheel directory. Default is {Path('.') / 'dist'}"),
+ ] = Path(".") / "dist",
+ bump_version: Annotated[
+ bool, Option(help="Whether to bump the version number.")
+ ] = True,
+ upload_pypi: Annotated[bool, Option(help="Whether to upload to PyPI.")] = True,
+ pypi_username: Annotated[str, Option(help="The username for PyPI.")] = "",
+ pypi_password: Annotated[str, Option(help="The password for PyPI.")] = "",
+ upload_demo: Annotated[
+ bool, Option(help="Whether to upload demo to HuggingFace.")
+ ] = True,
+ demo_dir: Annotated[
+ Optional[Path], Option(help="Path to the demo directory.")
+ ] = None,
+ source_dir: Annotated[
+ Optional[Path],
+ Option(help="Path to the source directory of the custom component."),
+ ] = None,
+ hf_token: Annotated[
+ Optional[str],
+ Option(
+ help="HuggingFace token for uploading demo. Can be omitted if already logged in via huggingface cli."
+ ),
+ ] = None,
+ prefer_local: Annotated[
+ bool,
+ Option(
+ help="Install the package from the local wheel in the demo space, even if it exists on PyPi."
+ ),
+ ] = False,
+ upload_source: Annotated[
+ bool,
+ Option(
+ help="Whether to upload the source code of the custom component, to share with the community."
+ ),
+ ] = True,
+):
+ console = Console()
+ dist_dir = dist_dir.resolve()
+ name = None
+ description = None
+ if not dist_dir.exists():
+ raise ValueError(
+ f"{dist_dir} does not exist. Run `gradio cc build` to create a wheel and source distribution."
+ )
+ if not dist_dir.is_dir():
+ raise ValueError(f"{dist_dir} is not a directory")
+ distribution_files = [
+ p.resolve() for p in Path(dist_dir).glob("*") if p.suffix in {".whl", ".gz"}
+ ]
+ wheel_file = max(
+ (p for p in distribution_files if p.suffix == ".whl"),
+ key=lambda s: semantic_version.Version(str(s).split("-")[1]),
+ )
+ if not wheel_file:
+ raise ValueError(
+ "A wheel file was not found in the distribution directory. "
+ "Run `gradio cc build` to create a wheel file."
+ )
+ config_file = None
+ if upload_pypi and (not pypi_username or not pypi_password):
+ panel = Panel(
+ "It is recommended to upload your component to pypi so that [bold][magenta]anyone[/][/] "
+ "can install it with [bold][magenta]pip install[/][/].\n\n"
+ f"A PyPi account is needed. If you do not have an account, register account here: [blue]{PYPI_REGISTER_URL}[/]",
+ )
+ print(panel)
+ upload_pypi = Confirm.ask(":snake: Upload to pypi?")
+ if upload_pypi and (Path.home() / ".pypirc").exists():
+ print(":closed_lock_with_key: Found .pypirc file in home directory.")
+ config_file = str(Path.home() / ".pypirc")
+ elif upload_pypi:
+ print(
+ ":light_bulb: If you have Two Factor Authentication enabled, the username is __token__ and your password is your API key."
+ )
+ pypi_username = Prompt.ask(":laptop_computer: Enter your pypi username")
+ pypi_password = Prompt.ask(
+ ":closed_lock_with_key: Enter your pypi password", password=True
+ )
+ if upload_pypi:
+ try:
+ from twine.commands.upload import upload as twine_upload # type: ignore
+ from twine.settings import Settings # type: ignore
+ except (ImportError, ModuleNotFoundError) as e:
+ raise ValueError(
+ "The twine library must be installed to publish to pypi."
+ "Install it with pip, pip install twine."
+ ) from e
+ if pypi_username and pypi_password:
+ twine_settings = Settings(username=pypi_username, password=pypi_password)
+ elif config_file:
+ twine_settings = Settings(config_file=config_file)
+ else:
+ raise ValueError(
+ "No pypi username or password provided and no ~/.pypirc file found."
+ )
+ try:
+ # do our best to only upload the latest versions
+ max_version = _get_max_version(distribution_files)
+ twine_files = [
+ str(p)
+ for p in distribution_files
+ if (not max_version or max_version in p.name)
+ ]
+ print(f"Uploading files: {','.join(twine_files)}")
+ twine_upload(twine_settings, twine_files)
+ except Exception:
+ console.print_exception()
+ if upload_demo and not demo_dir:
+ panel = Panel(
+ "It is recommended you upload a demo of your component to [blue]https://huggingface.co/spaces[/] "
+ "so that anyone can try it from their browser."
+ )
+ print(panel)
+ upload_demo = Confirm.ask(":hugging_face: Upload demo?")
+ if upload_demo:
+ panel = Panel(
+ "Please provide the path to the [magenta]demo directory[/] for your custom component.\n\n"
+ "This directory should contain [magenta]all the files[/] it needs to run successfully.\n\n"
+ "Please make sure the gradio app is in an [magenta]app.py[/] file.\n\n"
+ "If you need additional python requirements, add a [magenta]requirements.txt[/] file to this directory."
+ )
+ print(panel)
+ demo_dir_ = Prompt.ask(
+ f":roller_coaster: Please enter the path to the demo directory. Leave blank to use: {(Path('.') / 'demo')}"
+ )
+ demo_dir_ = demo_dir_ or str(Path(".") / "demo")
+ demo_dir = Path(demo_dir_).resolve()
+
+ if upload_source and not source_dir:
+ panel = Panel(
+ "It is recommended that you share your [magenta]source code[/] so that others can learn from and improve your component."
+ )
+ print(panel)
+ upload_source = Confirm.ask(":books: Would you like to share your source code?")
+ if upload_source:
+ source_dir_ = Prompt.ask(
+ ":page_with_curl: Enter the path to the source code [magenta]directory[/]. Leave blank to use current directory"
+ )
+ source_dir_ = source_dir_ or str(Path("."))
+ source_dir = Path(source_dir_).resolve()
+ if upload_demo:
+ pyproject_toml_path = (
+ (source_dir / "pyproject.toml")
+ if source_dir
+ else Path(".") / "pyproject.toml"
+ )
+
+ try:
+ pyproject_toml = parse(pyproject_toml_path.read_text())
+ package_name = pyproject_toml["project"]["name"] # type: ignore
+ except Exception:
+ (package_name, version) = wheel_file.name.split("-")[:2]
+
+ try:
+ latest_release = httpx.get(
+ f"https://pypi.org/pypi/{package_name}/json"
+ ).json()["info"]["version"]
+ except Exception:
+ latest_release = None
+
+ assert demo_dir
+ demo_path = resolve_demo(demo_dir)
+
+ if prefer_local or not latest_release:
+ additional_reqs = [wheel_file.name]
+ else:
+ additional_reqs = [f"{package_name}=={latest_release}"]
+ if (demo_dir / "requirements.txt").exists():
+ reqs = (demo_dir / "requirements.txt").read_text().splitlines()
+ reqs += additional_reqs
+ else:
+ reqs = additional_reqs
+
+ color_from, color_to = random.choice(colors), random.choice(colors)
+ package_name, version = wheel_file.name.split("-")[:2]
+ with tempfile.TemporaryDirectory() as tempdir:
+ shutil.copytree(
+ str(demo_dir),
+ str(tempdir),
+ dirs_exist_ok=True,
+ )
+ if source_dir:
+ shutil.copytree(
+ str(source_dir),
+ str(Path(tempdir) / "src"),
+ dirs_exist_ok=True,
+ ignore=_ignore,
+ )
+ reqs_txt = Path(tempdir) / "requirements.txt"
+ reqs_txt.write_text("\n".join(reqs))
+ readme = Path(tempdir) / "README.md"
+ template = ""
+ if upload_source and source_dir:
+ pyproject_toml = parse((source_dir / "pyproject.toml").read_text())
+ keywords = pyproject_toml["project"].get("keywords", []) # type: ignore
+ keywords = [
+ k
+ for k in keywords
+ if k not in {"gradio-custom-component", "gradio custom component"}
+ ]
+ if keywords:
+ template = "," + ",".join(keywords)
+ name = pyproject_toml["project"]["name"] # type: ignore
+ description = pyproject_toml["project"]["description"] # type: ignore
+
+ readme_text = README_CONTENTS.format(
+ package_name=package_name,
+ version=version,
+ color_from=color_from,
+ color_to=color_to,
+ template=template,
+ )
+
+ if name and description:
+ readme_text += f"\n\n# Name: {name}"
+ readme_text += f"\n\nDescription: {description}"
+ readme_text += f"\n\nInstall with: pip install {package_name}"
+
+ readme.write_text(readme_text)
+ dockerfile = Path(tempdir) / "Dockerfile"
+ dockerfile.write_text(make_dockerfile(demo_path.name))
+
+ api = HfApi()
+ new_space = api.create_repo(
+ repo_id=f"{package_name}",
+ repo_type="space",
+ exist_ok=True,
+ private=False,
+ space_sdk="docker",
+ token=hf_token,
+ )
+ api.upload_folder(
+ repo_id=new_space.repo_id,
+ folder_path=tempdir,
+ token=hf_token,
+ repo_type="space",
+ )
+ api.upload_file(
+ repo_id=new_space.repo_id,
+ path_or_fileobj=str(wheel_file),
+ path_in_repo=wheel_file.name,
+ token=hf_token,
+ repo_type="space",
+ )
+ print("\n")
+ print(f"Demo uploaded to {new_space} !")
+
+
+def resolve_demo(demo_dir: Path) -> Path:
+ _demo_dir = demo_dir.resolve()
+ if (_demo_dir / "space.py").exists():
+ return _demo_dir / "space.py"
+ elif (_demo_dir / "app.py").exists():
+ return _demo_dir / "app.py"
+ else:
+ raise FileNotFoundError(
+ f'Could not find "space.py" or "app.py" in "{demo_dir}".'
+ )
diff --git a/gradio/cli/commands/components/show.py b/gradio/cli/commands/components/show.py
new file mode 100644
index 0000000000000000000000000000000000000000..afd63fb9a319642137b1f0a2a3b7834f79f8d296
--- /dev/null
+++ b/gradio/cli/commands/components/show.py
@@ -0,0 +1,70 @@
+import inspect
+
+from rich.console import Console
+from rich.table import Table
+
+import gradio._simple_templates
+import gradio.components
+import gradio.layouts
+from gradio.blocks import BlockContext
+from gradio.components import Component, FormComponent
+
+_IGNORE = {
+ "Text",
+ "Dataframe",
+ "Highlightedtext",
+ "Annotatedimage",
+ "Checkboxgroup",
+ "Json",
+ "Highlight",
+ "Component",
+ "Form",
+ "Dataset",
+ "FormComponent",
+ "Fallback",
+ "State",
+}
+
+_BEGINNER_FRIENDLY = {"Slider", "Radio", "Checkbox", "Number", "CheckboxGroup", "File"}
+
+
+def _get_table_items(module):
+ items = []
+ for name in module.__all__:
+ gr_cls = getattr(module, name)
+ if not (
+ inspect.isclass(gr_cls) and issubclass(gr_cls, (Component, BlockContext))
+ ) or (name in _IGNORE):
+ continue
+ tags = []
+ if "Simple" in name or name in _BEGINNER_FRIENDLY:
+ tags.append(":seedling::handshake:Beginner Friendly:seedling::handshake:")
+ if issubclass(gr_cls, FormComponent):
+ tags.append(":pencil::jigsaw:Form Component:pencil::jigsaw:")
+ if name in gradio.layouts.__all__:
+ tags.append(":triangular_ruler:Layout:triangular_ruler:")
+ doc = inspect.getdoc(gr_cls) or "No description available."
+ doc = doc.split(".")[0]
+ if tags:
+ doc = f"[{', '.join(tags)}]" + " " + doc
+ items.append((name, doc))
+
+ return items
+
+
+def _show():
+ items = (
+ _get_table_items(gradio._simple_templates)
+ + _get_table_items(gradio.components)
+ + _get_table_items(gradio.layouts)
+ )
+ table = Table(show_header=True, header_style="orange1", show_lines=True)
+ table.add_column("Name", justify="center")
+ table.add_column("Description", justify="center")
+
+ for item in items:
+ table.add_row(*item)
+
+ console = Console()
+ with console.pager():
+ console.print(table)
diff --git a/gradio/cli/commands/deploy_space.py b/gradio/cli/commands/deploy_space.py
new file mode 100644
index 0000000000000000000000000000000000000000..c82564456335b1036d0a996d96ade8d4222add2b
--- /dev/null
+++ b/gradio/cli/commands/deploy_space.py
@@ -0,0 +1,177 @@
+from __future__ import annotations
+
+import os
+import re
+from typing import Optional
+
+import huggingface_hub
+from rich import print
+from typer import Option
+from typing_extensions import Annotated
+
+import gradio as gr
+
+repo_directory = os.getcwd()
+readme_file = os.path.join(repo_directory, "README.md")
+github_action_template = os.path.join(
+ os.path.dirname(__file__), "deploy_space_action.yaml"
+)
+
+
+def add_configuration_to_readme(
+ title: str | None,
+ app_file: str | None,
+) -> dict:
+ configuration = {}
+
+ dir_name = os.path.basename(repo_directory)
+ if title is None:
+ title = input(f"Enter Spaces app title [{dir_name}]: ") or dir_name
+ formatted_title = format_title(title)
+ if formatted_title != title:
+ print(f"Formatted to {formatted_title}. ")
+ configuration["title"] = formatted_title
+
+ if app_file is None:
+ for file in os.listdir(repo_directory):
+ file_path = os.path.join(repo_directory, file)
+ if not os.path.isfile(file_path) or not file.endswith(".py"):
+ continue
+
+ with open(file_path, encoding="utf-8", errors="ignore") as f:
+ content = f.read()
+ if "import gradio" in content:
+ app_file = file
+ break
+
+ app_file = (
+ input(f"Enter Gradio app file {f'[{app_file}]' if app_file else ''}: ")
+ or app_file
+ )
+ if not app_file or not os.path.exists(app_file):
+ raise FileNotFoundError("Failed to find Gradio app file.")
+ configuration["app_file"] = app_file
+
+ configuration["sdk"] = "gradio"
+ configuration["sdk_version"] = gr.__version__
+ huggingface_hub.metadata_save(readme_file, configuration)
+
+ configuration["hardware"] = (
+ input(
+ f"Enter Spaces hardware ({', '.join(hardware.value for hardware in huggingface_hub.SpaceHardware)}) [cpu-basic]: "
+ )
+ or "cpu-basic"
+ )
+
+ secrets = {}
+ if input("Any Spaces secrets (y/n) [n]: ") == "y":
+ while True:
+ secret_name = input("Enter secret name (leave blank to end): ")
+ if not secret_name:
+ break
+ secret_value = input(f"Enter secret value for {secret_name}: ")
+ secrets[secret_name] = secret_value
+ configuration["secrets"] = secrets
+
+ requirements_file = os.path.join(repo_directory, "requirements.txt")
+ if (
+ not os.path.exists(requirements_file)
+ and input("Create requirements.txt file? (y/n) [n]: ").lower() == "y"
+ ):
+ while True:
+ requirement = input("Enter a dependency (leave blank to end): ")
+ if not requirement:
+ break
+ with open(requirements_file, "a") as f:
+ f.write(requirement + "\n")
+
+ if (
+ input(
+ "Create Github Action to automatically update Space on 'git push'? [n]: "
+ ).lower()
+ == "y"
+ ):
+ track_branch = input("Enter branch to track [main]: ") or "main"
+ github_action_file = os.path.join(
+ repo_directory, ".github/workflows/update_space.yml"
+ )
+ os.makedirs(os.path.dirname(github_action_file), exist_ok=True)
+ with open(github_action_template) as f:
+ github_action_content = f.read()
+ github_action_content = github_action_content.replace("$branch", track_branch)
+ with open(github_action_file, "w") as f:
+ f.write(github_action_content)
+
+ print(
+ "Github Action created. Add your Hugging Face write token (from https://huggingface.co/settings/tokens) as an Actions Secret named 'hf_token' to your GitHub repository. This can be set in your repository's settings page."
+ )
+
+ return configuration
+
+
+def format_title(title: str):
+ title = title.replace(" ", "_")
+ title = re.sub(r"[^a-zA-Z0-9\-._]", "", title)
+ title = re.sub("-+", "-", title)
+ while title.startswith("."):
+ title = title[1:]
+ return title
+
+
+def deploy(
+ title: Annotated[Optional[str], Option(help="Spaces app title")] = None,
+ app_file: Annotated[
+ Optional[str], Option(help="File containing the Gradio app")
+ ] = None,
+):
+ if (
+ os.getenv("SYSTEM") == "spaces"
+ ): # in case a repo with this function is uploaded to spaces
+ return
+
+ hf_api = huggingface_hub.HfApi()
+ whoami = None
+ login = False
+ try:
+ whoami = hf_api.whoami()
+ if whoami["auth"]["accessToken"]["role"] != "write":
+ login = True
+ except OSError:
+ login = True
+ if login:
+ print("Need 'write' access token to create a Spaces repo.")
+ huggingface_hub.login(add_to_git_credential=False)
+ whoami = hf_api.whoami()
+
+ configuration: None | dict = None
+ if os.path.exists(readme_file):
+ try:
+ configuration = huggingface_hub.metadata_load(readme_file)
+ except ValueError:
+ pass
+
+ if configuration is None:
+ print(
+ f"Creating new Spaces Repo in '{repo_directory}'. Collecting metadata, press Enter to accept default value."
+ )
+ configuration = add_configuration_to_readme(
+ title,
+ app_file,
+ )
+
+ space_id = huggingface_hub.create_repo(
+ configuration["title"],
+ space_sdk="gradio",
+ repo_type="space",
+ exist_ok=True,
+ space_hardware=configuration.get("hardware"),
+ ).repo_id
+ hf_api.upload_folder(
+ repo_id=space_id,
+ repo_type="space",
+ folder_path=repo_directory,
+ )
+ if configuration.get("secrets"):
+ for secret_name, secret_value in configuration["secrets"].items():
+ huggingface_hub.add_space_secret(space_id, secret_name, secret_value)
+ print(f"Space available at https://huggingface.co/spaces/{space_id}")
diff --git a/gradio/cli/commands/display.py b/gradio/cli/commands/display.py
new file mode 100644
index 0000000000000000000000000000000000000000..c3e5c87c48f930388b21fdc206d5ec4361836302
--- /dev/null
+++ b/gradio/cli/commands/display.py
@@ -0,0 +1,32 @@
+from __future__ import annotations
+
+import time
+from types import TracebackType
+from typing import Optional
+
+from rich.live import Live
+from rich.panel import Panel
+
+
+class LivePanelDisplay:
+ def __init__(self, msg: str | None = None) -> None:
+ self.lines = [msg] if msg else []
+ self._panel = Live(Panel("\n".join(self.lines)), refresh_per_second=5)
+
+ def update(self, msg: str, add_sleep: float | None = None):
+ self.lines.append(msg)
+ self._panel.update(Panel("\n".join(self.lines)))
+ if add_sleep:
+ time.sleep(add_sleep)
+
+ def __enter__(self) -> LivePanelDisplay:
+ self._panel.__enter__()
+ return self
+
+ def __exit__(
+ self,
+ exc_type: Optional[type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType],
+ ) -> None:
+ self._panel.stop()
diff --git a/gradio/cli/commands/reload.py b/gradio/cli/commands/reload.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc75bbbba090fea402822870378bed3cf2879299
--- /dev/null
+++ b/gradio/cli/commands/reload.py
@@ -0,0 +1,129 @@
+"""
+
+Contains the functions that run when `gradio` is called from the command line. Specifically, allows
+
+$ gradio app.py, to run app.py in reload mode where any changes in the app.py file or Gradio library reloads the demo.
+$ gradio app.py my_demo, to use variable names other than "demo"
+"""
+from __future__ import annotations
+
+import inspect
+import os
+import re
+import site
+import subprocess
+import sys
+import threading
+from pathlib import Path
+from typing import List, Optional
+
+import typer
+from rich import print
+
+import gradio
+from gradio import utils
+
+reload_thread = threading.local()
+
+
+def _setup_config(
+ demo_path: Path,
+ demo_name: str = "demo",
+ additional_watch_dirs: list[str] | None = None,
+ encoding: str = "utf-8",
+):
+ original_path = Path(demo_path)
+ app_text = original_path.read_text(encoding=encoding)
+
+ patterns = [
+ f"with gr\\.Blocks\\(.*\\) as {demo_name}",
+ f"{demo_name} = gr\\.Blocks",
+ f"{demo_name} = gr\\.Interface",
+ f"{demo_name} = gr\\.ChatInterface",
+ f"{demo_name} = gr\\.TabbedInterface",
+ ]
+
+ if not any(re.search(p, app_text, flags=re.DOTALL) for p in patterns):
+ print(
+ f"\n[bold red]Warning[/]: Cannot statically find a gradio demo called {demo_name}. "
+ "Reload work may fail."
+ )
+
+ abs_original_path = utils.abspath(original_path)
+
+ if original_path.is_absolute():
+ relpath = original_path.relative_to(Path.cwd())
+ else:
+ relpath = original_path
+ module_name = str(relpath.parent / relpath.stem).replace(os.path.sep, ".")
+
+ gradio_folder = Path(inspect.getfile(gradio)).parent
+
+ message = "Watching:"
+ message_change_count = 0
+
+ watching_dirs = []
+ if str(gradio_folder).strip():
+ package_install = any(
+ utils.is_in_or_equal(gradio_folder, d) for d in site.getsitepackages()
+ )
+ if not package_install:
+ # This is a source install
+ watching_dirs.append(gradio_folder)
+ message += f" '{gradio_folder}'"
+ message_change_count += 1
+
+ abs_parent = abs_original_path.parent
+ if str(abs_parent).strip():
+ watching_dirs.append(abs_parent)
+ if message_change_count == 1:
+ message += ","
+ message += f" '{abs_parent}'"
+
+ abs_current = Path.cwd().absolute()
+ if str(abs_current).strip():
+ watching_dirs.append(abs_current)
+ if message_change_count == 1:
+ message += ","
+ message += f" '{abs_current}'"
+
+ for wd in additional_watch_dirs or []:
+ if Path(wd) not in watching_dirs:
+ watching_dirs.append(wd)
+
+ if message_change_count == 1:
+ message += ","
+ message += f" '{wd}'"
+
+ print(message + "\n")
+
+ # guaranty access to the module of an app
+ sys.path.insert(0, os.getcwd())
+ return module_name, abs_original_path, [str(s) for s in watching_dirs], demo_name
+
+
+def main(
+ demo_path: Path,
+ demo_name: str = "demo",
+ watch_dirs: Optional[List[str]] = None,
+ encoding: str = "utf-8",
+):
+ # default execution pattern to start the server and watch changes
+ module_name, path, watch_dirs, demo_name = _setup_config(
+ demo_path, demo_name, watch_dirs, encoding
+ )
+ # extra_args = args[1:] if len(args) == 1 or args[1].startswith("--") else args[2:]
+ popen = subprocess.Popen(
+ [sys.executable, "-u", path],
+ env=dict(
+ os.environ,
+ GRADIO_WATCH_DIRS=",".join(watch_dirs),
+ GRADIO_WATCH_MODULE_NAME=module_name,
+ GRADIO_WATCH_DEMO_NAME=demo_name,
+ ),
+ )
+ popen.wait()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/gradio/cli/commands/utils.py b/gradio/cli/commands/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gradio/component_meta.py b/gradio/component_meta.py
new file mode 100644
index 0000000000000000000000000000000000000000..d76fa999eb38859ecac3a94311b63333830dfdd2
--- /dev/null
+++ b/gradio/component_meta.py
@@ -0,0 +1,197 @@
+from __future__ import annotations
+
+import ast
+import inspect
+from abc import ABCMeta
+from functools import wraps
+from pathlib import Path
+
+from jinja2 import Template
+
+from gradio.events import EventListener
+from gradio.exceptions import ComponentDefinitionError
+from gradio.utils import no_raise_exception
+
+INTERFACE_TEMPLATE = '''
+{{ contents }}
+
+ {% for event in events %}
+ def {{ event }}(self,
+ fn: Callable | None,
+ inputs: Component | Sequence[Component] | set[Component] | None = None,
+ outputs: Component | Sequence[Component] | None = None,
+ api_name: str | None | Literal[False] = None,
+ scroll_to_output: bool = False,
+ show_progress: Literal["full", "minimal", "hidden"] = "full",
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ cancels: dict[str, Any] | list[dict[str, Any]] | None = None,
+ every: float | None = None,
+ trigger_mode: Literal["once", "multiple", "always_last"] | None = None,
+ js: str | None = None,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ concurrency_id: str | None = None,
+ show_api: bool = True) -> Dependency:
+ """
+ Parameters:
+ fn: the function to call when this event is triggered. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: List of gradio.components to use as inputs. If the function takes no inputs, this should be an empty list.
+ outputs: List of gradio.components to use as outputs. If the function returns no outputs, this should be an empty list.
+ api_name: Defines how the endpoint appears in the API docs. Can be a string, None, or False. If False, the endpoint will not be exposed in the api docs. If set to None, the endpoint will be exposed in the api docs as an unnamed endpoint, although this behavior will be changed in Gradio 4.0. If set to a string, the endpoint will be exposed in the api docs with the given name.
+ scroll_to_output: If True, will scroll to output component on completion
+ show_progress: If True, will show progress animation while pending
+ queue: If True, will place the request on the queue, if the queue has been enabled. If False, will not put this event on the queue, even if the queue has been enabled. If None, will use the queue setting of the gradio app.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ preprocess: If False, will not run preprocessing of component data before running 'fn' (e.g. leaving it as a base64 string if this method is called with the `Image` component).
+ postprocess: If False, will not run postprocessing of component data before returning 'fn' output to the browser.
+ cancels: A list of other events to cancel when this listener is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method. Functions that have not yet run (or generators that are iterating) will be cancelled, but functions that are currently running will be allowed to finish.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ trigger_mode: If "once" (default for all events except `.change()`) would not allow any submissions while an event is pending. If set to "multiple", unlimited submissions are allowed while pending, and "always_last" (default for `.change()` event) would allow a second submission after the pending event is complete.
+ js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ concurrency_limit: If set, this is the maximum number of this event that can be running simultaneously. Can be set to None to mean no concurrency_limit (any number of this event can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `Blocks.queue()`, which itself is 1 by default).
+ concurrency_id: If set, this is the id of the concurrency group. Events with the same concurrency_id will be limited by the lowest set concurrency_limit.
+ show_api: whether to show this event in the "view API" page of the Gradio app, or in the ".view_api()" method of the Gradio clients. Unlike setting api_name to False, setting show_api to False will still allow downstream apps to use this event. If fn is None, show_api will automatically be set to False.
+ """
+ ...
+ {% endfor %}
+'''
+
+
+def create_pyi(class_code: str, events: list[EventListener | str]):
+ template = Template(INTERFACE_TEMPLATE)
+ events = [e if isinstance(e, str) else e.event_name for e in events]
+ return template.render(events=events, contents=class_code)
+
+
+def extract_class_source_code(
+ code: str, class_name: str
+) -> tuple[str, int] | tuple[None, None]:
+ class_start_line = code.find(f"class {class_name}")
+ if class_start_line == -1:
+ return None, None
+
+ class_ast = ast.parse(code)
+ for node in ast.walk(class_ast):
+ if isinstance(node, ast.ClassDef) and node.name == class_name:
+ segment = ast.get_source_segment(code, node)
+ assert segment
+ return segment, node.lineno
+ return None, None
+
+
+def create_or_modify_pyi(
+ component_class: type, class_name: str, events: list[str | EventListener]
+):
+ source_file = Path(inspect.getfile(component_class))
+
+ source_code = source_file.read_text()
+
+ current_impl, lineno = extract_class_source_code(source_code, class_name)
+
+ assert current_impl
+ assert lineno
+ new_interface = create_pyi(current_impl, events)
+
+ pyi_file = source_file.with_suffix(".pyi")
+ if not pyi_file.exists():
+ last_empty_line_before_class = -1
+ lines = source_code.splitlines()
+ for i, line in enumerate(lines):
+ if line in ["", " "]:
+ last_empty_line_before_class = i
+ if i >= lineno:
+ break
+ lines = (
+ lines[:last_empty_line_before_class]
+ + ["from gradio.events import Dependency"]
+ + lines[last_empty_line_before_class:]
+ )
+ with no_raise_exception():
+ pyi_file.write_text("\n".join(lines))
+ current_interface, _ = extract_class_source_code(pyi_file.read_text(), class_name)
+ if not current_interface:
+ with no_raise_exception():
+ with open(str(pyi_file), mode="a") as f:
+ f.write(new_interface)
+ else:
+ contents = pyi_file.read_text()
+ contents = contents.replace(current_interface, new_interface.strip())
+ current_contents = pyi_file.read_text()
+ if current_contents != contents:
+ with no_raise_exception():
+ pyi_file.write_text(contents)
+
+
+def in_event_listener():
+ from gradio.context import LocalContext
+
+ return LocalContext.in_event_listener.get()
+
+
+def updateable(fn):
+ @wraps(fn)
+ def wrapper(*args, **kwargs):
+ fn_args = inspect.getfullargspec(fn).args
+ self = args[0]
+
+ # We need to ensure __init__ is always called at least once
+ # so that the component has all the variables in self defined
+ # test_blocks.py::test_async_iterator_update_with_new_component
+ # checks this
+ initialized_before = hasattr(self, "_constructor_args")
+ if not initialized_before:
+ self._constructor_args = []
+ for i, arg in enumerate(args):
+ if i == 0 or i >= len(fn_args): # skip self, *args
+ continue
+ arg_name = fn_args[i]
+ kwargs[arg_name] = arg
+ self._constructor_args.append(kwargs)
+ if in_event_listener() and initialized_before:
+ return None
+ else:
+ return fn(self, **kwargs)
+
+ return wrapper
+
+
+class ComponentMeta(ABCMeta):
+ def __new__(cls, name, bases, attrs):
+ if "__init__" in attrs:
+ attrs["__init__"] = updateable(attrs["__init__"])
+ if "EVENTS" not in attrs:
+ found = False
+ for base in bases:
+ if hasattr(base, "EVENTS"):
+ found = True
+ break
+ if not found:
+ raise ComponentDefinitionError(
+ f"{name} or its base classes must define an EVENTS list. "
+ "If no events are supported, set it to an empty list."
+ )
+ events = attrs.get("EVENTS", [])
+ if not all(isinstance(e, (str, EventListener)) for e in events):
+ raise ComponentDefinitionError(
+ f"All events for {name} must either be an string or an instance "
+ "of EventListener."
+ )
+ new_events = []
+ for event in events:
+ trigger = (
+ event
+ if isinstance(event, EventListener)
+ else EventListener(event_name=event)
+ ).copy()
+ new_events.append(trigger)
+ trigger.set_doc(component=name)
+ attrs[event] = trigger.listener
+ if "EVENTS" in attrs:
+ attrs["EVENTS"] = new_events
+ component_class = super().__new__(cls, name, bases, attrs)
+ create_or_modify_pyi(component_class, name, events)
+ return component_class
diff --git a/gradio/components/__init__.py b/gradio/components/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..14cf404a7ba867273f9c427cde97956e651f2c31
--- /dev/null
+++ b/gradio/components/__init__.py
@@ -0,0 +1,115 @@
+from gradio.components.annotated_image import AnnotatedImage
+from gradio.components.audio import Audio
+from gradio.components.bar_plot import BarPlot
+from gradio.components.base import (
+ Component,
+ FormComponent,
+ StreamingInput,
+ StreamingOutput,
+ _Keywords,
+ component,
+ get_component_instance,
+)
+from gradio.components.button import Button
+from gradio.components.chatbot import Chatbot
+from gradio.components.checkbox import Checkbox
+from gradio.components.checkboxgroup import CheckboxGroup
+from gradio.components.clear_button import ClearButton
+from gradio.components.code import Code
+from gradio.components.color_picker import ColorPicker
+from gradio.components.dataframe import Dataframe
+from gradio.components.dataset import Dataset
+from gradio.components.dropdown import Dropdown
+from gradio.components.duplicate_button import DuplicateButton
+from gradio.components.fallback import Fallback
+from gradio.components.file import File
+from gradio.components.file_explorer import FileExplorer
+from gradio.components.gallery import Gallery
+from gradio.components.highlighted_text import HighlightedText
+from gradio.components.html import HTML
+from gradio.components.image import Image
+from gradio.components.image_editor import ImageEditor
+from gradio.components.json_component import JSON
+from gradio.components.label import Label
+from gradio.components.line_plot import LinePlot
+from gradio.components.login_button import LoginButton
+from gradio.components.logout_button import LogoutButton
+from gradio.components.markdown import Markdown
+from gradio.components.model3d import Model3D
+from gradio.components.number import Number
+from gradio.components.paramviewer import ParamViewer
+from gradio.components.plot import Plot
+from gradio.components.radio import Radio
+from gradio.components.scatter_plot import ScatterPlot
+from gradio.components.slider import Slider
+from gradio.components.state import State
+from gradio.components.textbox import Textbox
+from gradio.components.upload_button import UploadButton
+from gradio.components.video import Video
+from gradio.layouts import Form
+
+Text = Textbox
+DataFrame = Dataframe
+Highlightedtext = HighlightedText
+Annotatedimage = AnnotatedImage
+Highlight = HighlightedText
+Checkboxgroup = CheckboxGroup
+Json = JSON
+
+__all__ = [
+ "Audio",
+ "BarPlot",
+ "Button",
+ "Chatbot",
+ "ClearButton",
+ "Component",
+ "component",
+ "get_component_instance",
+ "_Keywords",
+ "Checkbox",
+ "CheckboxGroup",
+ "Code",
+ "ColorPicker",
+ "Dataframe",
+ "DataFrame",
+ "Dataset",
+ "DuplicateButton",
+ "Fallback",
+ "Form",
+ "FormComponent",
+ "Gallery",
+ "HTML",
+ "FileExplorer",
+ "Image",
+ "JSON",
+ "Json",
+ "Label",
+ "LinePlot",
+ "LoginButton",
+ "LogoutButton",
+ "Markdown",
+ "Textbox",
+ "Dropdown",
+ "Model3D",
+ "File",
+ "HighlightedText",
+ "AnnotatedImage",
+ "CheckboxGroup",
+ "Text",
+ "Highlightedtext",
+ "Annotatedimage",
+ "Highlight",
+ "Checkboxgroup",
+ "Number",
+ "Plot",
+ "Radio",
+ "ScatterPlot",
+ "Slider",
+ "State",
+ "UploadButton",
+ "Video",
+ "StreamingInput",
+ "StreamingOutput",
+ "ImageEditor",
+ "ParamViewer",
+]
diff --git a/gradio/components/annotated_image.py b/gradio/components/annotated_image.py
new file mode 100644
index 0000000000000000000000000000000000000000..4565ab37b8baceee57adb0cf5a63c63274ccf3e5
--- /dev/null
+++ b/gradio/components/annotated_image.py
@@ -0,0 +1,195 @@
+"""gr.AnnotatedImage() component."""
+
+from __future__ import annotations
+
+from typing import Any, List
+
+import numpy as np
+from gradio_client.documentation import document, set_documentation_group
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+from gradio import processing_utils, utils
+from gradio.components.base import Component
+from gradio.data_classes import FileData, GradioModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
+
+
+class Annotation(GradioModel):
+ image: FileData
+ label: str
+
+
+class AnnotatedImageData(GradioModel):
+ image: FileData
+ annotations: List[Annotation]
+
+
+@document()
+class AnnotatedImage(Component):
+ """
+ Displays a base image and colored subsections on top of that image. Subsections can take the from of rectangles (e.g. object detection) or masks (e.g. image segmentation).
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {Tuple[numpy.ndarray | PIL.Image | str, List[Tuple[numpy.ndarray | Tuple[int, int, int, int], str]]]} consisting of a base image and a list of subsections, that are either (x1, y1, x2, y2) tuples identifying object boundaries, or 0-1 confidence masks of the same shape as the image. A label is provided for each subsection.
+
+ Demos: image_segmentation
+ """
+
+ EVENTS = [Events.select]
+
+ data_model = AnnotatedImageData
+
+ def __init__(
+ self,
+ value: tuple[
+ np.ndarray | _Image.Image | str,
+ list[tuple[np.ndarray | tuple[int, int, int, int], str]],
+ ]
+ | None = None,
+ *,
+ show_legend: bool = True,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ color_map: dict[str, str] | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Tuple of base image and list of (subsection, label) pairs.
+ show_legend: If True, will show a legend of the subsections.
+ height: The height of the image, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the image, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ color_map: A dictionary mapping labels to colors. The colors must be specified as hex codes.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.show_legend = show_legend
+ self.height = height
+ self.width = width
+ self.color_map = color_map
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def postprocess(
+ self,
+ value: tuple[
+ np.ndarray | _Image.Image | str,
+ list[tuple[np.ndarray | tuple[int, int, int, int], str]],
+ ]
+ | None,
+ ) -> AnnotatedImageData | None:
+ """
+ Parameters:
+ value: Tuple of base image and list of subsections, with each subsection a two-part tuple where the first element is a 4 element bounding box or a 0-1 confidence mask, and the second element is the label.
+ Returns:
+ Tuple of base image file and list of subsections, with each subsection a two-part tuple where the first element image path of the mask, and the second element is the label.
+ """
+ if value is None:
+ return None
+ base_img = value[0]
+ if isinstance(base_img, str):
+ base_img_path = base_img
+ base_img = np.array(_Image.open(base_img))
+ elif isinstance(base_img, np.ndarray):
+ base_file = processing_utils.save_img_array_to_cache(
+ base_img, cache_dir=self.GRADIO_CACHE
+ )
+ base_img_path = str(utils.abspath(base_file))
+ elif isinstance(base_img, _Image.Image):
+ base_file = processing_utils.save_pil_to_cache(
+ base_img, cache_dir=self.GRADIO_CACHE
+ )
+ base_img_path = str(utils.abspath(base_file))
+ base_img = np.array(base_img)
+ else:
+ raise ValueError(
+ "AnnotatedImage only accepts filepaths, PIL images or numpy arrays for the base image."
+ )
+
+ sections = []
+ color_map = self.color_map or {}
+
+ def hex_to_rgb(value):
+ value = value.lstrip("#")
+ lv = len(value)
+ return [int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3)]
+
+ for mask, label in value[1]:
+ mask_array = np.zeros((base_img.shape[0], base_img.shape[1]))
+ if isinstance(mask, np.ndarray):
+ mask_array = mask
+ else:
+ x1, y1, x2, y2 = mask
+ border_width = 3
+ mask_array[y1:y2, x1:x2] = 0.5
+ mask_array[y1:y2, x1 : x1 + border_width] = 1
+ mask_array[y1:y2, x2 - border_width : x2] = 1
+ mask_array[y1 : y1 + border_width, x1:x2] = 1
+ mask_array[y2 - border_width : y2, x1:x2] = 1
+
+ if label in color_map:
+ rgb_color = hex_to_rgb(color_map[label])
+ else:
+ rgb_color = [255, 0, 0]
+ colored_mask = np.zeros((base_img.shape[0], base_img.shape[1], 4))
+ solid_mask = np.copy(mask_array)
+ solid_mask[solid_mask > 0] = 1
+
+ colored_mask[:, :, 0] = rgb_color[0] * solid_mask
+ colored_mask[:, :, 1] = rgb_color[1] * solid_mask
+ colored_mask[:, :, 2] = rgb_color[2] * solid_mask
+ colored_mask[:, :, 3] = mask_array * 255
+
+ colored_mask_img = _Image.fromarray((colored_mask).astype(np.uint8))
+
+ mask_file = processing_utils.save_pil_to_cache(
+ colored_mask_img, cache_dir=self.GRADIO_CACHE
+ )
+ mask_file_path = str(utils.abspath(mask_file))
+ sections.append(
+ Annotation(image=FileData(path=mask_file_path), label=label)
+ )
+
+ return AnnotatedImageData(
+ image=FileData(path=base_img_path),
+ annotations=sections,
+ )
+
+ def example_inputs(self) -> Any:
+ return {}
+
+ def preprocess(
+ self, payload: AnnotatedImageData | None
+ ) -> AnnotatedImageData | None:
+ return payload
diff --git a/gradio/components/audio.py b/gradio/components/audio.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e5b048e2b98d9da5ac2e4cd42764df684d609c5
--- /dev/null
+++ b/gradio/components/audio.py
@@ -0,0 +1,313 @@
+"""gr.Audio() component."""
+
+from __future__ import annotations
+
+import dataclasses
+from pathlib import Path
+from typing import Any, Callable, Literal
+
+import httpx
+import numpy as np
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import processing_utils, utils
+from gradio.components.base import Component, StreamingInput, StreamingOutput
+from gradio.data_classes import FileData
+from gradio.events import Events
+from gradio.exceptions import Error
+
+set_documentation_group("component")
+
+
+@dataclasses.dataclass
+class WaveformOptions:
+ """
+ A dataclass for specifying options for the waveform display in the Audio component. An instance of this class can be passed into the `waveform_options` parameter of `gr.Audio`.
+ Parameters:
+ waveform_color: The color (as a hex string or valid CSS color) of the full waveform representing the amplitude of the audio. Defaults to a light gray color.
+ waveform_progress_color: The color (as a hex string or valid CSS color) that the waveform fills with to as the audio plays. Defaults to an orange color.
+ show_recording_waveform: Whether to show the waveform when recording audio. Defaults to True.
+ show_controls: Whether to show the standard HTML audio player below the waveform when recording audio or playing recorded audio. Defaults to False.
+ skip_length: The percentage (between 0 and 100) of the audio to skip when clicking on the skip forward / skip backward buttons. Defaults to 5.
+ sample_rate: The output sample rate (in Hz) of the audio after editing. Defaults to 44100.
+ """
+
+ waveform_color: str = "#9ca3af"
+ waveform_progress_color: str = "#f97316"
+ show_recording_waveform: bool = True
+ show_controls: bool = False
+ skip_length: int | float = 5
+ sample_rate: int = 44100
+
+
+@document()
+class Audio(
+ StreamingInput,
+ StreamingOutput,
+ Component,
+):
+ """
+ Creates an audio component that can be used to upload/record audio (as an input) or display audio (as an output).
+ Preprocessing: depending on `type`, passes the uploaded audio as {str} filepath or a {Tuple(int, numpy.array)} corresponding to (sample rate in Hz, audio data). If the latter, the audio data is a 16-bit int array whose values range from -32768 to 32767 and shape of the audio data array is (samples,) for mono audio or (samples, channels) for multi-channel audio.
+ Postprocessing: expects a {Tuple(int, numpy.array)} corresponding to (sample rate in Hz, audio data as a float or int numpy array) or as a {str} or {pathlib.Path} filepath or URL to an audio file, or bytes for binary content (recommended for streaming). Note: When converting audio data from float format to WAV, the audio is normalized by its peak value to avoid distortion or clipping in the resulting audio.
+ Examples-format: a {str} filepath to a local file that contains audio.
+ Demos: main_note, generate_tone, reverse_audio
+ Guides: real-time-speech-recognition
+ """
+
+ EVENTS = [
+ Events.stream,
+ Events.change,
+ Events.clear,
+ Events.play,
+ Events.pause,
+ Events.stop,
+ Events.pause,
+ Events.start_recording,
+ Events.pause_recording,
+ Events.stop_recording,
+ Events.upload,
+ ]
+
+ data_model = FileData
+
+ def __init__(
+ self,
+ value: str | Path | tuple[int, np.ndarray] | Callable | None = None,
+ *,
+ sources: list[Literal["upload", "microphone"]] | None = None,
+ type: Literal["numpy", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ streaming: bool = False,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ format: Literal["wav", "mp3"] = "wav",
+ autoplay: bool = False,
+ show_download_button: bool | None = None,
+ show_share_button: bool | None = None,
+ editable: bool = True,
+ min_length: int | None = None,
+ max_length: int | None = None,
+ waveform_options: WaveformOptions | dict | None = None,
+ ):
+ """
+ Parameters:
+ value: A path, URL, or [sample_rate, numpy array] tuple (sample rate in Hz, audio data as a float or int numpy array) for the default value that Audio component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ sources: A list of sources permitted for audio. "upload" creates a box where user can drop an audio file, "microphone" creates a microphone input. The first element in the list will be used as the default source. If None, defaults to ["upload", "microphone"], or ["microphone"] if `streaming` is True.
+ type: The format the audio file is converted to before being passed into the prediction function. "numpy" converts the audio to a tuple consisting of: (int sample rate, numpy.array for the data), "filepath" passes a str path to a temporary file containing the audio.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: If True, will allow users to upload and edit an audio file. If False, can only be used to play audio. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ streaming: If set to True when used in a `live` interface as an input, will automatically stream webcam feed. When used set as an output, takes audio chunks yield from the backend and combines them into one streaming audio output.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ format: The file format to save audio files. Either 'wav' or 'mp3'. wav files are lossless but will tend to be larger files. mp3 files tend to be smaller. Default is wav. Applies both when this component is used as an input (when `type` is "format") and when this component is used as an output.
+ autoplay: Whether to automatically play the audio when the component is used as an output. Note: browsers will not autoplay audio files if the user has not interacted with the page yet.
+ show_download_button: If True, will show a download button in the corner of the component for saving audio. If False, icon does not appear. By default, it will be True for output components and False for input components.
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ editable: If True, allows users to manipulate the audio file if the component is interactive. Defaults to True.
+ min_length: The minimum length of audio (in seconds) that the user can pass into the prediction function. If None, there is no minimum length.
+ max_length: The maximum length of audio (in seconds) that the user can pass into the prediction function. If None, there is no maximum length.
+ waveform_options: A dictionary of options for the waveform display. Options include: waveform_color (str), waveform_progress_color (str), show_controls (bool), skip_length (int). Default is None, which uses the default values for these options.
+ """
+ valid_sources: list[Literal["upload", "microphone"]] = ["upload", "microphone"]
+ if sources is None:
+ self.sources = ["microphone"] if streaming else valid_sources
+ elif isinstance(sources, str) and sources in valid_sources:
+ self.sources = [sources]
+ elif isinstance(sources, list):
+ self.sources = sources
+ else:
+ raise ValueError(
+ f"`sources` must be a list consisting of elements in {valid_sources}"
+ )
+ for source in self.sources:
+ if source not in valid_sources:
+ raise ValueError(
+ f"`sources` must a list consisting of elements in {valid_sources}"
+ )
+ valid_types = ["numpy", "filepath"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.streaming = streaming
+ if self.streaming and "microphone" not in self.sources:
+ raise ValueError(
+ "Audio streaming only available if sources includes 'microphone'."
+ )
+ self.format = format
+ self.autoplay = autoplay
+ self.show_download_button = show_download_button
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+ self.editable = editable
+ if waveform_options is None:
+ self.waveform_options = WaveformOptions()
+ elif isinstance(waveform_options, dict):
+ self.waveform_options = WaveformOptions(**waveform_options)
+ else:
+ self.waveform_options = waveform_options
+ self.min_length = min_length
+ self.max_length = max_length
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> Any:
+ return "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav"
+
+ def preprocess(
+ self, payload: FileData | None
+ ) -> tuple[int, np.ndarray] | str | None:
+ if payload is None:
+ return payload
+
+ assert payload.path
+ # Need a unique name for the file to avoid re-using the same audio file if
+ # a user submits the same audio file twice
+ temp_file_path = Path(payload.path)
+ output_file_name = str(
+ temp_file_path.with_name(f"{temp_file_path.stem}{temp_file_path.suffix}")
+ )
+
+ sample_rate, data = processing_utils.audio_from_file(temp_file_path)
+
+ duration = len(data) / sample_rate
+ if self.min_length is not None and duration < self.min_length:
+ raise Error(
+ f"Audio is too short, and must be at least {self.min_length} seconds"
+ )
+ if self.max_length is not None and duration > self.max_length:
+ raise Error(
+ f"Audio is too long, and must be at most {self.max_length} seconds"
+ )
+
+ if self.type == "numpy":
+ return sample_rate, data
+ elif self.type == "filepath":
+ output_file = str(Path(output_file_name).with_suffix(f".{self.format}"))
+ processing_utils.audio_to_file(
+ sample_rate, data, output_file, format=self.format
+ )
+ return output_file
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'numpy', 'filepath'."
+ )
+
+ def postprocess(
+ self, value: tuple[int, np.ndarray] | str | Path | bytes | None
+ ) -> FileData | bytes | None:
+ """
+ Parameters:
+ value: audio data in either of the following formats: a tuple of (sample_rate, data), or a string filepath or URL to an audio file, or None.
+ Returns:
+ base64 url data
+ """
+ orig_name = None
+ if value is None:
+ return None
+ if isinstance(value, bytes):
+ if self.streaming:
+ return value
+ file_path = processing_utils.save_bytes_to_cache(
+ value, "audio", cache_dir=self.GRADIO_CACHE
+ )
+ orig_name = Path(file_path).name
+ elif isinstance(value, tuple):
+ sample_rate, data = value
+ file_path = processing_utils.save_audio_to_cache(
+ data, sample_rate, format=self.format, cache_dir=self.GRADIO_CACHE
+ )
+ orig_name = Path(file_path).name
+ else:
+ if not isinstance(value, (str, Path)):
+ raise ValueError(f"Cannot process {value} as Audio")
+ file_path = str(value)
+ orig_name = Path(file_path).name if Path(file_path).exists() else None
+ return FileData(path=file_path, orig_name=orig_name)
+
+ def stream_output(
+ self, value, output_id: str, first_chunk: bool
+ ) -> tuple[bytes | None, Any]:
+ output_file = {
+ "path": output_id,
+ "is_stream": True,
+ }
+ if value is None:
+ return None, output_file
+ if isinstance(value, bytes):
+ return value, output_file
+ if client_utils.is_http_url_like(value["path"]):
+ response = httpx.get(value["path"])
+ binary_data = response.content
+ else:
+ output_file["orig_name"] = value["orig_name"]
+ file_path = value["path"]
+ is_wav = file_path.endswith(".wav")
+ with open(file_path, "rb") as f:
+ binary_data = f.read()
+ if is_wav:
+ # strip length information from first chunk header, remove headers entirely from subsequent chunks
+ if first_chunk:
+ binary_data = (
+ binary_data[:4] + b"\xFF\xFF\xFF\xFF" + binary_data[8:]
+ )
+ binary_data = (
+ binary_data[:40] + b"\xFF\xFF\xFF\xFF" + binary_data[44:]
+ )
+ else:
+ binary_data = binary_data[44:]
+ return binary_data, output_file
+
+ def process_example(
+ self, value: tuple[int, np.ndarray] | str | Path | bytes | None
+ ) -> str:
+ if value is None:
+ return ""
+ elif isinstance(value, (str, Path)):
+ return Path(value).name
+ return "(audio)"
+
+ def check_streamable(self):
+ if (
+ self.sources is not None
+ and "microphone" not in self.sources
+ and self.streaming
+ ):
+ raise ValueError(
+ "Audio streaming only available if source includes 'microphone'."
+ )
diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e5e4b58ffea99135018be1699700519dad40fd6
--- /dev/null
+++ b/gradio/components/bar_plot.py
@@ -0,0 +1,297 @@
+"""gr.BarPlot() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+import altair as alt
+import pandas as pd
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.plot import AltairPlot, AltairPlotData, Plot
+
+set_documentation_group("component")
+
+
+@document()
+class BarPlot(Plot):
+ """
+ Create a bar plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: bar_plot, chicago-bikeshare-dashboard
+ """
+
+ data_model = AltairPlotData
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ vertical: bool = True,
+ group: str | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ group_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ y_lim: list[int] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ every: float | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ sort: Literal["x", "y", "-x", "-y"] | None = None,
+ show_actions_button: bool = False,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the bar color. Must be categorical (discrete values).
+ vertical: If True, the bars will be displayed vertically. If False, the x and y axis will be switched, displaying the bars horizontally. Default is True.
+ group: The column with which to split the overall plot into smaller subplots.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers over a bar.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ x_label_angle: The angle (in degrees) of the x axis labels. Positive values are clockwise, and negative values are counter-clockwise.
+ y_label_angle: The angle (in degrees) of the y axis labels. Positive values are clockwise, and negative values are counter-clockwise.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ group_title: The label displayed on top of the subplot columns (or rows if vertical=True). Use an empty string to omit.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ sort: Specifies the sorting axis as either "x", "y", "-x" or "-y". If None, no sorting is applied.
+ show_actions_button: Whether to show the actions button on the top right corner of the plot.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.vertical = vertical
+ self.group = group
+ self.group_title = group_title
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.x_label_angle = x_label_angle
+ self.y_label_angle = y_label_angle
+ self.color_legend_title = color_legend_title
+ self.group_title = group_title
+ self.color_legend_position = color_legend_position
+ self.y_lim = y_lim
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ self.sort = sort
+ self.show_actions_button = show_actions_button
+ super().__init__(
+ value=value,
+ label=label,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ every=every,
+ )
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ vertical: bool = True,
+ group: str | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ group_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ y_lim: list[int] | None = None,
+ interactive: bool | None = True,
+ sort: Literal["x", "y", "-x", "-y"] | None = None,
+ ):
+ """Helper for creating the bar plot."""
+ interactive = True if interactive is None else interactive
+ orientation = (
+ {"field": group, "title": group_title if group_title is not None else group}
+ if group
+ else {}
+ )
+
+ x_title = x_title or x
+ y_title = y_title or y
+
+ # If horizontal, switch x and y
+ if not vertical:
+ y, x = x, y
+ x = f"sum({x}):Q"
+ y_title, x_title = x_title, y_title
+ orientation = {"row": alt.Row(**orientation)} if orientation else {} # type: ignore
+ x_lim = y_lim
+ y_lim = None
+ else:
+ y = f"sum({y}):Q"
+ x_lim = None
+ orientation = {"column": alt.Column(**orientation)} if orientation else {} # type: ignore
+
+ encodings = dict(
+ x=alt.X(
+ x, # type: ignore
+ title=x_title, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ axis=alt.Axis(labelAngle=x_label_angle)
+ if x_label_angle is not None
+ else alt.Axis(),
+ sort=sort if vertical and sort is not None else None,
+ ),
+ y=alt.Y(
+ y, # type: ignore
+ title=y_title, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ axis=alt.Axis(labelAngle=y_label_angle)
+ if y_label_angle is not None
+ else alt.Axis(),
+ sort=sort if not vertical and sort is not None else None,
+ ),
+ **orientation,
+ )
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+
+ if color:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ encodings["color"] = {
+ "field": color,
+ "type": "nominal",
+ "scale": {"domain": domain, "range": range_},
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ }
+
+ if tooltip:
+ encodings["tooltip"] = tooltip
+
+ chart = (
+ alt.Chart(value) # type: ignore
+ .mark_bar() # type: ignore
+ .encode(**encodings)
+ .properties(background="transparent", **properties)
+ )
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(
+ self, value: pd.DataFrame | dict | None
+ ) -> AltairPlotData | dict | None:
+ # if None or update
+ if value is None or isinstance(value, dict):
+ return value
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=value,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ vertical=self.vertical,
+ group=self.group,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ x_label_angle=self.x_label_angle,
+ y_label_angle=self.y_label_angle,
+ color_legend_title=self.color_legend_title,
+ color_legend_position=self.color_legend_position, # type: ignore
+ group_title=self.group_title,
+ y_lim=self.y_lim,
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ sort=self.sort, # type: ignore
+ )
+
+ return AltairPlotData(type="altair", plot=chart.to_json(), chart="bar")
+
+ def example_inputs(self) -> dict[str, Any]:
+ return {}
+
+ def preprocess(self, payload: AltairPlotData) -> AltairPlotData:
+ return payload
diff --git a/gradio/components/base.py b/gradio/components/base.py
new file mode 100644
index 0000000000000000000000000000000000000000..5966f52589e581fded1aa4f89388a36bf8f08e4e
--- /dev/null
+++ b/gradio/components/base.py
@@ -0,0 +1,369 @@
+"""Contains all of the components that can be used with Gradio Interface / Blocks.
+Along with the docs for each component, you can find the names of example demos that use
+each component. These demos are located in the `demo` directory."""
+
+from __future__ import annotations
+
+import abc
+import hashlib
+import json
+import sys
+import warnings
+from abc import ABC, abstractmethod
+from enum import Enum
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, Callable
+
+from gradio_client.documentation import set_documentation_group
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+from gradio import utils
+from gradio.blocks import Block, BlockContext
+from gradio.component_meta import ComponentMeta
+from gradio.data_classes import GradioDataModel
+from gradio.events import EventListener
+from gradio.layouts import Form
+from gradio.processing_utils import move_files_to_cache
+
+if TYPE_CHECKING:
+ from typing import TypedDict
+
+ class DataframeData(TypedDict):
+ headers: list[str]
+ data: list[list[str | int | bool]]
+
+
+set_documentation_group("component")
+_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
+
+
+class _Keywords(Enum):
+ NO_VALUE = "NO_VALUE" # Used as a sentinel to determine if nothing is provided as a argument for `value` in `Component.update()`
+ FINISHED_ITERATING = "FINISHED_ITERATING" # Used to skip processing of a component's value (needed for generators + state)
+
+
+class ComponentBase(ABC, metaclass=ComponentMeta):
+ EVENTS: list[EventListener | str] = []
+
+ @abstractmethod
+ def preprocess(self, payload: Any) -> Any:
+ """
+ Any preprocessing needed to be performed on function input.
+ """
+ return payload
+
+ @abstractmethod
+ def postprocess(self, value):
+ """
+ Any postprocessing needed to be performed on function output.
+ """
+ return value
+
+ @abstractmethod
+ def process_example(self, value):
+ """
+ Process the input data in a way that can be displayed by the examples dataset component in the front-end.
+
+ For example, only return the name of a file as opposed to a full path. Or get the head of a dataframe.
+ The return value must be able to be json-serializable to put in the config.
+ """
+ pass
+
+ @abstractmethod
+ def api_info(self) -> dict[str, list[str]]:
+ """
+ The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description].
+ Keys of the dictionary are: raw_input, raw_output, serialized_input, serialized_output
+ """
+ pass
+
+ @abstractmethod
+ def example_inputs(self) -> Any:
+ """
+ The example inputs for this component as a dictionary whose values are example inputs compatible with this component.
+ Keys of the dictionary are: raw, serialized
+ """
+ pass
+
+ @abstractmethod
+ def flag(self, payload: Any | GradioDataModel, flag_dir: str | Path = "") -> str:
+ """
+ Write the component's value to a format that can be stored in a csv or jsonl format for flagging.
+ """
+ pass
+
+ @abstractmethod
+ def read_from_flag(
+ self,
+ payload: Any,
+ flag_dir: str | Path | None = None,
+ ) -> GradioDataModel | Any:
+ """
+ Convert the data from the csv or jsonl file into the component state.
+ """
+ return payload
+
+ @property
+ @abstractmethod
+ def skip_api(self):
+ """Whether this component should be skipped from the api return value"""
+
+ @classmethod
+ def has_event(cls, event: str | EventListener) -> bool:
+ return event in cls.EVENTS
+
+ @classmethod
+ def get_component_class_id(cls) -> str:
+ module_name = cls.__module__
+ module_path = sys.modules[module_name].__file__
+ module_hash = hashlib.md5(f"{cls.__name__}_{module_path}".encode()).hexdigest()
+ return module_hash
+
+
+def server(fn):
+ fn._is_server_fn = True
+ return fn
+
+
+class Component(ComponentBase, Block):
+ """
+ A base class for defining methods that all input/output components should have.
+ """
+
+ def __init__(
+ self,
+ value: Any = None,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int | None = None,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ load_fn: Callable | None = None,
+ every: float | None = None,
+ ):
+ self.server_fns = [
+ value
+ for value in self.__class__.__dict__.values()
+ if callable(value) and getattr(value, "_is_server_fn", False)
+ ]
+
+ # Svelte components expect elem_classes to be a list
+ # If we don't do this, returning a new component for an
+ # update will break the frontend
+ if not elem_classes:
+ elem_classes = []
+
+ # This gets overridden when `select` is called
+ self._selectable = False
+ if not hasattr(self, "data_model"):
+ self.data_model: type[GradioDataModel] | None = None
+
+ Block.__init__(
+ self,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ visible=visible,
+ render=render,
+ )
+ if isinstance(self, StreamingInput):
+ self.check_streamable()
+
+ self.label = label
+ self.info = info
+ if not container:
+ if show_label:
+ warnings.warn("show_label has no effect when container is False.")
+ show_label = False
+ if show_label is None:
+ show_label = True
+ self.show_label = show_label
+ self.container = container
+ if scale is not None and scale != round(scale):
+ warnings.warn(
+ f"'scale' value should be an integer. Using {scale} will cause issues."
+ )
+ self.scale = scale
+ self.min_width = min_width
+ self.interactive = interactive
+
+ # load_event is set in the Blocks.attach_load_events method
+ self.load_event: None | dict[str, Any] = None
+ self.load_event_to_attach: None | tuple[Callable, float | None] = None
+ load_fn, initial_value = self.get_load_fn_and_initial_value(value)
+ initial_value = self.postprocess(initial_value)
+ self.value = move_files_to_cache(initial_value, self, postprocess=True) # type: ignore
+
+ if callable(load_fn):
+ self.attach_load_event(load_fn, every)
+
+ self.component_class_id = self.__class__.get_component_class_id()
+
+ TEMPLATE_DIR = "./templates/"
+ FRONTEND_DIR = "../../frontend/"
+
+ def get_config(self):
+ config = super().get_config()
+ if self.info:
+ config["info"] = self.info
+ if len(self.server_fns):
+ config["server_fns"] = [fn.__name__ for fn in self.server_fns]
+ config.pop("render", None)
+ return config
+
+ @property
+ def skip_api(self):
+ return False
+
+ @staticmethod
+ def get_load_fn_and_initial_value(value):
+ if callable(value):
+ initial_value = value()
+ load_fn = value
+ else:
+ initial_value = value
+ load_fn = None
+ return load_fn, initial_value
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ return f"{self.get_block_name()}"
+
+ def attach_load_event(self, callable: Callable, every: float | None):
+ """Add a load event that runs `callable`, optionally every `every` seconds."""
+ self.load_event_to_attach = (callable, every)
+
+ def process_example(self, value):
+ """
+ Process the input data in a way that can be displayed by the examples dataset component in the front-end.
+ By default, this calls the `.postprocess()` method of the component. However, if the `.postprocess()` method is
+ computationally intensive, or returns a large payload, a custom implementation may be appropriate.
+
+ For example, the `process_example()` method of the `gr.Audio()` component only returns the name of the file, not
+ the processed audio file. The `.process_example()` method of the `gr.Dataframe()` returns the head of a dataframe
+ instead of the full dataframe.
+
+ The return value of this method must be json-serializable to put in the config.
+ """
+ return self.postprocess(value)
+
+ def as_example(self, value):
+ """Deprecated and replaced by `process_example()`."""
+ return self.process_example(value)
+
+ def api_info(self) -> dict[str, Any]:
+ """
+ The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description].
+ Keys of the dictionary are: raw_input, raw_output, serialized_input, serialized_output
+ """
+ if self.data_model is not None:
+ return self.data_model.model_json_schema()
+ raise NotImplementedError(
+ f"The api_info method has not been implemented for {self.get_block_name()}"
+ )
+
+ def flag(self, payload: Any, flag_dir: str | Path = "") -> str:
+ """
+ Write the component's value to a format that can be stored in a csv or jsonl format for flagging.
+ """
+ if self.data_model:
+ payload = self.data_model.from_json(payload)
+ Path(flag_dir).mkdir(exist_ok=True)
+ return payload.copy_to_dir(flag_dir).model_dump_json()
+ return payload
+
+ def read_from_flag(
+ self,
+ payload: Any,
+ flag_dir: str | Path | None = None,
+ ):
+ """
+ Convert the data from the csv or jsonl file into the component state.
+ """
+ if self.data_model:
+ return self.data_model.from_json(json.loads(payload))
+ return payload
+
+
+class FormComponent(Component):
+ def get_expected_parent(self) -> type[Form] | None:
+ if getattr(self, "container", None) is False:
+ return None
+ return Form
+
+ def preprocess(self, payload: Any) -> Any:
+ return payload
+
+ def postprocess(self, value):
+ return value
+
+
+class StreamingOutput(metaclass=abc.ABCMeta):
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+ self.streaming: bool
+
+ @abc.abstractmethod
+ def stream_output(
+ self, value, output_id: str, first_chunk: bool
+ ) -> tuple[bytes, Any]:
+ pass
+
+
+class StreamingInput(metaclass=abc.ABCMeta):
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+
+ @abc.abstractmethod
+ def check_streamable(self):
+ """Used to check if streaming is supported given the input."""
+ pass
+
+
+def component(cls_name: str, render: bool) -> Component:
+ obj = utils.component_or_layout_class(cls_name)(render=render)
+ if isinstance(obj, BlockContext):
+ raise ValueError(f"Invalid component: {obj.__class__}")
+ assert isinstance(obj, Component)
+ return obj
+
+
+def get_component_instance(
+ comp: str | dict | Component, render: bool = False, unrender: bool = False
+) -> Component:
+ """
+ Returns a component instance from a string, dict, or Component object.
+ Parameters:
+ comp: the component to instantiate. If a string, must be the name of a component, e.g. "dropdown". If a dict, must have a "name" key, e.g. {"name": "dropdown", "choices": ["a", "b"]}. If a Component object, will be returned as is.
+ render: whether to render the component. If True, renders the component (if not already rendered). If False, does not do anything.
+ unrender: whether to unrender the component. If True, unrenders the the component (if already rendered) -- this is useful when constructing an Interface or ChatInterface inside of a Blocks. If False, does not do anything.
+ """
+ if isinstance(comp, str):
+ component_obj = component(comp, render=render)
+ elif isinstance(comp, dict):
+ name = comp.pop("name")
+ component_cls = utils.component_or_layout_class(name)
+ component_obj = component_cls(**comp, render=render)
+ if isinstance(component_obj, BlockContext):
+ raise ValueError(f"Invalid component: {name}")
+ elif isinstance(comp, Component):
+ component_obj = comp
+ else:
+ raise ValueError(
+ f"Component must provided as a `str` or `dict` or `Component` but is {comp}"
+ )
+
+ if render and not component_obj.is_rendered:
+ component_obj.render()
+ elif unrender and component_obj.is_rendered:
+ component_obj.unrender()
+ assert isinstance(component_obj, Component)
+ return component_obj
diff --git a/gradio/components/button.py b/gradio/components/button.py
new file mode 100644
index 0000000000000000000000000000000000000000..20a4d1537d73f0876c3073faa8b4d2a4ddddc34e
--- /dev/null
+++ b/gradio/components/button.py
@@ -0,0 +1,87 @@
+"""gr.Button() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Button(Component):
+ """
+ Used to create a button, that can be assigned arbitrary click() events. The label (value) of the button can be used as an input or set via the output of a function.
+
+ Preprocessing: passes the button value as a {str} into the function
+ Postprocessing: expects a {str} to be returned from a function, which is set as the label of the button
+ Demos: blocks_inputs, blocks_kinematics
+ """
+
+ EVENTS = [Events.click]
+
+ def __init__(
+ self,
+ value: str | Callable = "Run",
+ *,
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ size: Literal["sm", "lg"] | None = None,
+ icon: str | None = None,
+ link: str | None = None,
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ scale: int | None = None,
+ min_width: int | None = None,
+ ):
+ """
+ Parameters:
+ value: Default text for the button to display. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ variant: 'primary' for main call-to-action, 'secondary' for a more subdued style, 'stop' for a stop button.
+ size: Size of the button. Can be "sm" or "lg".
+ icon: URL or path to the icon file to display within the button. If None, no icon will be displayed. Must be within the working directory of the Gradio app or an external URL.
+ link: URL to open when the button is clicked. If None, no link will be used.
+ visible: If False, component will be hidden.
+ interactive: If False, the Button will be in a disabled state.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ """
+ super().__init__(
+ every=every,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ interactive=interactive,
+ scale=scale,
+ min_width=min_width,
+ )
+ self.icon = self.move_resource_to_block_cache(icon)
+ self.variant = variant
+ self.size = size
+ self.link = link
+
+ @property
+ def skip_api(self):
+ return True
+
+ def preprocess(self, payload: str) -> str:
+ return payload
+
+ def postprocess(self, value: str) -> str:
+ return value
+
+ def example_inputs(self) -> Any:
+ return None
diff --git a/gradio/components/chatbot.py b/gradio/components/chatbot.py
new file mode 100644
index 0000000000000000000000000000000000000000..69d3ac55dc43507a72b2ea5e892df208dbd1e40a
--- /dev/null
+++ b/gradio/components/chatbot.py
@@ -0,0 +1,220 @@
+"""gr.Chatbot() component."""
+
+from __future__ import annotations
+
+import inspect
+from pathlib import Path
+from typing import Any, Callable, List, Literal, Optional, Tuple, Union
+
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import processing_utils, utils
+from gradio.components.base import Component
+from gradio.data_classes import FileData, GradioModel, GradioRootModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+class FileMessage(GradioModel):
+ file: FileData
+ alt_text: Optional[str] = None
+
+
+class ChatbotData(GradioRootModel):
+ root: List[Tuple[Union[str, FileMessage, None], Union[str, FileMessage, None]]]
+
+
+@document()
+class Chatbot(Component):
+ """
+ Displays a chatbot output showing both user submitted messages and responses. Supports a subset of Markdown including bold, italics, code, tables. Also supports audio/video/image files, which are displayed in the Chatbot, and other kinds of files which are displayed as links.
+ Preprocessing: passes the messages in the Chatbot as a {List[List[str | None | Tuple]]}, i.e. a list of lists. The inner list has 2 elements: the user message and the response message. See `Postprocessing` for the format of these messages.
+ Postprocessing: expects function to return a {List[List[str | None | Tuple]]}, i.e. a list of lists. The inner list should have 2 elements: the user message and the response message. The individual messages can be (1) strings in valid Markdown, (2) tuples if sending files: (a filepath or URL to a file, [optional string alt text]) -- if the file is image/video/audio, it is displayed in the Chatbot, or (3) None, in which case the message is not displayed.
+
+ Demos: chatbot_simple, chatbot_multimodal
+ Guides: creating-a-chatbot
+ """
+
+ EVENTS = [Events.change, Events.select, Events.like]
+ data_model = ChatbotData
+
+ def __init__(
+ self,
+ value: list[list[str | tuple[str] | tuple[str | Path, str] | None]]
+ | Callable
+ | None = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ height: int | str | None = None,
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ rtl: bool = False,
+ show_share_button: bool | None = None,
+ show_copy_button: bool = False,
+ avatar_images: tuple[str | Path | None, str | Path | None] | None = None,
+ sanitize_html: bool = True,
+ render_markdown: bool = True,
+ bubble_full_width: bool = True,
+ line_breaks: bool = True,
+ likeable: bool = False,
+ layout: Literal["panel", "bubble"] | None = None,
+ ):
+ """
+ Parameters:
+ value: Default value to show in chatbot. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ height: The height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ latex_delimiters: A list of dicts of the form {"left": open delimiter (str), "right": close delimiter (str), "display": whether to display in newline (bool)} that will be used to render LaTeX expressions. If not provided, `latex_delimiters` is set to `[{ "left": "$$", "right": "$$", "display": True }]`, so only expressions enclosed in $$ delimiters will be rendered as LaTeX, and in a new line. Pass in an empty list to disable LaTeX rendering. For more information, see the [KaTeX documentation](https://katex.org/docs/autorender.html).
+ rtl: If True, sets the direction of the rendered text to right-to-left. Default is False, which renders text left-to-right.
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ show_copy_button: If True, will show a copy button for each chatbot message.
+ avatar_images: Tuple of two avatar image paths or URLs for user and bot (in that order). Pass None for either the user or bot image to skip. Must be within the working directory of the Gradio app or an external URL.
+ sanitize_html: If False, will disable HTML sanitization for chatbot messages. This is not recommended, as it can lead to security vulnerabilities.
+ render_markdown: If False, will disable Markdown rendering for chatbot messages.
+ bubble_full_width: If False, the chat bubble will fit to the content of the message. If True (default), the chat bubble will be the full width of the component.
+ line_breaks: If True (default), will enable Github-flavored Markdown line breaks in chatbot messages. If False, single new lines will be ignored. Only applies if `render_markdown` is True.
+ likeable: Whether the chat messages display a like or dislike button. Set automatically by the .like method but has to be present in the signature for it to show up in the config.
+ layout: If "panel", will display the chatbot in a llm style layout. If "bubble", will display the chatbot with message bubbles, with the user and bot messages on alterating sides. Will default to "bubble".
+ """
+ self.likeable = likeable
+ self.height = height
+ self.rtl = rtl
+ if latex_delimiters is None:
+ latex_delimiters = [{"left": "$$", "right": "$$", "display": True}]
+ self.latex_delimiters = latex_delimiters
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+ self.render_markdown = render_markdown
+ self.show_copy_button = show_copy_button
+ self.sanitize_html = sanitize_html
+ self.bubble_full_width = bubble_full_width
+ self.line_breaks = line_breaks
+ self.layout = layout
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+ self.avatar_images: list[str | None] = [None, None]
+ if avatar_images is None:
+ pass
+ else:
+ self.avatar_images = [
+ processing_utils.move_resource_to_block_cache(avatar_images[0], self),
+ processing_utils.move_resource_to_block_cache(avatar_images[1], self),
+ ]
+
+ def _preprocess_chat_messages(
+ self, chat_message: str | FileMessage | None
+ ) -> str | tuple[str | None] | tuple[str | None, str] | None:
+ if chat_message is None:
+ return None
+ elif isinstance(chat_message, FileMessage):
+ if chat_message.alt_text is not None:
+ return (chat_message.file.path, chat_message.alt_text)
+ else:
+ return (chat_message.file.path,)
+ elif isinstance(chat_message, str):
+ return chat_message
+ else:
+ raise ValueError(f"Invalid message for Chatbot component: {chat_message}")
+
+ def preprocess(
+ self,
+ payload: ChatbotData,
+ ) -> list[list[str | tuple[str] | tuple[str, str] | None]]:
+ if payload is None:
+ return payload
+ processed_messages = []
+ for message_pair in payload.root:
+ if not isinstance(message_pair, (tuple, list)):
+ raise TypeError(
+ f"Expected a list of lists or list of tuples. Received: {message_pair}"
+ )
+ if len(message_pair) != 2:
+ raise TypeError(
+ f"Expected a list of lists of length 2 or list of tuples of length 2. Received: {message_pair}"
+ )
+ processed_messages.append(
+ [
+ self._preprocess_chat_messages(message_pair[0]),
+ self._preprocess_chat_messages(message_pair[1]),
+ ]
+ )
+ return processed_messages
+
+ def _postprocess_chat_messages(
+ self, chat_message: str | tuple | list | None
+ ) -> str | FileMessage | None:
+ if chat_message is None:
+ return None
+ elif isinstance(chat_message, (tuple, list)):
+ filepath = str(chat_message[0])
+
+ mime_type = client_utils.get_mimetype(filepath)
+ return FileMessage(
+ file=FileData(path=filepath, mime_type=mime_type),
+ alt_text=chat_message[1] if len(chat_message) > 1 else None,
+ )
+ elif isinstance(chat_message, str):
+ chat_message = inspect.cleandoc(chat_message)
+ return chat_message
+ else:
+ raise ValueError(f"Invalid message for Chatbot component: {chat_message}")
+
+ def postprocess(
+ self,
+ value: list[list[str | tuple[str] | tuple[str, str] | None] | tuple],
+ ) -> ChatbotData:
+ if value is None:
+ return ChatbotData(root=[])
+ processed_messages = []
+ for message_pair in value:
+ if not isinstance(message_pair, (tuple, list)):
+ raise TypeError(
+ f"Expected a list of lists or list of tuples. Received: {message_pair}"
+ )
+ if len(message_pair) != 2:
+ raise TypeError(
+ f"Expected a list of lists of length 2 or list of tuples of length 2. Received: {message_pair}"
+ )
+ processed_messages.append(
+ [
+ self._postprocess_chat_messages(message_pair[0]),
+ self._postprocess_chat_messages(message_pair[1]),
+ ]
+ )
+ return ChatbotData(root=processed_messages)
+
+ def example_inputs(self) -> Any:
+ return [["Hello!", None]]
diff --git a/gradio/components/checkbox.py b/gradio/components/checkbox.py
new file mode 100644
index 0000000000000000000000000000000000000000..44ef1f9604026437b8b0880c476beb290217749f
--- /dev/null
+++ b/gradio/components/checkbox.py
@@ -0,0 +1,87 @@
+"""gr.Checkbox() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Checkbox(FormComponent):
+ """
+ Creates a checkbox that can be set to `True` or `False`.
+
+ Preprocessing: passes the status of the checkbox as a {bool} into the function.
+ Postprocessing: expects a {bool} returned from the function and, if it is True, checks the checkbox.
+ Examples-format: a {bool} representing whether the box is checked.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ EVENTS = [Events.change, Events.input, Events.select]
+
+ def __init__(
+ self,
+ value: bool | Callable = False,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: if True, checked by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, this checkbox can be checked; if False, checking will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "boolean"}
+
+ def example_inputs(self) -> bool:
+ return True
+
+ def preprocess(self, payload: bool | None) -> bool | None:
+ return payload
+
+ def postprocess(self, value: bool | None) -> bool | None:
+ return value
diff --git a/gradio/components/checkboxgroup.py b/gradio/components/checkboxgroup.py
new file mode 100644
index 0000000000000000000000000000000000000000..f46e2516074977f0826873bfd0b64b9421e3cfd0
--- /dev/null
+++ b/gradio/components/checkboxgroup.py
@@ -0,0 +1,126 @@
+"""gr.CheckboxGroup() component"""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class CheckboxGroup(FormComponent):
+ """
+ Creates a set of checkboxes of which a subset can be checked.
+ Preprocessing: passes the list of checked checkboxes as a {List[str | int | float]} or their indices as a {List[int]} into the function, depending on `type`.
+ Postprocessing: expects a {List[str | int | float]}, each element of which becomes a checked checkbox.
+ Examples-format: a {List[str | int | float]} representing the values to be checked.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ EVENTS = [Events.change, Events.input, Events.select]
+
+ def __init__(
+ self,
+ choices: list[str | int | float | tuple[str, str | int | float]] | None = None,
+ *,
+ value: list[str | float | int] | str | float | int | Callable | None = None,
+ type: Literal["value", "index"] = "value",
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ choices: A list of string or numeric options to select from. An option can also be a tuple of the form (name, value), where name is the displayed name of the checkbox button and value is the value to be passed to the function, or returned by the function.
+ value: Default selected list of options. If a single choice is selected, it can be passed in as a string or numeric type. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the list of strings of the choices selected, "index" returns the list of indices of the choices selected.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: Additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: If True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: Relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: Minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: If True, choices in this checkbox group will be checkable; if False, checking will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.choices = (
+ # Although we expect choices to be a list of tuples, it can be a list of tuples if the Gradio app
+ # is loaded with gr.load() since Python tuples are converted to lists in JSON.
+ [tuple(c) if isinstance(c, (tuple, list)) else (str(c), c) for c in choices]
+ if choices
+ else []
+ )
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> Any:
+ return [self.choices[0][1]] if self.choices else None
+
+ def api_info(self) -> dict[str, Any]:
+ return {
+ "items": {"enum": [c[1] for c in self.choices], "type": "string"},
+ "title": "Checkbox Group",
+ "type": "array",
+ }
+
+ def preprocess(
+ self, payload: list[str | int | float]
+ ) -> list[str | int | float] | list[int | None]:
+ if self.type == "value":
+ return payload
+ elif self.type == "index":
+ choice_values = [value for _, value in self.choices]
+ return [
+ choice_values.index(choice) if choice in choice_values else None
+ for choice in payload
+ ]
+ else:
+ raise ValueError(
+ f"Unknown type: {self.type}. Please choose from: 'value', 'index'."
+ )
+
+ def postprocess(
+ self, value: list[str | int | float] | str | int | float | None
+ ) -> list[str | int | float]:
+ if value is None:
+ return []
+ if not isinstance(value, list):
+ value = [value]
+ return value
diff --git a/gradio/components/clear_button.py b/gradio/components/clear_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ad807afc6f923b250dda4820996fb6cec435f47
--- /dev/null
+++ b/gradio/components/clear_button.py
@@ -0,0 +1,121 @@
+""" Predefined buttons with bound events that can be included in a gr.Blocks for convenience. """
+
+from __future__ import annotations
+
+import copy
+import json
+from typing import Any, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components import Button, Component
+from gradio.context import Context
+from gradio.data_classes import GradioModel, GradioRootModel
+from gradio.utils import resolve_singleton
+
+set_documentation_group("component")
+
+
+@document("add")
+class ClearButton(Button):
+ """
+ Button that clears the value of a component or a list of components when clicked. It is instantiated with the list of components to clear.
+ Preprocessing: passes the button value as a {str} into the function
+ Postprocessing: expects a {str} to be returned from a function, which is set as the label of the button
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ components: None | list[Component] | Component = None,
+ *,
+ value: str = "Clear",
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ size: Literal["sm", "lg"] | None = None,
+ icon: str | None = None,
+ link: str | None = None,
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ scale: int | None = None,
+ min_width: int | None = None,
+ api_name: str | None | Literal["False"] = None,
+ show_api: bool = False,
+ ):
+ super().__init__(
+ value,
+ every=every,
+ variant=variant,
+ size=size,
+ icon=icon,
+ link=link,
+ visible=visible,
+ interactive=interactive,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ scale=scale,
+ min_width=min_width,
+ )
+ self.api_name = api_name
+ self.show_api = show_api
+
+ if Context.root_block:
+ self.add(components)
+
+ def add(self, components: None | Component | list[Component]) -> ClearButton:
+ """
+ Adds a component or list of components to the list of components that will be cleared when the button is clicked.
+ """
+ from gradio.components import State # Avoid circular import
+
+ if not components:
+ # This needs to be here because when the ClearButton is created in an gr.Interface, we don't
+ # want to create dependencies for it before we have created the dependencies for the submit function.
+ # We generally assume that the submit function dependency is the first thing created in an gr.Interface.
+ return self
+
+ if isinstance(components, Component):
+ components = [components]
+ none_values = []
+ state_components = []
+ initial_states = []
+ for component in components:
+ if isinstance(component, State):
+ state_components.append(component)
+ initial_states.append(copy.deepcopy(component.value))
+ none = component.postprocess(None)
+ if isinstance(none, (GradioModel, GradioRootModel)):
+ none = none.model_dump()
+ none_values.append(none)
+ clear_values = json.dumps(none_values)
+ self.click(
+ None,
+ [],
+ components,
+ js=f"() => {clear_values}",
+ api_name=self.api_name,
+ show_api=self.show_api,
+ )
+ if state_components:
+ self.click(
+ lambda: resolve_singleton(initial_states),
+ None,
+ state_components,
+ api_name=self.api_name,
+ show_api=self.show_api,
+ )
+ return self
+
+ def postprocess(self, value: str | None) -> str | None:
+ return value
+
+ def preprocess(self, payload: str | None) -> str | None:
+ return payload
+
+ def example_inputs(self) -> Any:
+ return None
diff --git a/gradio/components/code.py b/gradio/components/code.py
new file mode 100644
index 0000000000000000000000000000000000000000..19fae0add448050b9c2c412f9698269eca07f8fb
--- /dev/null
+++ b/gradio/components/code.py
@@ -0,0 +1,132 @@
+"""gr.Code() component"""
+
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document("languages")
+class Code(Component):
+ """
+ Creates a Code editor for entering, editing or viewing code.
+ Preprocessing: passes a {str} of code into the function.
+ Postprocessing: expects the function to return a {str} of code or a single-element {tuple}: {(string_filepath,)}
+ """
+
+ languages = [
+ "python",
+ "markdown",
+ "json",
+ "html",
+ "css",
+ "javascript",
+ "typescript",
+ "yaml",
+ "dockerfile",
+ "shell",
+ "r",
+ None,
+ ]
+
+ EVENTS = [
+ Events.change,
+ Events.input,
+ Events.focus,
+ Events.blur,
+ ]
+
+ def __init__(
+ self,
+ value: str | tuple[str] | None = None,
+ language: Literal[
+ "python",
+ "markdown",
+ "json",
+ "html",
+ "css",
+ "javascript",
+ "typescript",
+ "yaml",
+ "dockerfile",
+ "shell",
+ "r",
+ ]
+ | None = None,
+ *,
+ every: float | None = None,
+ lines: int = 5,
+ label: str | None = None,
+ interactive: bool | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Default value to show in the code editor. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ language: The language to display the code as. Supported languages listed in `gr.Code.languages`.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ interactive: Whether user should be able to enter code or only view it.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ if language not in Code.languages:
+ raise ValueError(f"Language {language} not supported.")
+
+ self.language = language
+ self.lines = lines
+ super().__init__(
+ label=label,
+ every=every,
+ interactive=interactive,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def preprocess(self, payload: Any) -> Any:
+ return payload
+
+ def postprocess(self, value: tuple | str | None) -> None | str:
+ if value is None:
+ return None
+ elif isinstance(value, tuple):
+ with open(value[0]) as file_data:
+ return file_data.read()
+ else:
+ return value.strip()
+
+ def flag(self, payload: Any, flag_dir: str | Path = "") -> str:
+ return super().flag(payload, flag_dir)
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
+
+ def example_inputs(self) -> Any:
+ return "print('Hello World')"
diff --git a/gradio/components/color_picker.py b/gradio/components/color_picker.py
new file mode 100644
index 0000000000000000000000000000000000000000..6575c9d42c0b7ff921edc1c6380b778070ef490f
--- /dev/null
+++ b/gradio/components/color_picker.py
@@ -0,0 +1,92 @@
+"""gr.ColorPicker() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class ColorPicker(Component):
+ """
+ Creates a color picker for user to select a color as string input.
+ Preprocessing: passes selected color value as a {str} into the function.
+ Postprocessing: expects a {str} returned from function and sets color picker value to it.
+ Examples-format: a {str} with a hexadecimal representation of a color, e.g. "#ff0000" for red.
+ Demos: color_picker, color_generator
+ """
+
+ EVENTS = [Events.change, Events.input, Events.submit, Events.focus, Events.blur]
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: default text to provide in color picker. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will be rendered as an editable color picker; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> str:
+ return "#000000"
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
+
+ def preprocess(self, payload: str | None) -> str | None:
+ if payload is None:
+ return None
+ else:
+ return str(payload)
+
+ def postprocess(self, value: str | None) -> str | None:
+ if value is None:
+ return None
+ else:
+ return str(value)
diff --git a/gradio/components/dataframe.py b/gradio/components/dataframe.py
new file mode 100644
index 0000000000000000000000000000000000000000..a69580b8005dd09f6423c649cc8048fdb073de32
--- /dev/null
+++ b/gradio/components/dataframe.py
@@ -0,0 +1,358 @@
+"""gr.Dataframe() component"""
+
+from __future__ import annotations
+
+import warnings
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ Dict,
+ List,
+ Literal,
+ Optional,
+ Tuple,
+ Union,
+)
+
+import numpy as np
+import pandas as pd
+import semantic_version
+from gradio_client.documentation import document, set_documentation_group
+from pandas.io.formats.style import Styler
+
+from gradio.components import Component
+from gradio.data_classes import GradioModel
+from gradio.events import Events
+
+if TYPE_CHECKING:
+ import polars as pl # type: ignore
+
+
+def _is_polars_available():
+ import importlib.util
+
+ spec = importlib.util.find_spec("polars")
+ return bool(spec)
+
+
+def _import_polars():
+ import polars as pl # type: ignore
+
+ return pl
+
+
+class DataframeData(GradioModel):
+ headers: List[str]
+ data: Union[List[List[Any]], List[Tuple[Any, ...]]]
+ metadata: Optional[Dict[str, Optional[List[Any]]]] = None
+
+
+set_documentation_group("component")
+
+
+@document()
+class Dataframe(Component):
+ """
+ Accepts or displays 2D input through a spreadsheet-like component for dataframes.
+ Preprocessing: passes the uploaded spreadsheet data as a {pandas.DataFrame}, {numpy.array}, {polars.DataFrame}, or {List[List]} depending on `type`
+ Postprocessing: expects a {pandas.DataFrame}, {pandas.Styler}, {numpy.array}, {polars.DataFrame}, {List[List]}, {List}, a {Dict} with keys `data` (and optionally `headers`), or {str} path to a csv, which is rendered in the spreadsheet.
+ Examples-format: a {str} filepath to a csv with data, a pandas dataframe, a polars dataframe, or a list of lists (excluding headers) where each sublist is a row of data.
+ Demos: filter_records, matrix_transpose, tax_calculator, sort_records
+ """
+
+ EVENTS = [Events.change, Events.input, Events.select]
+
+ data_model = DataframeData
+
+ def __init__(
+ self,
+ value: pd.DataFrame
+ | Styler
+ | np.ndarray
+ | pl.DataFrame
+ | list
+ | list[list]
+ | dict
+ | str
+ | Callable
+ | None = None,
+ *,
+ headers: list[str] | None = None,
+ row_count: int | tuple[int, str] = (1, "dynamic"),
+ col_count: int | tuple[int, str] | None = None,
+ datatype: str | list[str] = "str",
+ type: Literal["pandas", "numpy", "array", "polars"] = "pandas",
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ every: float | None = None,
+ height: int = 500,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ wrap: bool = False,
+ line_breaks: bool = True,
+ column_widths: list[str | int] | None = None,
+ ):
+ """
+ Parameters:
+ value: Default value to display in the DataFrame. If a Styler is provided, it will be used to set the displayed value in the DataFrame (e.g. to set precision of numbers) if the `interactive` is False. If a Callable function is provided, the function will be called whenever the app loads to set the initial value of the component.
+ headers: List of str header names. If None, no headers are shown.
+ row_count: Limit number of rows for input and decide whether user can create new rows. The first element of the tuple is an `int`, the row count; the second should be 'fixed' or 'dynamic', the new row behaviour. If an `int` is passed the rows default to 'dynamic'
+ col_count: Limit number of columns for input and decide whether user can create new columns. The first element of the tuple is an `int`, the number of columns; the second should be 'fixed' or 'dynamic', the new column behaviour. If an `int` is passed the columns default to 'dynamic'
+ datatype: Datatype of values in sheet. Can be provided per column as a list of strings, or for the entire sheet as a single string. Valid datatypes are "str", "number", "bool", "date", and "markdown".
+ type: Type of value to be returned by component. "pandas" for pandas dataframe, "numpy" for numpy array, "polars" for polars dataframe, or "array" for a Python list of lists.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ latex_delimiters: A list of dicts of the form {"left": open delimiter (str), "right": close delimiter (str), "display": whether to display in newline (bool)} that will be used to render LaTeX expressions. If not provided, `latex_delimiters` is set to `[{ "left": "$$", "right": "$$", "display": True }]`, so only expressions enclosed in $$ delimiters will be rendered as LaTeX, and in a new line. Pass in an empty list to disable LaTeX rendering. For more information, see the [KaTeX documentation](https://katex.org/docs/autorender.html). Only applies to columns whose datatype is "markdown".
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ show_label: if True, will display label.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ height: The maximum height of the dataframe, specified in pixels if a number is passed, or in CSS units if a string is passed. If more rows are created than can fit in the height, a scrollbar will appear.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will allow users to edit the dataframe; if False, can only be used to display data. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ wrap: If True, the text in table cells will wrap when appropriate. If False and the `column_width` parameter is not set, the column widths will expand based on the cell contents and the table may need to be horizontally scrolled. If `column_width` is set, then any overflow text will be hidden.
+ line_breaks: If True (default), will enable Github-flavored Markdown line breaks in chatbot messages. If False, single new lines will be ignored. Only applies for columns of type "markdown."
+ column_widths: An optional list representing the width of each column. The elements of the list should be in the format "100px" (ints are also accepted and converted to pixel values) or "10%". If not provided, the column widths will be automatically determined based on the content of the cells. Setting this parameter will cause the browser to try to fit the table within the page width.
+ """
+ self.wrap = wrap
+ self.row_count = self.__process_counts(row_count)
+ self.col_count = self.__process_counts(
+ col_count, len(headers) if headers else 3
+ )
+
+ self.__validate_headers(headers, self.col_count[0])
+
+ self.headers = (
+ headers
+ if headers is not None
+ else [str(i) for i in (range(1, self.col_count[0] + 1))]
+ )
+ self.datatype = (
+ datatype if isinstance(datatype, list) else [datatype] * self.col_count[0]
+ )
+ valid_types = ["pandas", "numpy", "array", "polars"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ if type == "polars" and not _is_polars_available():
+ raise ImportError(
+ "Polars is not installed. Please install using `pip install polars`."
+ )
+ self.type = type
+ values = {
+ "str": "",
+ "number": 0,
+ "bool": False,
+ "date": "01/01/1970",
+ "markdown": "",
+ "html": "",
+ }
+ column_dtypes = (
+ [datatype] * self.col_count[0] if isinstance(datatype, str) else datatype
+ )
+ self.empty_input = {
+ "headers": self.headers,
+ "data": [
+ [values[c] for c in column_dtypes] for _ in range(self.row_count[0])
+ ],
+ "metadata": None,
+ }
+
+ if latex_delimiters is None:
+ latex_delimiters = [{"left": "$$", "right": "$$", "display": True}]
+ self.latex_delimiters = latex_delimiters
+ self.height = height
+ self.line_breaks = line_breaks
+ self.column_widths = [
+ w if isinstance(w, str) else f"{w}px" for w in (column_widths or [])
+ ]
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def preprocess(
+ self, payload: DataframeData
+ ) -> pd.DataFrame | np.ndarray | pl.DataFrame | list:
+ if self.type == "pandas":
+ if payload.headers is not None:
+ return pd.DataFrame(payload.data, columns=payload.headers)
+ else:
+ return pd.DataFrame(payload.data)
+ if self.type == "polars":
+ polars = _import_polars()
+ if payload.headers is not None:
+ return polars.DataFrame(payload.data, schema=payload.headers)
+ else:
+ return polars.DataFrame(payload.data)
+ if self.type == "numpy":
+ return np.array(payload.data)
+ elif self.type == "array":
+ return payload.data
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'pandas', 'numpy', 'array', 'polars'."
+ )
+
+ def postprocess(
+ self,
+ value: pd.DataFrame
+ | Styler
+ | np.ndarray
+ | pl.DataFrame
+ | list
+ | list[list]
+ | dict
+ | str
+ | None,
+ ) -> DataframeData:
+ if value is None:
+ return self.postprocess(self.empty_input)
+ if isinstance(value, dict):
+ return DataframeData(
+ headers=value.get("headers", []), data=value.get("data", [[]])
+ )
+ if isinstance(value, (str, pd.DataFrame)):
+ if isinstance(value, str):
+ value = pd.read_csv(value) # type: ignore
+ return DataframeData(
+ headers=list(value.columns), # type: ignore
+ data=value.to_dict(orient="split")["data"], # type: ignore
+ )
+ elif isinstance(value, Styler):
+ if semantic_version.Version(pd.__version__) < semantic_version.Version(
+ "1.5.0"
+ ):
+ raise ValueError(
+ "Styler objects are only supported in pandas version 1.5.0 or higher. Please try: `pip install --upgrade pandas` to use this feature."
+ )
+ if self.interactive:
+ warnings.warn(
+ "Cannot display Styler object in interactive mode. Will display as a regular pandas dataframe instead."
+ )
+ df: pd.DataFrame = value.data # type: ignore
+ return DataframeData(
+ headers=list(df.columns),
+ data=df.to_dict(orient="split")["data"], # type: ignore
+ metadata=self.__extract_metadata(value), # type: ignore
+ )
+ elif isinstance(value, (str, pd.DataFrame)):
+ df = pd.read_csv(value) if isinstance(value, str) else value # type: ignore
+ return DataframeData(
+ headers=list(df.columns),
+ data=df.to_dict(orient="split")["data"], # type: ignore
+ )
+ elif _is_polars_available() and isinstance(value, _import_polars().DataFrame):
+ df_dict = value.to_dict()
+ headers = list(df_dict.keys())
+ data = list(zip(*df_dict.values()))
+ return DataframeData(headers=headers, data=data)
+ elif isinstance(value, (np.ndarray, list)):
+ if len(value) == 0:
+ return self.postprocess([[]])
+ if isinstance(value, np.ndarray):
+ value = value.tolist()
+ if not isinstance(value, list):
+ raise ValueError("output cannot be converted to list")
+
+ _headers = self.headers
+ if len(self.headers) < len(value[0]):
+ _headers: list[str] = [
+ *self.headers,
+ *[str(i) for i in range(len(self.headers) + 1, len(value[0]) + 1)],
+ ]
+ elif len(self.headers) > len(value[0]):
+ _headers = self.headers[: len(value[0])]
+
+ return DataframeData(headers=_headers, data=value)
+ else:
+ raise ValueError("Cannot process value as a Dataframe")
+
+ @staticmethod
+ def __get_cell_style(cell_id: str, cell_styles: list[dict]) -> str:
+ styles_for_cell = []
+ for style in cell_styles:
+ if cell_id in style.get("selectors", []):
+ styles_for_cell.extend(style.get("props", []))
+ styles_str = "; ".join([f"{prop}: {value}" for prop, value in styles_for_cell])
+ return styles_str
+
+ @staticmethod
+ def __extract_metadata(df: Styler) -> dict[str, list[list]]:
+ metadata = {"display_value": [], "styling": []}
+ style_data = df._compute()._translate(None, None) # type: ignore
+ cell_styles = style_data.get("cellstyle", [])
+ for i in range(len(style_data["body"])):
+ metadata["display_value"].append([])
+ metadata["styling"].append([])
+ for j in range(len(style_data["body"][i])):
+ cell_type = style_data["body"][i][j]["type"]
+ if cell_type != "td":
+ continue
+ display_value = style_data["body"][i][j]["display_value"]
+ cell_id = style_data["body"][i][j]["id"]
+ styles_str = Dataframe.__get_cell_style(cell_id, cell_styles)
+ metadata["display_value"][i].append(display_value)
+ metadata["styling"][i].append(styles_str)
+ return metadata
+
+ @staticmethod
+ def __process_counts(count, default=3) -> tuple[int, str]:
+ if count is None:
+ return (default, "dynamic")
+ if isinstance(count, (int, float)):
+ return (int(count), "dynamic")
+ else:
+ return count
+
+ @staticmethod
+ def __validate_headers(headers: list[str] | None, col_count: int):
+ if headers is not None and len(headers) != col_count:
+ raise ValueError(
+ f"The length of the headers list must be equal to the col_count int.\n"
+ f"The column count is set to {col_count} but `headers` has {len(headers)} items. "
+ f"Check the values passed to `col_count` and `headers`."
+ )
+
+ def process_example(
+ self,
+ value: pd.DataFrame
+ | Styler
+ | np.ndarray
+ | pl.DataFrame
+ | list
+ | list[list]
+ | dict
+ | str
+ | None,
+ ):
+ if value is None:
+ return ""
+ value_df_data = self.postprocess(value)
+ value_df = pd.DataFrame(value_df_data.data, columns=value_df_data.headers)
+ return value_df.head(n=5).to_dict(orient="split")["data"]
+
+ def example_inputs(self) -> Any:
+ return {"headers": ["a", "b"], "data": [["foo", "bar"]]}
diff --git a/gradio/components/dataset.py b/gradio/components/dataset.py
new file mode 100644
index 0000000000000000000000000000000000000000..e778751c12aed677ed14995903f142cfd639f0c8
--- /dev/null
+++ b/gradio/components/dataset.py
@@ -0,0 +1,143 @@
+"""gr.Dataset() component."""
+
+from __future__ import annotations
+
+from typing import Any, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import processing_utils
+from gradio.components.base import (
+ Component,
+ get_component_instance,
+)
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Dataset(Component):
+ """
+ Used to create an output widget for showing datasets. Used to render the examples
+ box.
+ Preprocessing: passes the selected sample either as a {list} of data (if type="value") or as an {int} index (if type="index")
+ Postprocessing: expects a {list} of {lists} corresponding to the dataset data.
+ """
+
+ EVENTS = [Events.click, Events.select]
+
+ def __init__(
+ self,
+ *,
+ label: str | None = None,
+ components: list[Component] | list[str],
+ samples: list[list[Any]] | None = None,
+ headers: list[str] | None = None,
+ type: Literal["values", "index"] = "values",
+ samples_per_page: int = 10,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ proxy_url: str | None = None,
+ ):
+ """
+ Parameters:
+ components: Which component types to show in this dataset widget, can be passed in as a list of string names or Components instances. The following components are supported in a Dataset: Audio, Checkbox, CheckboxGroup, ColorPicker, Dataframe, Dropdown, File, HTML, Image, Markdown, Model3D, Number, Radio, Slider, Textbox, TimeSeries, Video
+ samples: a nested list of samples. Each sublist within the outer list represents a data sample, and each element within the sublist represents an value for each component
+ headers: Column headers in the Dataset widget, should be the same len as components. If not provided, inferred from component labels
+ type: 'values' if clicking on a sample should pass the value of the sample, or "index" if it should pass the index of the sample
+ samples_per_page: how many examples to show per page.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ proxy_url: The URL of the external Space used to load this component. Set automatically when using `gr.load()`. This should not be set manually.
+ """
+ super().__init__(
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+ self.container = container
+ self.scale = scale
+ self.min_width = min_width
+ self._components = [get_component_instance(c) for c in components]
+ self.component_props = [
+ component.recover_kwargs(
+ component.get_config(),
+ ["value"],
+ )
+ for component in self._components
+ ]
+
+ # Narrow type to Component
+ assert all(
+ isinstance(c, Component) for c in self._components
+ ), "All components in a `Dataset` must be subclasses of `Component`"
+ self._components = [c for c in self._components if isinstance(c, Component)]
+ self.proxy_url = proxy_url
+ for component in self._components:
+ component.proxy_url = proxy_url
+ self.samples = [[]] if samples is None else samples
+ for example in self.samples:
+ for i, (component, ex) in enumerate(zip(self._components, example)):
+ # If proxy_url is set, that means it is being loaded from an external Gradio app
+ # which means that the example has already been processed.
+ if self.proxy_url is None:
+ # The `as_example()` method has been renamed to `process_example()` but we
+ # use the previous name to be backwards-compatible with previously-created
+ # custom components
+ example[i] = component.as_example(ex)
+ example[i] = processing_utils.move_files_to_cache(
+ example[i], component
+ )
+ self.type = type
+ self.label = label
+ if headers is not None:
+ self.headers = headers
+ elif all(c.label is None for c in self._components):
+ self.headers = []
+ else:
+ self.headers = [c.label or "" for c in self._components]
+ self.samples_per_page = samples_per_page
+
+ def api_info(self) -> dict[str, str]:
+ return {"type": "integer", "description": "index of selected example"}
+
+ def get_config(self):
+ config = super().get_config()
+
+ config["components"] = []
+ config["component_props"] = self.component_props
+ config["component_ids"] = []
+
+ for component in self._components:
+ config["components"].append(component.get_block_name())
+
+ config["component_ids"].append(component._id)
+
+ return config
+
+ def preprocess(self, payload: int) -> int | list[list] | None:
+ if self.type == "index":
+ return payload
+ elif self.type == "values":
+ return self.samples[payload]
+
+ def postprocess(self, samples: list[list]) -> dict:
+ return {
+ "samples": samples,
+ "__type__": "update",
+ }
+
+ def example_inputs(self) -> Any:
+ return 0
diff --git a/gradio/components/dropdown.py b/gradio/components/dropdown.py
new file mode 100644
index 0000000000000000000000000000000000000000..cba2e7185289f6d16a3ef32c302d30b3bb003268
--- /dev/null
+++ b/gradio/components/dropdown.py
@@ -0,0 +1,178 @@
+"""gr.Dropdown() component."""
+
+from __future__ import annotations
+
+import warnings
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Dropdown(FormComponent):
+ """
+ Creates a dropdown of choices from which entries can be selected.
+ Preprocessing: passes the value of the selected dropdown entry as a {str} or its index as an {int} into the function, depending on `type`.
+ Postprocessing: expects a {str} corresponding to the value of the dropdown entry to be selected.
+ Examples-format: a {str} representing the drop down value to select.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ EVENTS = [Events.change, Events.input, Events.select, Events.focus, Events.blur]
+
+ def __init__(
+ self,
+ choices: list[str | int | float | tuple[str, str | int | float]] | None = None,
+ *,
+ value: str | int | float | list[str | int | float] | Callable | None = None,
+ type: Literal["value", "index"] = "value",
+ multiselect: bool | None = None,
+ allow_custom_value: bool = False,
+ max_choices: int | None = None,
+ filterable: bool = True,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ choices: A list of string options to choose from. An option can also be a tuple of the form (name, value), where name is the displayed name of the dropdown choice and value is the value to be passed to the function, or returned by the function.
+ value: default value(s) selected in dropdown. If None, no value is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ multiselect: if True, multiple choices can be selected.
+ allow_custom_value: If True, allows user to enter a custom value that is not in the list of choices.
+ max_choices: maximum number of choices that can be selected. If None, no limit is enforced.
+ filterable: If True, user will be able to type into the dropdown and filter the choices by typing. Can only be set to False if `allow_custom_value` is False.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, choices in this dropdown will be selectable; if False, selection will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.choices = (
+ # Although we expect choices to be a list of tuples, it can be a list of tuples if the Gradio app
+ # is loaded with gr.load() since Python tuples are converted to lists in JSON.
+ [tuple(c) if isinstance(c, (tuple, list)) else (str(c), c) for c in choices]
+ if choices
+ else []
+ )
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.multiselect = multiselect
+ if multiselect and isinstance(value, str):
+ value = [value]
+ if not multiselect and max_choices is not None:
+ warnings.warn(
+ "The `max_choices` parameter is ignored when `multiselect` is False."
+ )
+ if not filterable and allow_custom_value:
+ filterable = True
+ warnings.warn(
+ "The `filterable` parameter cannot be set to False when `allow_custom_value` is True. Setting `filterable` to True."
+ )
+ self.max_choices = max_choices
+ self.allow_custom_value = allow_custom_value
+ self.filterable = filterable
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def api_info(self) -> dict[str, Any]:
+ if self.multiselect:
+ json_type = {
+ "type": "array",
+ "items": {"type": "string", "enum": [c[1] for c in self.choices]},
+ }
+ else:
+ json_type = {
+ "type": "string",
+ "enum": [c[1] for c in self.choices],
+ }
+ return json_type
+
+ def example_inputs(self) -> Any:
+ if self.multiselect:
+ return [self.choices[0][1]] if self.choices else []
+ else:
+ return self.choices[0][1] if self.choices else None
+
+ def preprocess(
+ self, payload: str | int | float | list[str | int | float] | None
+ ) -> str | int | float | list[str | int | float] | list[int | None] | None:
+ if self.type == "value":
+ return payload
+ elif self.type == "index":
+ choice_values = [value for _, value in self.choices]
+ if payload is None:
+ return None
+ elif self.multiselect:
+ assert isinstance(payload, list)
+ return [
+ choice_values.index(choice) if choice in choice_values else None
+ for choice in payload
+ ]
+ else:
+ return (
+ choice_values.index(payload) if payload in choice_values else None
+ )
+ else:
+ raise ValueError(
+ f"Unknown type: {self.type}. Please choose from: 'value', 'index'."
+ )
+
+ def _warn_if_invalid_choice(self, value):
+ if self.allow_custom_value or value in [value for _, value in self.choices]:
+ return
+ warnings.warn(
+ f"The value passed into gr.Dropdown() is not in the list of choices. Please update the list of choices to include: {value} or set allow_custom_value=True."
+ )
+
+ def postprocess(
+ self, value: str | int | float | list[str | int | float] | None
+ ) -> str | int | float | list[str | int | float] | None:
+ if value is None:
+ return None
+ if self.multiselect:
+ if not isinstance(value, list):
+ value = [value]
+ [self._warn_if_invalid_choice(_y) for _y in value]
+ else:
+ self._warn_if_invalid_choice(value)
+ return value
diff --git a/gradio/components/duplicate_button.py b/gradio/components/duplicate_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..4012712352bdad49a22aa39c217378e9c6661a39
--- /dev/null
+++ b/gradio/components/duplicate_button.py
@@ -0,0 +1,84 @@
+""" Predefined buttons with bound events that can be included in a gr.Blocks for convenience. """
+
+from __future__ import annotations
+
+from typing import Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components import Button
+from gradio.context import Context
+from gradio.utils import get_space
+
+set_documentation_group("component")
+
+
+@document()
+class DuplicateButton(Button):
+ """
+ Button that triggers a Spaces Duplication, when the demo is on Hugging Face Spaces. Does nothing locally.
+ Preprocessing: passes the button value as a {str} into the function
+ Postprocessing: expects a {str} to be returned from a function, which is set as the label of the button
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str = "Duplicate Space",
+ *,
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ size: Literal["sm", "lg"] | None = "sm",
+ icon: str | None = None,
+ link: str | None = None,
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ scale: int | None = 0,
+ min_width: int | None = None,
+ _activate: bool = True,
+ ):
+ """
+ Parameters:
+ value: Default text for the button to display. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ variant: 'primary' for main call-to-action, 'secondary' for a more subdued style, 'stop' for a stop button.
+ size: Size of the button. Can be "sm" or "lg".
+ icon: URL or path to the icon file to display within the button. If None, no icon will be displayed.
+ link: URL to open when the button is clicked. If None, no link will be used.
+ visible: If False, component will be hidden.
+ interactive: If False, the Button will be in a disabled state.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ """
+ super().__init__(
+ value=value,
+ every=every,
+ variant=variant,
+ size=size,
+ icon=icon,
+ link=link,
+ visible=visible,
+ interactive=interactive,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ scale=scale,
+ min_width=min_width,
+ )
+ if _activate and Context.root_block:
+ self.activate()
+
+ def activate(self):
+ space_name = get_space()
+ if space_name is not None:
+ self.click(
+ fn=None,
+ js=f"() => {{ window.open(`https://huggingface.co/spaces/{space_name}?duplicate=true`, '_blank') }}",
+ )
diff --git a/gradio/components/fallback.py b/gradio/components/fallback.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c9b98a6315fda62b1ea4efa84da2cfb6d86fdf4
--- /dev/null
+++ b/gradio/components/fallback.py
@@ -0,0 +1,15 @@
+from gradio.components.base import Component
+
+
+class Fallback(Component):
+ def preprocess(self, payload):
+ return payload
+
+ def postprocess(self, value):
+ return value
+
+ def example_inputs(self):
+ return {"foo": "bar"}
+
+ def api_info(self):
+ return {"type": {}, "description": "any valid json"}
diff --git a/gradio/components/file.py b/gradio/components/file.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb0b35cd5a281a9f9d1920d8f17998b39c25e305
--- /dev/null
+++ b/gradio/components/file.py
@@ -0,0 +1,177 @@
+"""gr.File() component"""
+
+from __future__ import annotations
+
+import tempfile
+import warnings
+from pathlib import Path
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.data_classes import FileData, ListFiles
+from gradio.events import Events
+from gradio.utils import NamedString
+
+set_documentation_group("component")
+
+
+@document()
+class File(Component):
+ """
+ Creates a file component that allows uploading generic file (when used as an input) and or displaying generic files (output).
+ Preprocessing: passes the uploaded file as a {tempfile._TemporaryFileWrapper} or {List[tempfile._TemporaryFileWrapper]} depending on `file_count` (or a {bytes}/{List[bytes]} depending on `type`)
+ Postprocessing: expects function to return a {str} path to a file, or {List[str]} consisting of paths to files.
+ Examples-format: a {str} path to a local file that populates the component.
+ Demos: zip_to_json, zip_files
+ """
+
+ EVENTS = [Events.change, Events.select, Events.clear, Events.upload]
+
+ def __init__(
+ self,
+ value: str | list[str] | Callable | None = None,
+ *,
+ file_count: Literal["single", "multiple", "directory"] = "single",
+ file_types: list[str] | None = None,
+ type: Literal["filepath", "binary"] = "filepath",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ height: int | float | None = None,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Default file to display, given as str file path. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
+ file_types: List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
+ type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ height: The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.
+ interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.file_count = file_count
+ if self.file_count in ["multiple", "directory"]:
+ self.data_model = ListFiles
+ else:
+ self.data_model = FileData
+ self.file_types = file_types
+ if file_types is not None and not isinstance(file_types, list):
+ raise ValueError(
+ f"Parameter file_types must be a list. Received {file_types.__class__.__name__}"
+ )
+ valid_types = [
+ "filepath",
+ "binary",
+ ]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ if file_count == "directory" and file_types is not None:
+ warnings.warn(
+ "The `file_types` parameter is ignored when `file_count` is 'directory'."
+ )
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+ self.type = type
+ self.height = height
+
+ def _process_single_file(self, f: FileData) -> NamedString | bytes:
+ file_name = f.path
+ if self.type == "filepath":
+ file = tempfile.NamedTemporaryFile(delete=False, dir=self.GRADIO_CACHE)
+ file.name = file_name
+ return NamedString(file_name)
+ elif self.type == "binary":
+ with open(file_name, "rb") as file_data:
+ return file_data.read()
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(type)
+ + ". Please choose from: 'filepath', 'binary'."
+ )
+
+ def preprocess(
+ self, payload: ListFiles | FileData | None
+ ) -> bytes | NamedString | list[bytes | NamedString] | None:
+ if payload is None:
+ return None
+ if self.file_count == "single":
+ if isinstance(payload, ListFiles):
+ return self._process_single_file(payload[0])
+ else:
+ return self._process_single_file(payload)
+ else:
+ if isinstance(payload, ListFiles):
+ return [self._process_single_file(f) for f in payload]
+ else:
+ return [self._process_single_file(payload)]
+
+ def postprocess(self, value: str | list[str] | None) -> ListFiles | FileData | None:
+ if value is None:
+ return None
+ if isinstance(value, list):
+ return ListFiles(
+ root=[
+ FileData(
+ path=file,
+ orig_name=Path(file).name,
+ size=Path(file).stat().st_size,
+ )
+ for file in value
+ ]
+ )
+ else:
+ return FileData(
+ path=value,
+ orig_name=Path(value).name,
+ size=Path(value).stat().st_size,
+ )
+
+ def process_example(self, input_data: str | list | None) -> str:
+ if input_data is None:
+ return ""
+ elif isinstance(input_data, list):
+ return ", ".join([Path(file).name for file in input_data])
+ else:
+ return Path(input_data).name
+
+ def example_inputs(self) -> Any:
+ if self.file_count == "single":
+ return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
+ else:
+ return [
+ "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
+ ]
diff --git a/gradio/components/file_explorer.py b/gradio/components/file_explorer.py
new file mode 100644
index 0000000000000000000000000000000000000000..302ae7e1eeb9373d9f902ac88bf8f42b83acef25
--- /dev/null
+++ b/gradio/components/file_explorer.py
@@ -0,0 +1,232 @@
+"""gr.FileExplorer() component"""
+
+from __future__ import annotations
+
+import itertools
+import os
+import re
+import warnings
+from pathlib import Path
+from typing import Any, Callable, List, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component, server
+from gradio.data_classes import GradioRootModel
+
+set_documentation_group("component")
+
+
+class FileExplorerData(GradioRootModel):
+ root: List[List[str]]
+
+
+@document()
+class FileExplorer(Component):
+ """
+ Creates a file explorer component that allows users to browse and select files on the machine hosting the Gradio app.
+ Preprocessing: passes the selected file or directory as a {str} path (relative to root) or {list[str}} depending on `file_count`
+ Postprocessing: expects function to return a {str} path to a file, or {List[str]} consisting of paths to files.
+ Examples-format: a {str} path to a local file that populates the component.
+ Demos: zip_to_json, zip_files
+ """
+
+ EVENTS = ["change"]
+ data_model = FileExplorerData
+
+ def __init__(
+ self,
+ glob: str = "**/*.*",
+ *,
+ value: str | list[str] | Callable | None = None,
+ file_count: Literal["single", "multiple"] = "multiple",
+ root_dir: str | Path = ".",
+ ignore_glob: str | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ height: int | float | None = None,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ root: None = None,
+ ):
+ """
+ Parameters:
+ glob: The glob-style pattern used to select which files to display, e.g. "*" to match all files, "*.png" to match all .png files, "**/*.txt" to match any .txt file in any subdirectory, etc. The default value matches all files and folders recursively. See the Python glob documentation at https://docs.python.org/3/library/glob.html for more information.
+ value: The file (or list of files, depending on the `file_count` parameter) to show as "selected" when the component is first loaded. If a callable is provided, it will be called when the app loads to set the initial value of the component. If not provided, no files are shown as selected.
+ file_count: Whether to allow single or multiple files to be selected. If "single", the component will return a single absolute file path as a string. If "multiple", the component will return a list of absolute file paths as a list of strings.
+ root_dir: Path to root directory to select files from. If not provided, defaults to current working directory.
+ ignore_glob: The glob-tyle pattern that will be used to exclude files from the list. For example, "*.py" will exclude all .py files from the list. See the Python glob documentation at https://docs.python.org/3/library/glob.html for more information.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ height: The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.
+ interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ if root is not None:
+ warnings.warn(
+ "The `root` parameter has been deprecated. Please use `root_dir` instead."
+ )
+ root_dir = root
+ self._constructor_args[0]["root_dir"] = root
+ self.root_dir = os.path.abspath(root_dir)
+ self.glob = glob
+ self.ignore_glob = ignore_glob
+ valid_file_count = ["single", "multiple", "directory"]
+ if file_count not in valid_file_count:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_file_count}"
+ )
+ self.file_count = file_count
+ self.height = height
+
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> Any:
+ return ["Users", "gradio", "app.py"]
+
+ def preprocess(self, payload: FileExplorerData | None) -> list[str] | str | None:
+ if payload is None:
+ return None
+
+ if self.file_count == "single":
+ if len(payload.root) > 1:
+ raise ValueError(
+ f"Expected only one file, but {len(payload.root)} were selected."
+ )
+ elif len(payload.root) == 0:
+ return None
+ else:
+ return self._safe_join(payload.root[0])
+ files = []
+ for file in payload.root:
+ file_ = self._safe_join(file)
+ files.append(file_)
+ return files
+
+ def _strip_root(self, path):
+ if path.startswith(self.root_dir):
+ return path[len(self.root_dir) + 1 :]
+ return path
+
+ def postprocess(self, value: str | list[str] | None) -> FileExplorerData | None:
+ if value is None:
+ return None
+
+ files = [value] if isinstance(value, str) else value
+ root = []
+ for file in files:
+ root.append(self._strip_root(file).split(os.path.sep))
+
+ return FileExplorerData(root=root)
+
+ @server
+ def ls(self, _=None) -> list[dict[str, str]] | None:
+ """
+ Returns:
+ tuple of list of files in directory, then list of folders in directory
+ """
+
+ def expand_braces(text, seen=None):
+ if seen is None:
+ seen = set()
+
+ spans = [m.span() for m in re.finditer("{[^{}]*}", text)][::-1]
+ alts = [text[start + 1 : stop - 1].split(",") for start, stop in spans]
+
+ if len(spans) == 0:
+ if text not in seen:
+ yield text
+ seen.add(text)
+
+ else:
+ for combo in itertools.product(*alts):
+ replaced = list(text)
+ for (start, stop), replacement in zip(spans, combo):
+ replaced[start:stop] = replacement
+
+ yield from expand_braces("".join(replaced), seen)
+
+ def make_tree(files):
+ tree = []
+ for file in files:
+ parts = file.split(os.path.sep)
+ make_node(parts, tree)
+ return tree
+
+ def make_node(parts, tree):
+ _tree = tree
+ for i in range(len(parts)):
+ if _tree is None:
+ continue
+ if i == len(parts) - 1:
+ type = "file"
+ _tree.append({"path": parts[i], "type": type, "children": None})
+ continue
+ type = "folder"
+ j = next(
+ (index for (index, v) in enumerate(_tree) if v["path"] == parts[i]),
+ None,
+ )
+ if j is not None:
+ _tree = _tree[j]["children"]
+ else:
+ _tree.append({"path": parts[i], "type": type, "children": []})
+ _tree = _tree[-1]["children"]
+
+ files: list[Path] = []
+ for result in expand_braces(self.glob):
+ files += list(Path(self.root_dir).resolve().glob(result))
+
+ files = [f for f in files if f != Path(self.root_dir).resolve()]
+
+ ignore_files = []
+ if self.ignore_glob:
+ for result in expand_braces(self.ignore_glob):
+ ignore_files += list(Path(self.root_dir).resolve().glob(result))
+ files = list(set(files) - set(ignore_files))
+
+ files_with_sep = []
+ for f in files:
+ file = str(f.relative_to(self.root_dir))
+ if f.is_dir():
+ file += os.path.sep
+ files_with_sep.append(file)
+
+ tree = make_tree(files_with_sep)
+ return tree
+
+ def _safe_join(self, folders):
+ combined_path = os.path.join(self.root_dir, *folders)
+ absolute_path = os.path.abspath(combined_path)
+ if os.path.commonprefix([self.root_dir, absolute_path]) != os.path.abspath(
+ self.root_dir
+ ):
+ raise ValueError("Attempted to navigate outside of root directory")
+ return absolute_path
diff --git a/gradio/components/gallery.py b/gradio/components/gallery.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0a43f7551f93173cb5dc99dc99f1c35cf59649e
--- /dev/null
+++ b/gradio/components/gallery.py
@@ -0,0 +1,215 @@
+"""gr.Gallery() component."""
+
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any, Callable, List, Literal, Optional, Tuple, Union
+from urllib.parse import urlparse
+
+import numpy as np
+from gradio_client.documentation import document, set_documentation_group
+from gradio_client.utils import is_http_url_like
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+from gradio import processing_utils, utils
+from gradio.components.base import Component
+from gradio.data_classes import FileData, GradioModel, GradioRootModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+GalleryImageType = Union[np.ndarray, _Image.Image, Path, str]
+CaptionedGalleryImageType = Tuple[GalleryImageType, str]
+
+
+class GalleryImage(GradioModel):
+ image: FileData
+ caption: Optional[str] = None
+
+
+class GalleryData(GradioRootModel):
+ root: List[GalleryImage]
+
+
+@document()
+class Gallery(Component):
+ """
+ Used to display a list of images as a gallery that can be scrolled through.
+ Preprocessing: A list of (image, caption) tuples. Each image is a filepath, numpy array or PIL.image depending on the `type` parameter. {List[tuple[str | PIL.Image | numpy.array, str | None]]}.
+ Postprocessing: expects a list of images in any format, {List[numpy.array | PIL.Image | str | pathlib.Path]}, or a {List} of (image, {str} caption) tuples and displays them.
+
+ Demos: fake_gan
+ """
+
+ EVENTS = [Events.select, Events.upload, Events.change]
+
+ data_model = GalleryData
+
+ def __init__(
+ self,
+ value: list[np.ndarray | _Image.Image | str | Path | tuple]
+ | Callable
+ | None = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ columns: int | tuple | None = 2,
+ rows: int | tuple | None = None,
+ height: int | float | None = None,
+ allow_preview: bool = True,
+ preview: bool | None = None,
+ selected_index: int | None = None,
+ object_fit: Literal["contain", "cover", "fill", "none", "scale-down"]
+ | None = None,
+ show_share_button: bool | None = None,
+ show_download_button: bool | None = True,
+ interactive: bool | None = None,
+ type: Literal["numpy", "pil", "filepath"] = "filepath",
+ ):
+ """
+ Parameters:
+ value: List of images to display in the gallery by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ columns: Represents the number of images that should be shown in one row, for each of the six standard screen sizes (<576px, <768px, <992px, <1200px, <1400px, >1400px). If fewer than 6 are given then the last will be used for all subsequent breakpoints
+ rows: Represents the number of rows in the image grid, for each of the six standard screen sizes (<576px, <768px, <992px, <1200px, <1400px, >1400px). If fewer than 6 are given then the last will be used for all subsequent breakpoints
+ height: The height of the gallery component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more images are displayed than can fit in the height, a scrollbar will appear.
+ allow_preview: If True, images in the gallery will be enlarged when they are clicked. Default is True.
+ preview: If True, Gallery will start in preview mode, which shows all of the images as thumbnails and allows the user to click on them to view them in full size. Only works if allow_preview is True.
+ selected_index: The index of the image that should be initially selected. If None, no image will be selected at start. If provided, will set Gallery to preview mode unless allow_preview is set to False.
+ object_fit: CSS object-fit property for the thumbnail images in the gallery. Can be "contain", "cover", "fill", "none", or "scale-down".
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ show_download_button: If True, will show a download button in the corner of the selected image. If False, the icon does not appear. Default is True.
+ interactive: If True, the gallery will be interactive, allowing the user to upload images. If False, the gallery will be static. Default is True.
+ type: The format the image is converted to before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (height, width, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image. If the image is SVG, the `type` is ignored and the filepath of the SVG is returned.
+ """
+ self.columns = columns
+ self.rows = rows
+ self.height = height
+ self.preview = preview
+ self.object_fit = object_fit
+ self.allow_preview = allow_preview
+ self.show_download_button = (
+ (utils.get_space() is not None)
+ if show_download_button is None
+ else show_download_button
+ )
+ self.selected_index = selected_index
+ self.type = type
+
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ interactive=interactive,
+ )
+
+ def postprocess(
+ self,
+ value: list[GalleryImageType | CaptionedGalleryImageType] | None,
+ ) -> GalleryData:
+ """
+ Parameters:
+ value: list of images, or list of (image, caption) tuples
+ Returns:
+ list of string file paths to images in temp directory
+ """
+ if value is None:
+ return GalleryData(root=[])
+ output = []
+ for img in value:
+ url = None
+ caption = None
+ orig_name = None
+ if isinstance(img, (tuple, list)):
+ img, caption = img
+ if isinstance(img, np.ndarray):
+ file = processing_utils.save_img_array_to_cache(
+ img, cache_dir=self.GRADIO_CACHE
+ )
+ file_path = str(utils.abspath(file))
+ elif isinstance(img, _Image.Image):
+ file = processing_utils.save_pil_to_cache(
+ img, cache_dir=self.GRADIO_CACHE
+ )
+ file_path = str(utils.abspath(file))
+ elif isinstance(img, str):
+ file_path = img
+ if is_http_url_like(img):
+ url = img
+ orig_name = Path(urlparse(img).path).name
+ else:
+ url = None
+ orig_name = Path(img).name
+ elif isinstance(img, Path):
+ file_path = str(img)
+ orig_name = img.name
+ else:
+ raise ValueError(f"Cannot process type as image: {type(img)}")
+ entry = GalleryImage(
+ image=FileData(path=file_path, url=url, orig_name=orig_name),
+ caption=caption,
+ )
+ output.append(entry)
+ return GalleryData(root=output)
+
+ @staticmethod
+ def convert_to_type(img: str, type: Literal["filepath", "numpy", "pil"]):
+ if type == "filepath":
+ return img
+ else:
+ converted_image = _Image.open(img)
+ if type == "numpy":
+ converted_image = np.array(converted_image)
+ return converted_image
+
+ def preprocess(
+ self, payload: GalleryData | None
+ ) -> (
+ List[tuple[str, str | None]]
+ | List[tuple[_Image.Image, str | None]]
+ | List[tuple[np.ndarray, str | None]]
+ | None
+ ):
+ if payload is None or not payload.root:
+ return None
+ data = []
+ for gallery_element in payload.root:
+ image = self.convert_to_type(gallery_element.image.path, self.type) # type: ignore
+ data.append((image, gallery_element.caption))
+ return data
+
+ def example_inputs(self) -> Any:
+ return [
+ "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"
+ ]
diff --git a/gradio/components/highlighted_text.py b/gradio/components/highlighted_text.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac0c7d96ac58339719e547c208a2cc75f3cd054d
--- /dev/null
+++ b/gradio/components/highlighted_text.py
@@ -0,0 +1,172 @@
+"""gr.HighlightedText() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, List, Union
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.data_classes import GradioModel, GradioRootModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+class HighlightedToken(GradioModel):
+ token: str
+ class_or_confidence: Union[str, float, None] = None
+
+
+class HighlightedTextData(GradioRootModel):
+ root: List[HighlightedToken]
+
+
+@document()
+class HighlightedText(Component):
+ """
+ Displays text that contains spans that are highlighted by category or numerical value.
+ Preprocessing: passes a list of tuples as a {List[Tuple[str, float | str | None]]]} into the function. If no labels are provided, the text will be displayed as a single span.
+ Postprocessing: expects a {List[Tuple[str, float | str]]]} consisting of spans of text and their associated labels, or a {Dict} with two keys: (1) "text" whose value is the complete text, and (2) "entities", which is a list of dictionaries, each of which have the keys: "entity" (consisting of the entity label, can alternatively be called "entity_group"), "start" (the character index where the label starts), and "end" (the character index where the label ends). Entities should not overlap.
+
+ Demos: diff_texts, text_analysis
+ Guides: named-entity-recognition
+ """
+
+ data_model = HighlightedTextData
+ EVENTS = [Events.change, Events.select]
+
+ def __init__(
+ self,
+ value: list[tuple[str, str | float | None]] | dict | Callable | None = None,
+ *,
+ color_map: dict[str, str]
+ | None = None, # Parameter moved to HighlightedText.style()
+ show_legend: bool = False,
+ combine_adjacent: bool = False,
+ adjacent_separator: str = "",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ interactive: bool | None = None,
+ ):
+ """
+ Parameters:
+ value: Default value to show. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ color_map: A dictionary mapping labels to colors. The colors may be specified as hex codes or by their names. For example: {"person": "red", "location": "#FFEE22"}
+ show_legend: whether to show span categories in a separate legend or inline.
+ combine_adjacent: If True, will merge the labels of adjacent tokens belonging to the same category.
+ adjacent_separator: Specifies the separator to be used between tokens if combine_adjacent is True.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ interactive: If True, the component will be editable, and allow user to select spans of text and label them.
+ """
+ self.color_map = color_map
+ self.show_legend = show_legend
+ self.combine_adjacent = combine_adjacent
+ self.adjacent_separator = adjacent_separator
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ interactive=interactive,
+ )
+
+ def example_inputs(self) -> Any:
+ return {"value": [{"token": "Hello", "class_or_confidence": "1"}]}
+
+ def postprocess(
+ self, value: list[tuple[str, str | float | None]] | dict | None
+ ) -> HighlightedTextData | None:
+ """
+ Parameters:
+ value: List of (word, category) tuples, or a dictionary of two keys: "text", and "entities", which itself is a list of dictionaries, each of which have the keys: "entity" (or "entity_group"), "start", and "end"
+ Returns:
+ List of (word, category) tuples
+ """
+ if value is None:
+ return None
+ if isinstance(value, dict):
+ try:
+ text = value["text"]
+ entities = value["entities"]
+ except KeyError as ke:
+ raise ValueError(
+ "Expected a dictionary with keys 'text' and 'entities' "
+ "for the value of the HighlightedText component."
+ ) from ke
+ if len(entities) == 0:
+ value = [(text, None)]
+ else:
+ list_format = []
+ index = 0
+ entities = sorted(entities, key=lambda x: x["start"])
+ for entity in entities:
+ list_format.append((text[index : entity["start"]], None))
+ entity_category = entity.get("entity") or entity.get("entity_group")
+ list_format.append(
+ (text[entity["start"] : entity["end"]], entity_category)
+ )
+ index = entity["end"]
+ list_format.append((text[index:], None))
+ value = list_format
+ if self.combine_adjacent:
+ output = []
+ running_text, running_category = None, None
+ for text, category in value:
+ if running_text is None:
+ running_text = text
+ running_category = category
+ elif category == running_category:
+ running_text += self.adjacent_separator + text
+ elif not text:
+ # Skip fully empty item, these get added in processing
+ # of dictionaries.
+ pass
+ else:
+ output.append((running_text, running_category))
+ running_text = text
+ running_category = category
+ if running_text is not None:
+ output.append((running_text, running_category))
+ return HighlightedTextData(
+ root=[
+ HighlightedToken(token=o[0], class_or_confidence=o[1])
+ for o in output
+ ]
+ )
+ else:
+ return HighlightedTextData(
+ root=[
+ HighlightedToken(token=o[0], class_or_confidence=o[1])
+ for o in value
+ ]
+ )
+
+ def preprocess(self, payload: HighlightedTextData | None) -> dict | None:
+ if payload is None:
+ return None
+ return payload.model_dump()
diff --git a/gradio/components/html.py b/gradio/components/html.py
new file mode 100644
index 0000000000000000000000000000000000000000..8534446a2d12c877b4552b493285b8ee858bce44
--- /dev/null
+++ b/gradio/components/html.py
@@ -0,0 +1,72 @@
+"""gr.HTML() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class HTML(Component):
+ """
+ Used to display arbitrary HTML output.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a valid HTML {str}.
+
+ Demos: text_analysis
+ Guides: key-features
+ """
+
+ EVENTS = [Events.change]
+
+ def __init__(
+ self,
+ value: str | Callable = "",
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Is used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: This parameter has no effect.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> Any:
+ return "Hello
"
+
+ def preprocess(self, payload: str | None) -> str | None:
+ return payload
+
+ def postprocess(self, value: str | None) -> str | None:
+ return value
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
diff --git a/gradio/components/image.py b/gradio/components/image.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd03991ac19701c64f93efe9fddbe3391c7e3421
--- /dev/null
+++ b/gradio/components/image.py
@@ -0,0 +1,204 @@
+"""gr.Image() component."""
+
+from __future__ import annotations
+
+import warnings
+from pathlib import Path
+from typing import Any, Literal, cast
+
+import numpy as np
+from gradio_client.documentation import document, set_documentation_group
+from PIL import Image as _Image # using _ to minimize namespace pollution
+from PIL import ImageOps
+
+import gradio.image_utils as image_utils
+from gradio import utils
+from gradio.components.base import Component, StreamingInput
+from gradio.data_classes import FileData
+from gradio.events import Events
+
+set_documentation_group("component")
+_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
+
+
+@document()
+class Image(StreamingInput, Component):
+ """
+ Creates an image component that can be used to upload images (as an input) or display images (as an output).
+ Preprocessing: passes the uploaded image as a {numpy.array}, {PIL.Image} or {str} filepath depending on `type`. For SVGs, the `type` parameter is ignored and the filepath of the SVG is returned.
+ Postprocessing: expects a {numpy.array}, {PIL.Image} or {str} or {pathlib.Path} filepath to an image and displays the image.
+ Examples-format: a {str} local filepath or URL to an image.
+ Demos: image_mod, image_mod_default_image
+ Guides: image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers, create-your-own-friends-with-a-gan
+ """
+
+ EVENTS = [
+ Events.clear,
+ Events.change,
+ Events.stream,
+ Events.select,
+ Events.upload,
+ ]
+
+ data_model = FileData
+
+ def __init__(
+ self,
+ value: str | _Image.Image | np.ndarray | None = None,
+ *,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ image_mode: Literal[
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
+ ] = "RGB",
+ sources: list[Literal["upload", "webcam", "clipboard"]] | None = None,
+ type: Literal["numpy", "pil", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ show_download_button: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ streaming: bool = False,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ show_share_button: bool | None = None,
+ ):
+ """
+ Parameters:
+ value: A PIL Image, numpy array, path or URL for the default value that Image component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ height: The height of the displayed image, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the displayed image, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ image_mode: "RGB" if color, or "L" if black and white. See https://pillow.readthedocs.io/en/stable/handbook/concepts.html for other supported image modes and their meaning.
+ sources: List of sources for the image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "clipboard" allows users to paste an image from the clipboard. If None, defaults to ["upload", "webcam", "clipboard"] if streaming is False, otherwise defaults to ["webcam"].
+ type: The format the image is converted before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (height, width, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image. If the image is SVG, the `type` is ignored and the filepath of the SVG is returned.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ show_download_button: If True, will display button to download image.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will allow users to upload and edit an image; if False, can only be used to display images. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ streaming: If True when used in a `live` interface, will automatically stream webcam feed. Only valid is source is 'webcam'.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ mirror_webcam: If True webcam will be mirrored. Default is True.
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ """
+ self.mirror_webcam = mirror_webcam
+ valid_types = ["numpy", "pil", "filepath"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.height = height
+ self.width = width
+ self.image_mode = image_mode
+ valid_sources = ["upload", "webcam", "clipboard"]
+ if sources is None:
+ self.sources = (
+ ["webcam"] if streaming else ["upload", "webcam", "clipboard"]
+ )
+ elif isinstance(sources, str):
+ self.sources = [sources] # type: ignore
+ else:
+ self.sources = sources
+ for source in self.sources: # type: ignore
+ if source not in valid_sources:
+ raise ValueError(
+ f"`sources` must a list consisting of elements in {valid_sources}"
+ )
+ self.streaming = streaming
+ self.show_download_button = show_download_button
+ if streaming and self.sources != ["webcam"]:
+ raise ValueError(
+ "Image streaming only available if sources is ['webcam']. Streaming not supported with multiple sources."
+ )
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def preprocess(
+ self, payload: FileData | None
+ ) -> np.ndarray | _Image.Image | str | None:
+ if payload is None:
+ return payload
+ file_path = Path(payload.path)
+ if payload.orig_name:
+ p = Path(payload.orig_name)
+ name = p.stem
+ suffix = p.suffix.replace(".", "")
+ if suffix in ["jpg", "jpeg"]:
+ suffix = "jpeg"
+ else:
+ name = "image"
+ suffix = "png"
+
+ if suffix.lower() == "svg":
+ return str(file_path)
+
+ im = _Image.open(file_path)
+ exif = im.getexif()
+ # 274 is the code for image rotation and 1 means "correct orientation"
+ if exif.get(274, 1) != 1 and hasattr(ImageOps, "exif_transpose"):
+ try:
+ im = ImageOps.exif_transpose(im)
+ except Exception:
+ warnings.warn(
+ f"Failed to transpose image {file_path} based on EXIF data."
+ )
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ im = im.convert(self.image_mode)
+ return image_utils.format_image(
+ im,
+ cast(Literal["numpy", "pil", "filepath"], self.type),
+ self.GRADIO_CACHE,
+ name=name,
+ format=suffix,
+ )
+
+ def postprocess(
+ self, value: np.ndarray | _Image.Image | str | Path | None
+ ) -> FileData | None:
+ if value is None:
+ return None
+ if isinstance(value, str) and value.lower().endswith(".svg"):
+ return FileData(path=value, orig_name=Path(value).name)
+ saved = image_utils.save_image(value, self.GRADIO_CACHE)
+ orig_name = Path(saved).name if Path(saved).exists() else None
+ return FileData(path=saved, orig_name=orig_name)
+
+ def check_streamable(self):
+ if self.streaming and self.sources != ["webcam"]:
+ raise ValueError(
+ "Image streaming only available if sources is ['webcam']. Streaming not supported with multiple sources."
+ )
+
+ def example_inputs(self) -> Any:
+ return "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"
diff --git a/gradio/components/image_editor.py b/gradio/components/image_editor.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3bfe63965155ea3f727a4cc7ee0aafd7ba91af9
--- /dev/null
+++ b/gradio/components/image_editor.py
@@ -0,0 +1,317 @@
+r"""gr.ImageEditor() component."""
+
+from __future__ import annotations
+
+import dataclasses
+import warnings
+from pathlib import Path
+from typing import Any, Iterable, List, Literal, Optional, TypedDict, Union, cast
+
+import numpy as np
+from gradio_client.documentation import document, set_documentation_group
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+import gradio.image_utils as image_utils
+from gradio import utils
+from gradio.components.base import Component
+from gradio.data_classes import FileData, GradioModel
+from gradio.events import Events
+
+set_documentation_group("component")
+_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
+
+
+ImageType = Union[np.ndarray, _Image.Image, str]
+
+
+class EditorValue(TypedDict):
+ background: Optional[ImageType]
+ layers: list[ImageType]
+ composite: Optional[ImageType]
+
+
+class EditorExampleValue(TypedDict):
+ background: Optional[str]
+ layers: Optional[list[str | None]]
+ composite: Optional[str]
+
+
+class EditorData(GradioModel):
+ background: Optional[FileData] = None
+ layers: List[FileData] = []
+ composite: Optional[FileData] = None
+
+
+@dataclasses.dataclass
+class Eraser:
+ """
+ A dataclass for specifying options for the eraser tool in the ImageEditor component. An instance of this class can be passed to the `eraser` parameter of `gr.ImageEditor`.
+ Parameters:
+ default_size: The default radius, in pixels, of the eraser tool. Defaults to "auto" in which case the radius is automatically determined based on the size of the image (generally 1/50th of smaller dimension).
+ """
+
+ default_size: int | Literal["auto"] = "auto"
+
+
+@dataclasses.dataclass
+class Brush(Eraser):
+ """
+ A dataclass for specifying options for the brush tool in the ImageEditor component. An instance of this class can be passed to the `brush` parameter of `gr.ImageEditor`.
+ Parameters:
+ default_size: The default radius, in pixels, of the brush tool. Defaults to "auto" in which case the radius is automatically determined based on the size of the image (generally 1/50th of smaller dimension).
+ colors: A list of colors to make available to the user when using the brush. Defaults to a list of 5 colors.
+ default_color: The default color of the brush. Defaults to the first color in the `colors` list.
+ color_mode: If set to "fixed", user can only select from among the colors in `colors`. If "defaults", the colors in `colors` are provided as a default palette, but the user can also select any color using a color picker.
+ """
+
+ colors: Union[
+ list[str],
+ str,
+ None,
+ ] = None
+ default_color: Union[str, Literal["auto"]] = "auto"
+ color_mode: Literal["fixed", "defaults"] = "defaults"
+
+ def __post_init__(self):
+ if self.colors is None:
+ self.colors = [
+ "rgb(204, 50, 50)",
+ "rgb(173, 204, 50)",
+ "rgb(50, 204, 112)",
+ "rgb(50, 112, 204)",
+ "rgb(173, 50, 204)",
+ ]
+ if self.default_color is None:
+ self.default_color = (
+ self.colors[0] if isinstance(self.colors, list) else self.colors
+ )
+
+
+@document()
+class ImageEditor(Component):
+ """
+ Creates an image component that can be used to upload and edit images (as an input) or display images (as an output).
+ Preprocessing: passes the uploaded images as a dictionary with keys: `background`, `layers`, and `composite`. The values corresponding to `background` and `composite` are images, while `layers` is a list of images. The images are of type PIL.Image, np.array, or str filepath, depending on the `type` parameter.
+ Postprocessing: expects a dictionary with keys: `background`, `layers`, and `composite`. The values corresponding to `background` and `composite` should be images or None, while `layers` should be a list of images. Images can be of type PIL.Image, np.array, or str filepath/URL. Or, the value can be simply a single image, in which case it will be used as the background.
+ Examples-format: a dictionary with keys: `background`, `layers`, and `composite`. The values corresponding to `background` and `composite` should be strings or None, while `layers` should be a list of strings. The image corresponding to `composite`, if not None, is used as the example image. Otherwise, the image corresonding to `background` is used. The strings should be filepaths or URLs. Or, the value can be simply a single string filepath/URL to an image, which is used directly as the example image.
+ Demos: image_editor
+ """
+
+ EVENTS = [
+ Events.clear,
+ Events.change,
+ Events.select,
+ Events.upload,
+ ]
+ data_model = EditorData
+
+ def __init__(
+ self,
+ value: EditorValue | ImageType | None = None,
+ *,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ image_mode: Literal[
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
+ ] = "RGBA",
+ sources: Iterable[Literal["upload", "webcam", "clipboard"]] = (
+ "upload",
+ "webcam",
+ "clipboard",
+ ),
+ type: Literal["numpy", "pil", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ show_download_button: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ show_share_button: bool | None = None,
+ _selectable: bool = False,
+ crop_size: tuple[int | float, int | float] | str | None = None,
+ transforms: Iterable[Literal["crop"]] = ("crop",),
+ eraser: Eraser | None | Literal[False] = None,
+ brush: Brush | None | Literal[False] = None,
+ ):
+ """
+ Parameters:
+ value: Optional initial image(s) to populate the image editor. Should be a dictionary with keys: `background`, `layers`, and `composite`. The values corresponding to `background` and `composite` should be images or None, while `layers` should be a list of images. Images can be of type PIL.Image, np.array, or str filepath/URL. Or, the value can be a callable, in which case the function will be called whenever the app loads to set the initial value of the component.
+ height: The height of the displayed images, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the displayed images, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ image_mode: "RGB" if color, or "L" if black and white. See https://pillow.readthedocs.io/en/stable/handbook/concepts.html for other supported image modes and their meaning.
+ sources: List of sources that can be used to set the background image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "clipboard" allows users to paste an image from the clipboard.
+ type: The format the images are converted to before being passed into the prediction function. "numpy" converts the images to numpy arrays with shape (height, width, 3) and values from 0 to 255, "pil" converts the images to PIL image objects, "filepath" passes images as str filepaths to temporary copies of the images.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ show_download_button: If True, will display button to download image.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will allow users to upload and edit an image; if False, can only be used to display images. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ mirror_webcam: If True webcam will be mirrored. Default is True.
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ crop_size: The size of the crop box in pixels. If a tuple, the first value is the width and the second value is the height. If a string, the value must be a ratio in the form `width:height` (e.g. "16:9").
+ transforms: The transforms tools to make available to users. "crop" allows the user to crop the image.
+ eraser: The options for the eraser tool in the image editor. Should be an instance of the `gr.Eraser` class, or None to use the default settings. Can also be False to hide the eraser tool.
+ brush: The options for the brush tool in the image editor. Should be an instance of the `gr.Brush` class, or None to use the default settings. Can also be False to hide the brush tool, which will also hide the eraser tool.
+ """
+ self._selectable = _selectable
+ self.mirror_webcam = mirror_webcam
+ valid_types = ["numpy", "pil", "filepath"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.height = height
+ self.width = width
+ self.image_mode = image_mode
+ valid_sources = ["upload", "webcam", "clipboard"]
+ if isinstance(sources, str):
+ sources = [sources] # type: ignore
+ for source in sources:
+ if source not in valid_sources:
+ raise ValueError(
+ f"`sources` must be a list consisting of elements in {valid_sources}"
+ )
+ self.sources = sources
+
+ self.show_download_button = show_download_button
+
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+
+ self.crop_size = crop_size
+ self.transforms = transforms
+ self.eraser = Eraser() if eraser is None else eraser
+ self.brush = Brush() if brush is None else brush
+
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def convert_and_format_image(
+ self,
+ file: FileData | None,
+ ) -> np.ndarray | _Image.Image | str | None:
+ if file is None:
+ return None
+
+ im = _Image.open(file.path)
+
+ if file.orig_name:
+ p = Path(file.orig_name)
+ name = p.stem
+ suffix = p.suffix.replace(".", "")
+ if suffix in ["jpg", "jpeg"]:
+ suffix = "jpeg"
+ else:
+ name = "image"
+ suffix = "png"
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ im = im.convert(self.image_mode)
+ if self.crop_size and not isinstance(self.crop_size, str):
+ im = image_utils.crop_scale(
+ im, int(self.crop_size[0]), int(self.crop_size[1])
+ )
+ return image_utils.format_image(
+ im,
+ cast(Literal["numpy", "pil", "filepath"], self.type),
+ self.GRADIO_CACHE,
+ format=suffix,
+ name=name,
+ )
+
+ def preprocess(self, payload: EditorData | None) -> EditorValue | None:
+ if payload is None:
+ return payload
+
+ bg = self.convert_and_format_image(payload.background)
+ layers = (
+ [self.convert_and_format_image(layer) for layer in payload.layers]
+ if payload.layers
+ else None
+ )
+ composite = self.convert_and_format_image(payload.composite)
+ return {
+ "background": bg,
+ "layers": [x for x in layers if x is not None] if layers else [],
+ "composite": composite,
+ }
+
+ def postprocess(self, value: EditorValue | ImageType | None) -> EditorData | None:
+ if value is None:
+ return None
+ elif isinstance(value, dict):
+ pass
+ elif isinstance(value, (np.ndarray, _Image.Image, str)):
+ value = {"background": value, "layers": [], "composite": value}
+ else:
+ raise ValueError(
+ "The value to `gr.ImageEditor` must be a dictionary of images or a single image."
+ )
+
+ layers = (
+ [
+ FileData(
+ path=image_utils.save_image(
+ cast(Union[np.ndarray, _Image.Image, str], layer),
+ self.GRADIO_CACHE,
+ )
+ )
+ for layer in value["layers"]
+ ]
+ if value["layers"]
+ else []
+ )
+
+ return EditorData(
+ background=FileData(
+ path=image_utils.save_image(value["background"], self.GRADIO_CACHE)
+ )
+ if value["background"] is not None
+ else None,
+ layers=layers,
+ composite=FileData(
+ path=image_utils.save_image(
+ cast(Union[np.ndarray, _Image.Image, str], value["composite"]),
+ self.GRADIO_CACHE,
+ )
+ )
+ if value["composite"] is not None
+ else None,
+ )
+
+ def example_inputs(self) -> Any:
+ return {
+ "background": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ "layers": [],
+ "composite": None,
+ }
diff --git a/gradio/components/json_component.py b/gradio/components/json_component.py
new file mode 100644
index 0000000000000000000000000000000000000000..c444e828ebfa8bbaf7cb8c878d602205107c89cf
--- /dev/null
+++ b/gradio/components/json_component.py
@@ -0,0 +1,93 @@
+"""gr.JSON() component."""
+
+from __future__ import annotations
+
+import json
+from pathlib import Path
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class JSON(Component):
+ """
+ Used to display arbitrary JSON output prettily.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {str} filepath to a file containing valid JSON -- or a {list} or {dict} that is valid JSON
+
+ Demos: zip_to_json, blocks_xray
+ """
+
+ EVENTS = [Events.change]
+
+ def __init__(
+ self,
+ value: str | dict | list | Callable | None = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def postprocess(self, value: dict | list | str | None) -> dict | list | None:
+ if value is None:
+ return None
+ if isinstance(value, str):
+ return json.loads(value)
+ else:
+ return value
+
+ def preprocess(self, payload: dict | list | str | None) -> dict | list | str | None:
+ return payload
+
+ def example_inputs(self) -> Any:
+ return {"foo": "bar"}
+
+ def flag(self, payload: Any, flag_dir: str | Path = "") -> str:
+ return json.dumps(payload)
+
+ def read_from_flag(self, payload: Any, flag_dir: str | Path | None = None):
+ return json.loads(payload)
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": {}, "description": "any valid json"}
diff --git a/gradio/components/label.py b/gradio/components/label.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb910dfd27a7f7721df3d4c2f1373c5391d0c95b
--- /dev/null
+++ b/gradio/components/label.py
@@ -0,0 +1,142 @@
+"""gr.Label() component."""
+
+from __future__ import annotations
+
+import json
+import operator
+from pathlib import Path
+from typing import Any, Callable, List, Optional, Union
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.data_classes import GradioModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+class LabelConfidence(GradioModel):
+ label: Optional[Union[str, int, float]] = None
+ confidence: Optional[float] = None
+
+
+class LabelData(GradioModel):
+ label: Optional[Union[str, int, float]] = None
+ confidences: Optional[List[LabelConfidence]] = None
+
+
+@document()
+class Label(Component):
+ """
+ Displays a classification label, along with confidence scores of top categories, if provided.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {Dict[str, float]} of classes and confidences, or {str} with just the class or an {int}/{float} for regression outputs, or a {str} path to a .json file containing a json dictionary in the structure produced by Label.postprocess().
+
+ Demos: main_note, titanic_survival
+ Guides: image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers
+ """
+
+ CONFIDENCES_KEY = "confidences"
+ data_model = LabelData
+ EVENTS = [Events.change, Events.select]
+
+ def __init__(
+ self,
+ value: dict[str, float] | str | float | Callable | None = None,
+ *,
+ num_top_classes: int | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ color: str | None = None,
+ ):
+ """
+ Parameters:
+ value: Default value to show in the component. If a str or number is provided, simply displays the string or number. If a {Dict[str, float]} of classes and confidences is provided, displays the top class on top and the `num_top_classes` below, along with their confidence bars. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ num_top_classes: number of most confident classes to show.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ color: The background color of the label (either a valid css color name or hexadecimal string).
+ """
+ self.num_top_classes = num_top_classes
+ self.color = color
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def postprocess(
+ self, value: dict[str, float] | str | float | None
+ ) -> LabelData | dict | None:
+ if value is None or value == {}:
+ return {}
+ if isinstance(value, str) and value.endswith(".json") and Path(value).exists():
+ return LabelData(**json.loads(Path(value).read_text()))
+ if isinstance(value, (str, float, int)):
+ return LabelData(label=str(value))
+ if isinstance(value, dict):
+ if "confidences" in value and isinstance(value["confidences"], dict):
+ value = value["confidences"]
+ value = {c["label"]: c["confidence"] for c in value}
+ sorted_pred = sorted(
+ value.items(), key=operator.itemgetter(1), reverse=True
+ )
+ if self.num_top_classes is not None:
+ sorted_pred = sorted_pred[: self.num_top_classes]
+ return LabelData(
+ label=sorted_pred[0][0],
+ confidences=[
+ LabelConfidence(label=pred[0], confidence=pred[1])
+ for pred in sorted_pred
+ ],
+ )
+ raise ValueError(
+ "The `Label` output interface expects one of: a string label, or an int label, a "
+ "float label, or a dictionary whose keys are labels and values are confidences. "
+ f"Instead, got a {type(value)}"
+ )
+
+ def preprocess(
+ self, payload: LabelData | None
+ ) -> dict[str, float] | str | float | None:
+ if payload is None:
+ return None
+ if payload.confidences is None:
+ return payload.label
+ return {
+ d["label"]: d["confidence"] for d in payload.model_dump()["confidences"]
+ }
+
+ def example_inputs(self) -> Any:
+ return {
+ "label": "Cat",
+ "confidences": [
+ {"label": "cat", "confidence": 0.9},
+ {"label": "dog", "confidence": 0.1},
+ ],
+ }
diff --git a/gradio/components/line_plot.py b/gradio/components/line_plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..b019e072f7aaf3aaaf78f43c40293f21cbba993c
--- /dev/null
+++ b/gradio/components/line_plot.py
@@ -0,0 +1,327 @@
+"""gr.LinePlot() component"""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+import altair as alt
+import pandas as pd
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.plot import AltairPlot, AltairPlotData, Plot
+
+set_documentation_group("component")
+
+
+@document()
+class LinePlot(Plot):
+ """
+ Create a line plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: line_plot, live_dashboard
+ """
+
+ data_model = AltairPlotData
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ stroke_dash: str | None = None,
+ overlay_point: bool | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ stroke_dash_legend_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ stroke_dash_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ x_lim: list[int] | None = None,
+ y_lim: list[int] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ every: float | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ show_actions_button: bool = False,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ stroke_dash: The column to determine the symbol used to draw the line, e.g. dashed lines, dashed lines with points.
+ overlay_point: Whether to draw a point on the line for each (x, y) coordinate pair.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ x_label_angle: The angle for the x axis labels. Positive values are clockwise, and negative values are counter-clockwise.
+ y_label_angle: The angle for the y axis labels. Positive values are clockwise, and negative values are counter-clockwise.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ stroke_dash_legend_title: The title given to the stroke_dash legend. By default, uses the value of the stroke_dash parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ stroke_dash_legend_position: The position of the stoke_dash legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ show_actions_button: Whether to show the actions button on the top right corner of the plot.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.stroke_dash = stroke_dash
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.x_label_angle = x_label_angle
+ self.y_label_angle = y_label_angle
+ self.color_legend_title = color_legend_title
+ self.stroke_dash_legend_title = stroke_dash_legend_title
+ self.color_legend_position = color_legend_position
+ self.stroke_dash_legend_position = stroke_dash_legend_position
+ self.overlay_point = overlay_point
+ self.x_lim = x_lim
+ self.y_lim = y_lim
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ self.show_actions_button = show_actions_button
+ super().__init__(
+ value=value,
+ label=label,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ every=every,
+ )
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ stroke_dash: str | None = None,
+ overlay_point: bool | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ stroke_dash_legend_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ stroke_dash_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: list[int] | None = None,
+ y_lim: list[int] | None = None,
+ interactive: bool | None = None,
+ ):
+ """Helper for creating the scatter plot."""
+ interactive = True if interactive is None else interactive
+ encodings = {
+ "x": alt.X(
+ x, # type: ignore
+ title=x_title or x, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ axis=alt.Axis(labelAngle=x_label_angle)
+ if x_label_angle is not None
+ else alt.Axis(),
+ ),
+ "y": alt.Y(
+ y, # type: ignore
+ title=y_title or y, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ axis=alt.Axis(labelAngle=y_label_angle)
+ if y_label_angle is not None
+ else alt.Axis(),
+ ),
+ }
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+
+ if color:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ encodings["color"] = {
+ "field": color,
+ "type": "nominal",
+ "scale": {"domain": domain, "range": range_},
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ }
+
+ highlight = None
+ if interactive and any([color, stroke_dash]):
+ highlight = alt.selection(
+ type="single", # type: ignore
+ on="mouseover",
+ fields=[c for c in [color, stroke_dash] if c],
+ nearest=True,
+ )
+
+ if stroke_dash:
+ stroke_dash = {
+ "field": stroke_dash, # type: ignore
+ "legend": AltairPlot.create_legend( # type: ignore
+ position=stroke_dash_legend_position, # type: ignore
+ title=stroke_dash_legend_title or stroke_dash, # type: ignore
+ ), # type: ignore
+ } # type: ignore
+ else:
+ stroke_dash = alt.value(alt.Undefined) # type: ignore
+
+ if tooltip:
+ encodings["tooltip"] = tooltip
+
+ chart = alt.Chart(value).encode(**encodings) # type: ignore
+
+ points = chart.mark_point(clip=True).encode(
+ opacity=alt.value(alt.Undefined) if overlay_point else alt.value(0),
+ )
+ lines = chart.mark_line(clip=True).encode(strokeDash=stroke_dash)
+
+ if highlight:
+ points = points.add_selection(highlight)
+
+ lines = lines.encode(
+ size=alt.condition(highlight, alt.value(4), alt.value(1)),
+ )
+
+ chart = (lines + points).properties(background="transparent", **properties)
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(
+ self, value: pd.DataFrame | dict | None
+ ) -> AltairPlotData | dict | None:
+ # if None or update
+ if value is None or isinstance(value, dict):
+ return value
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=value,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ overlay_point=self.overlay_point,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ x_label_angle=self.x_label_angle,
+ y_label_angle=self.y_label_angle,
+ color_legend_title=self.color_legend_title, # type: ignore
+ color_legend_position=self.color_legend_position, # type: ignore
+ stroke_dash_legend_title=self.stroke_dash_legend_title,
+ stroke_dash_legend_position=self.stroke_dash_legend_position, # type: ignore
+ x_lim=self.x_lim,
+ y_lim=self.y_lim,
+ stroke_dash=self.stroke_dash,
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ )
+
+ return AltairPlotData(type="altair", plot=chart.to_json(), chart="line")
+
+ def example_inputs(self) -> Any:
+ return None
+
+ def preprocess(self, value: AltairPlotData | None) -> AltairPlotData | None:
+ return value
diff --git a/gradio/components/login_button.py b/gradio/components/login_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..04b1a97b34c66c12c299fabd00aa4c114a2dda2e
--- /dev/null
+++ b/gradio/components/login_button.py
@@ -0,0 +1,118 @@
+"""Predefined button to sign in with Hugging Face in a Gradio Space."""
+from __future__ import annotations
+
+import json
+import warnings
+from typing import Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components import Button
+from gradio.context import Context
+from gradio.routes import Request
+
+set_documentation_group("component")
+
+
+@document()
+class LoginButton(Button):
+ """
+ Button that redirects the user to Sign with Hugging Face using OAuth.
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str = "Sign in with Hugging Face",
+ logout_value: str = "Logout ({})",
+ *,
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ size: Literal["sm", "lg"] | None = None,
+ icon: str
+ | None = "https://huggingface.co/front/assets/huggingface_logo-noborder.svg",
+ link: str | None = None,
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ scale: int | None = 0,
+ min_width: int | None = None,
+ signed_in_value: str = "Signed in as {}",
+ ):
+ """
+ Parameters:
+ logout_value: The text to display when the user is signed in. The string should contain a placeholder for the username with a call-to-action to logout, e.g. "Logout ({})".
+ """
+ if signed_in_value != "Signed in as {}":
+ warnings.warn(
+ "The `signed_in_value` parameter is deprecated. Please use `logout_value` instead."
+ )
+ self.logout_value = logout_value
+ super().__init__(
+ value,
+ every=every,
+ variant=variant,
+ size=size,
+ icon=icon,
+ link=link,
+ visible=visible,
+ interactive=interactive,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ scale=scale,
+ min_width=min_width,
+ )
+ if Context.root_block:
+ self.activate()
+ else:
+ warnings.warn(
+ "LoginButton created outside of a Blocks context. May not work unless you call its `activate()` method manually."
+ )
+
+ def activate(self):
+ # Taken from https://cmgdo.com/external-link-in-gradio-button/
+ # Taking `self` as input to check if user is logged in
+ # ('self' value will be either "Sign in with Hugging Face" or "Signed in as ...")
+ _js = _js_handle_redirect.replace(
+ "BUTTON_DEFAULT_VALUE", json.dumps(self.value)
+ )
+ self.click(fn=None, inputs=[self], outputs=None, js=_js)
+
+ self.attach_load_event(self._check_login_status, None)
+
+ def _check_login_status(self, request: Request) -> LoginButton:
+ # Each time the page is refreshed or loaded, check if the user is logged in and adapt label
+ session = getattr(request, "session", None) or getattr(
+ request.request, "session", None
+ )
+ if session is None or "oauth_info" not in session:
+ return LoginButton(value=self.value, interactive=True)
+ else:
+ username = session["oauth_info"]["userinfo"]["preferred_username"]
+ logout_text = self.logout_value.format(username)
+ return LoginButton(logout_text, interactive=True)
+
+
+# JS code to redirects to /login/huggingface if user is not logged in.
+# If the app is opened in an iframe, open the login page in a new tab.
+# Otherwise, redirects locally. Taken from https://stackoverflow.com/a/61596084.
+# If user is logged in, redirect to logout page (always in-place).
+_js_handle_redirect = """
+(buttonValue) => {
+ if (buttonValue === BUTTON_DEFAULT_VALUE) {
+ url = '/login/huggingface' + window.location.search;
+ if ( window !== window.parent ) {
+ window.open(url, '_blank');
+ } else {
+ window.location.assign(url);
+ }
+ } else {
+ url = '/logout' + window.location.search
+ window.location.assign(url);
+ }
+}
+"""
diff --git a/gradio/components/logout_button.py b/gradio/components/logout_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..c80822e0e0017f2fc8c67cacff6df693dadabcdd
--- /dev/null
+++ b/gradio/components/logout_button.py
@@ -0,0 +1,61 @@
+"""Predefined button to sign out from Hugging Face in a Gradio Space."""
+from __future__ import annotations
+
+import warnings
+from typing import Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components import Button
+
+set_documentation_group("component")
+
+
+@document()
+class LogoutButton(Button):
+ """
+ Button to log out a user from a Space.
+
+ Note: `LogoutButton` component is deprecated. Please use `gr.LoginButton` instead
+ which handles both the login and logout processes.
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str = "Logout",
+ *,
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ size: Literal["sm", "lg"] | None = None,
+ icon: str
+ | None = "https://huggingface.co/front/assets/huggingface_logo-noborder.svg",
+ # Link to logout page (which will delete the session cookie and redirect to landing page).
+ link: str | None = "/logout",
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ scale: int | None = 0,
+ min_width: int | None = None,
+ ):
+ warnings.warn(
+ "The `gr.LogoutButton` component is deprecated. Please use `gr.LoginButton` instead which handles both the login and logout processes."
+ )
+ super().__init__(
+ value,
+ every=every,
+ variant=variant,
+ size=size,
+ icon=icon,
+ link=link,
+ visible=visible,
+ interactive=interactive,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ scale=scale,
+ min_width=min_width,
+ )
diff --git a/gradio/components/markdown.py b/gradio/components/markdown.py
new file mode 100644
index 0000000000000000000000000000000000000000..cdf1a45da4bf9f3b0b28bdb589554dd9dd736f53
--- /dev/null
+++ b/gradio/components/markdown.py
@@ -0,0 +1,94 @@
+"""gr.Markdown() component."""
+
+from __future__ import annotations
+
+import inspect
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Markdown(Component):
+ """
+ Used to render arbitrary Markdown output. Can also render latex enclosed by dollar signs.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a valid {str} that can be rendered as Markdown.
+
+ Demos: blocks_hello, blocks_kinematics
+ Guides: key-features
+ """
+
+ EVENTS = [Events.change]
+
+ def __init__(
+ self,
+ value: str | Callable = "",
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ rtl: bool = False,
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ sanitize_html: bool = True,
+ line_breaks: bool = False,
+ header_links: bool = False,
+ ):
+ """
+ Parameters:
+ value: Value to show in Markdown component. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Is used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: This parameter has no effect.
+ rtl: If True, sets the direction of the rendered text to right-to-left. Default is False, which renders text left-to-right.
+ latex_delimiters: A list of dicts of the form {"left": open delimiter (str), "right": close delimiter (str), "display": whether to display in newline (bool)} that will be used to render LaTeX expressions. If not provided, `latex_delimiters` is set to `[{ "left": "$$", "right": "$$", "display": True }]`, so only expressions enclosed in $$ delimiters will be rendered as LaTeX, and in a new line. Pass in an empty list to disable LaTeX rendering. For more information, see the [KaTeX documentation](https://katex.org/docs/autorender.html).
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ sanitize_html: If False, will disable HTML sanitization when converted from markdown. This is not recommended, as it can lead to security vulnerabilities.
+ line_breaks: If True, will enable Github-flavored Markdown line breaks in chatbot messages. If False (default), single new lines will be ignored.
+ header_links: If True, will automatically create anchors for headings, displaying a link icon on hover.
+ """
+ self.rtl = rtl
+ if latex_delimiters is None:
+ latex_delimiters = [{"left": "$$", "right": "$$", "display": True}]
+ self.latex_delimiters = latex_delimiters
+ self.sanitize_html = sanitize_html
+ self.line_breaks = line_breaks
+ self.header_links = header_links
+
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def postprocess(self, value: str | None) -> str | None:
+ if value is None:
+ return None
+ unindented_y = inspect.cleandoc(value)
+ return unindented_y
+
+ def preprocess(self, payload: str | None) -> str | None:
+ return payload
+
+ def example_inputs(self) -> Any:
+ return "# Hello!"
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
diff --git a/gradio/components/model3d.py b/gradio/components/model3d.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d501131252170657416d7b83dfdc4f894589bf0
--- /dev/null
+++ b/gradio/components/model3d.py
@@ -0,0 +1,114 @@
+"""gr.Model3D() component."""
+
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.data_classes import FileData
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Model3D(Component):
+ """
+ Component allows users to upload or view 3D Model files (.obj, .glb, or .gltf).
+ Preprocessing: This component passes the uploaded file as a {str}filepath.
+ Postprocessing: expects function to return a {str} or {pathlib.Path} filepath of type (.obj, glb, or .gltf)
+
+ Demos: model3D
+ Guides: how-to-use-3D-model-component
+ """
+
+ EVENTS = [Events.change, Events.upload, Events.edit, Events.clear]
+
+ data_model = FileData
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ clear_color: tuple[float, float, float, float] | None = None,
+ camera_position: tuple[
+ int | float | None, int | float | None, int | float | None
+ ] = (
+ None,
+ None,
+ None,
+ ),
+ zoom_speed: float = 1,
+ pan_speed: float = 1,
+ height: int | str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ every: float | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: path to (.obj, glb, or .gltf) file to show in model3D viewer. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ clear_color: background color of scene, should be a tuple of 4 floats between 0 and 1 representing RGBA values.
+ camera_position: initial camera position of scene, provided as a tuple of `(alpha, beta, radius)`. Each value is optional. If provided, `alpha` and `beta` should be in degrees reflecting the angular position along the longitudinal and latitudinal axes, respectively. Radius corresponds to the distance from the center of the object to the camera.
+ zoom_speed: the speed of zooming in and out of the scene when the cursor wheel is rotated or when screen is pinched on a mobile device. Should be a positive float, increase this value to make zooming faster, decrease to make it slower. Affects the wheelPrecision property of the camera.
+ pan_speed: the speed of panning the scene when the cursor is dragged or when the screen is dragged on a mobile device. Should be a positive float, increase this value to make panning faster, decrease to make it slower. Affects the panSensibility property of the camera.
+ height: The height of the model3D component, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ show_label: if True, will display label.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.clear_color = clear_color or [0, 0, 0, 0]
+ self.camera_position = camera_position
+ self.height = height
+ self.zoom_speed = zoom_speed
+ self.pan_speed = pan_speed
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def preprocess(self, payload: FileData | None) -> str | None:
+ if payload is None:
+ return payload
+ return payload.path
+
+ def postprocess(self, value: str | Path | None) -> FileData | None:
+ if value is None:
+ return value
+ return FileData(path=str(value), orig_name=Path(value).name)
+
+ def process_example(self, input_data: str | Path | None) -> str:
+ return Path(input_data).name if input_data else ""
+
+ def example_inputs(self):
+ # TODO: Use permanent link
+ return "https://raw.githubusercontent.com/gradio-app/gradio/main/demo/model3D/files/Fox.gltf"
diff --git a/gradio/components/number.py b/gradio/components/number.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f44edb43d6ac9b11935191828c6538dea588d05
--- /dev/null
+++ b/gradio/components/number.py
@@ -0,0 +1,131 @@
+"""gr.Number() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+from gradio.exceptions import Error
+
+set_documentation_group("component")
+
+
+@document()
+class Number(FormComponent):
+ """
+ Creates a numeric field for user to enter numbers as input or display numeric output.
+ Preprocessing: passes field value as a {float} or {int} into the function, depending on `precision`.
+ Postprocessing: expects an {int} or {float} returned from the function and sets field value to it.
+ Examples-format: a {float} or {int} representing the number's value.
+
+ Demos: tax_calculator, titanic_survival, blocks_simple_squares
+ """
+
+ EVENTS = [Events.change, Events.input, Events.submit, Events.focus]
+
+ def __init__(
+ self,
+ value: float | Callable | None = None,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ precision: int | None = None,
+ minimum: float | None = None,
+ maximum: float | None = None,
+ step: float = 1,
+ ):
+ """
+ Parameters:
+ value: default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will be editable; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ precision: Precision to round input/output to. If set to 0, will round to nearest integer and convert type to int. If None, no rounding happens.
+ minimum: Minimum value. Only applied when component is used as an input. If a user provides a smaller value, a gr.Error exception is raised by the backend.
+ maximum: Maximum value. Only applied when component is used as an input. If a user provides a larger value, a gr.Error exception is raised by the backend.
+ step: The interval between allowed numbers in the component. Can be used along with optional parameters `minimum` and `maximum` to create a range of legal values starting from `minimum` and incrementing according to this parameter.
+ """
+ self.precision = precision
+ self.minimum = minimum
+ self.maximum = maximum
+ self.step = step
+
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ @staticmethod
+ def _round_to_precision(num: float | int, precision: int | None) -> float | int:
+ """
+ Round to a given precision.
+
+ If precision is None, no rounding happens. If 0, num is converted to int.
+
+ Parameters:
+ num: Number to round.
+ precision: Precision to round to.
+ Returns:
+ rounded number or the original number if precision is None
+ """
+ if precision is None:
+ return num
+ elif precision == 0:
+ return int(round(num, precision))
+ else:
+ return round(num, precision)
+
+ def preprocess(self, payload: float | None) -> float | None:
+ if payload is None:
+ return None
+ elif self.minimum is not None and payload < self.minimum:
+ raise Error(f"Value {payload} is less than minimum value {self.minimum}.")
+ elif self.maximum is not None and payload > self.maximum:
+ raise Error(
+ f"Value {payload} is greater than maximum value {self.maximum}."
+ )
+ return self._round_to_precision(payload, self.precision)
+
+ def postprocess(self, value: float | None) -> float | None:
+ if value is None:
+ return None
+ return self._round_to_precision(value, self.precision)
+
+ def api_info(self) -> dict[str, str]:
+ return {"type": "number"}
+
+ def example_inputs(self) -> Any:
+ return 3
diff --git a/gradio/components/paramviewer.py b/gradio/components/paramviewer.py
new file mode 100644
index 0000000000000000000000000000000000000000..66220d54733dddc2ba420ad90aec31fffdd53838
--- /dev/null
+++ b/gradio/components/paramviewer.py
@@ -0,0 +1,73 @@
+from __future__ import annotations
+
+from typing import Literal, TypedDict
+
+from gradio.components.base import Component
+from gradio.events import Events
+
+
+class Parameter(TypedDict):
+ type: str
+ description: str
+ default: str
+
+
+class ParamViewer(Component):
+ """
+ Displays an interactive table of parameters and their descriptions and default values width syntax highlighting
+ """
+
+ EVENTS = [
+ Events.change,
+ Events.upload,
+ ]
+
+ def __init__(
+ self,
+ value: list[Parameter] | None = None,
+ language: Literal["python", "typescript"] = "python",
+ linkify: list[str] | None = None,
+ every: float | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: A list of dictionaries with keys "type", "description", and "default" for each parameter.
+ language: The language to display the code in. One of "python" or "typescript".
+ linkify: A list of strings to linkify. If a string is found in the description, it will be linked to the corresponding url.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+
+ """
+ self.value = value
+ self.language = language
+ self.linkify = linkify
+ super().__init__(
+ every=every,
+ value=value,
+ render=render,
+ )
+
+ def preprocess(self, payload: list[Parameter]) -> list[Parameter]:
+ """
+ Parameters:
+ payload: A list of dictionaries with keys "type", "description", and "default" for each parameter.
+ Returns:
+ A list of dictionaries with keys "type", "description", and "default" for each parameter.
+ """
+ return payload
+
+ def postprocess(self, value: list[Parameter]) -> list[Parameter]:
+ """
+ Parameters:
+ value: A list of dictionaries with keys "type", "description", and "default" for each parameter.
+ Returns:
+ A list of dictionaries with keys "type", "description", and "default" for each parameter.
+ """
+ return value
+
+ def example_inputs(self):
+ return [{"type": "numpy", "description": "any valid json", "default": "None"}]
+
+ def api_info(self):
+ return {"type": {}, "description": "any valid json"}
diff --git a/gradio/components/plot.py b/gradio/components/plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..673b51dd59dee502ea6c4af4fda0d2763a07e9dc
--- /dev/null
+++ b/gradio/components/plot.py
@@ -0,0 +1,139 @@
+"""gr.Plot() component."""
+
+from __future__ import annotations
+
+import json
+from types import ModuleType
+from typing import Any, Callable, Literal
+
+import altair as alt
+import pandas as pd
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import processing_utils
+from gradio.components.base import Component
+from gradio.data_classes import GradioModel
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+class PlotData(GradioModel):
+ type: Literal["altair", "bokeh", "plotly", "matplotlib"]
+ plot: str
+
+
+class AltairPlotData(PlotData):
+ chart: Literal["bar", "line", "scatter"]
+ type: Literal["altair"] = "altair"
+
+
+@document()
+class Plot(Component):
+ """
+ Used to display various kinds of plots (matplotlib, plotly, or bokeh are supported).
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects either a {matplotlib.figure.Figure}, a {plotly.graph_objects._figure.Figure}, or a {dict} corresponding to a bokeh plot (json_item format)
+
+ Demos: altair_plot, outbreak_forecast, blocks_kinematics, stock_forecast, map_airbnb
+ Guides: plot-component-for-maps
+ """
+
+ data_model = PlotData
+ EVENTS = [Events.change, Events.clear]
+
+ def __init__(
+ self,
+ value: Callable | None | pd.DataFrame = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: Optionally, supply a default plot object to display, must be a matplotlib, plotly, altair, or bokeh figure, or a callable. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def get_config(self):
+ try:
+ import bokeh # type: ignore
+
+ bokeh_version = bokeh.__version__
+ except ImportError:
+ bokeh_version = None
+
+ config = super().get_config()
+ config["bokeh_version"] = bokeh_version
+ return config
+
+ def preprocess(self, payload: PlotData | None) -> PlotData | None:
+ return payload
+
+ def example_inputs(self) -> Any:
+ return None
+
+ def postprocess(self, value) -> PlotData | None:
+ import matplotlib.figure
+
+ if value is None:
+ return None
+ if isinstance(value, (ModuleType, matplotlib.figure.Figure)): # type: ignore
+ dtype = "matplotlib"
+ out_y = processing_utils.encode_plot_to_base64(value)
+ elif "bokeh" in value.__module__:
+ dtype = "bokeh"
+ from bokeh.embed import json_item # type: ignore
+
+ out_y = json.dumps(json_item(value))
+ else:
+ is_altair = "altair" in value.__module__
+ dtype = "altair" if is_altair else "plotly"
+ out_y = value.to_json()
+ return PlotData(type=dtype, plot=out_y)
+
+
+class AltairPlot:
+ @staticmethod
+ def create_legend(position, title):
+ if position == "none":
+ legend = None
+ else:
+ position = {"orient": position} if position else {}
+ legend = {"title": title, **position}
+
+ return legend
+
+ @staticmethod
+ def create_scale(limit):
+ return alt.Scale(domain=limit) if limit else alt.Undefined
diff --git a/gradio/components/radio.py b/gradio/components/radio.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ba9f45d5ff2322925f00bde109418512b26fa5b
--- /dev/null
+++ b/gradio/components/radio.py
@@ -0,0 +1,127 @@
+"""gr.Radio() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Radio(FormComponent):
+ """
+ Creates a set of (string or numeric type) radio buttons of which only one can be selected.
+ Preprocessing: passes the value of the selected radio button as a {str} or {int} or {float} or its index as an {int} into the function, depending on `type`.
+ Postprocessing: expects a {str} or {int} or {float} corresponding to the value of the radio button to be selected.
+ Examples-format: a {str} representing the radio option to select.
+
+ Demos: sentence_builder, titanic_survival, blocks_essay
+ """
+
+ EVENTS = [Events.select, Events.change, Events.input]
+
+ def __init__(
+ self,
+ choices: list[str | int | float | tuple[str, str | int | float]] | None = None,
+ *,
+ value: str | int | float | Callable | None = None,
+ type: str = "value",
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ choices: A list of string or numeric options to select from. An option can also be a tuple of the form (name, value), where name is the displayed name of the radio button and value is the value to be passed to the function, or returned by the function.
+ value: The option selected by default. If None, no option is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: Additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: Relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: Minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: If True, choices in this radio group will be selectable; if False, selection will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.choices = (
+ # Although we expect choices to be a list of tuples, it can be a list of tuples if the Gradio app
+ # is loaded with gr.load() since Python tuples are converted to lists in JSON.
+ [tuple(c) if isinstance(c, (tuple, list)) else (str(c), c) for c in choices]
+ if choices
+ else []
+ )
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def example_inputs(self) -> Any:
+ return self.choices[0][1] if self.choices else None
+
+ def preprocess(self, payload: str | int | float | None) -> str | int | float | None:
+ """
+ Parameters:
+ payload: selected choice
+ Returns:
+ value of the selected choice as string or index within choice list
+ """
+ if self.type == "value":
+ return payload
+ elif self.type == "index":
+ if payload is None:
+ return None
+ else:
+ choice_values = [value for _, value in self.choices]
+ return (
+ choice_values.index(payload) if payload in choice_values else None
+ )
+ else:
+ raise ValueError(
+ f"Unknown type: {self.type}. Please choose from: 'value', 'index'."
+ )
+
+ def postprocess(self, value: str | int | float | None) -> str | int | float | None:
+ return value
+
+ def api_info(self) -> dict[str, Any]:
+ return {
+ "enum": [c[1] for c in self.choices],
+ "title": "Radio",
+ "type": "string",
+ }
diff --git a/gradio/components/scatter_plot.py b/gradio/components/scatter_plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e5dd4120751efc0e12c3dd58356439aa4849431
--- /dev/null
+++ b/gradio/components/scatter_plot.py
@@ -0,0 +1,352 @@
+"""gr.ScatterPlot() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+import altair as alt
+import pandas as pd
+from gradio_client.documentation import document, set_documentation_group
+from pandas.api.types import is_numeric_dtype
+
+from gradio.components.plot import AltairPlot, AltairPlotData, Plot
+
+set_documentation_group("component")
+
+
+@document()
+class ScatterPlot(Plot):
+ """
+ Create a scatter plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: scatter_plot
+ Guides: creating-a-dashboard-from-bigquery-data
+ """
+
+ data_model = AltairPlotData
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ size: str | None = None,
+ shape: str | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ size_legend_title: str | None = None,
+ shape_legend_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ size_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ shape_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ x_lim: list[int | float] | None = None,
+ y_lim: list[int | float] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ show_actions_button: bool = False,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot, or a callable. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ size: The column used to determine the point size. Should contain numeric data so that gradio can map the data to the point size.
+ shape: The column used to determine the point shape. Should contain categorical data. Gradio will map each unique value to a different shape.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x-axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y-axis. By default, uses the value of the y parameter.
+ x_label_angle: The angle for the x axis labels rotation. Positive values are clockwise, and negative values are counter-clockwise.
+ y_label_angle: The angle for the y axis labels rotation. Positive values are clockwise, and negative values are counter-clockwise.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ size_legend_title: The title given to the size legend. By default, uses the value of the size parameter.
+ shape_legend_title: The title given to the shape legend. By default, uses the value of the shape parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ size_legend_position: The position of the size legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ shape_legend_position: The position of the shape legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: Whether the label should be displayed.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ show_actions_button: Whether to show the actions button on the top right corner of the plot.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.size = size
+ self.shape = shape
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.x_label_angle = x_label_angle
+ self.y_label_angle = y_label_angle
+ self.color_legend_title = color_legend_title
+ self.color_legend_position = color_legend_position
+ self.size_legend_title = size_legend_title
+ self.size_legend_position = size_legend_position
+ self.shape_legend_title = shape_legend_title
+ self.shape_legend_position = shape_legend_position
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ self.x_lim = x_lim
+ self.y_lim = y_lim
+ self.show_actions_button = show_actions_button
+ super().__init__(
+ value=value,
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ size: str | None = None,
+ shape: str | None = None,
+ title: str | None = None,
+ tooltip: list[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ x_label_angle: float | None = None,
+ y_label_angle: float | None = None,
+ color_legend_title: str | None = None,
+ size_legend_title: str | None = None,
+ shape_legend_title: str | None = None,
+ color_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ size_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ shape_legend_position: Literal[
+ "left",
+ "right",
+ "top",
+ "bottom",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ "none",
+ ]
+ | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: list[int | float] | None = None,
+ y_lim: list[int | float] | None = None,
+ interactive: bool | None = True,
+ ):
+ """Helper for creating the scatter plot."""
+ interactive = True if interactive is None else interactive
+ encodings = {
+ "x": alt.X(
+ x, # type: ignore
+ title=x_title or x, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ axis=alt.Axis(labelAngle=x_label_angle)
+ if x_label_angle is not None
+ else alt.Axis(),
+ ), # ignore: type
+ "y": alt.Y(
+ y, # type: ignore
+ title=y_title or y, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ axis=alt.Axis(labelAngle=y_label_angle)
+ if y_label_angle is not None
+ else alt.Axis(),
+ ),
+ }
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+ if color:
+ if is_numeric_dtype(value[color]):
+ domain = [value[color].min(), value[color].max()]
+ range_ = [0, 1]
+ type_ = "quantitative"
+ else:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ type_ = "nominal"
+
+ encodings["color"] = {
+ "field": color,
+ "type": type_,
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ "scale": {"domain": domain, "range": range_},
+ }
+ if tooltip:
+ encodings["tooltip"] = tooltip
+ if size:
+ encodings["size"] = {
+ "field": size,
+ "type": "quantitative" if is_numeric_dtype(value[size]) else "nominal",
+ "legend": AltairPlot.create_legend(
+ position=size_legend_position, title=size_legend_title or size
+ ),
+ }
+ if shape:
+ encodings["shape"] = {
+ "field": shape,
+ "type": "quantitative" if is_numeric_dtype(value[shape]) else "nominal",
+ "legend": AltairPlot.create_legend(
+ position=shape_legend_position, title=shape_legend_title or shape
+ ),
+ }
+ chart = (
+ alt.Chart(value) # type: ignore
+ .mark_point(clip=True) # type: ignore
+ .encode(**encodings)
+ .properties(background="transparent", **properties)
+ )
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(
+ self, value: pd.DataFrame | dict | None
+ ) -> AltairPlotData | dict | None:
+ # if None or update
+ if value is None or isinstance(value, dict):
+ return value
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=value,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ size=self.size,
+ shape=self.shape,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ x_label_angle=self.x_label_angle,
+ y_label_angle=self.y_label_angle,
+ color_legend_title=self.color_legend_title,
+ size_legend_title=self.size_legend_title,
+ shape_legend_title=self.size_legend_title,
+ color_legend_position=self.color_legend_position, # type: ignore
+ size_legend_position=self.size_legend_position, # type: ignore
+ shape_legend_position=self.shape_legend_position, # type: ignore
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ x_lim=self.x_lim,
+ y_lim=self.y_lim,
+ )
+
+ return AltairPlotData(type="altair", plot=chart.to_json(), chart="scatter")
+
+ def example_inputs(self) -> Any:
+ return None
+
+ def preprocess(self, payload: AltairPlotData | None) -> AltairPlotData | None:
+ return payload
diff --git a/gradio/components/slider.py b/gradio/components/slider.py
new file mode 100644
index 0000000000000000000000000000000000000000..62c031dc7eb7fbcef6e5301bc17edda5481f5723
--- /dev/null
+++ b/gradio/components/slider.py
@@ -0,0 +1,121 @@
+"""gr.Slider() component."""
+
+from __future__ import annotations
+
+import math
+import random
+from typing import Any, Callable
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import FormComponent
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Slider(FormComponent):
+ """
+ Creates a slider that ranges from {minimum} to {maximum} with a step size of {step}.
+ Preprocessing: passes slider value as a {float} into the function.
+ Postprocessing: expects an {int} or {float} returned from function and sets slider value to it as long as it is within range.
+ Examples-format: A {float} or {int} representing the slider's value.
+
+ Demos: sentence_builder, slider_release, interface_random_slider, blocks_random_slider
+ Guides: create-your-own-friends-with-a-gan
+ """
+
+ EVENTS = [Events.change, Events.input, Events.release]
+
+ def __init__(
+ self,
+ minimum: float = 0,
+ maximum: float = 100,
+ value: float | Callable | None = None,
+ *,
+ step: float | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ randomize: bool = False,
+ ):
+ """
+ Parameters:
+ minimum: minimum value for slider.
+ maximum: maximum value for slider.
+ value: default value. If callable, the function will be called whenever the app loads to set the initial value of the component. Ignored if randomized=True.
+ step: increment between slider values.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, slider will be adjustable; if False, adjusting will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ randomize: If True, the value of the slider when the app loads is taken uniformly at random from the range given by the minimum and maximum.
+ """
+ self.minimum = minimum
+ self.maximum = maximum
+ if step is None:
+ difference = maximum - minimum
+ power = math.floor(math.log10(difference) - 2)
+ self.step = 10**power
+ else:
+ self.step = step
+ if randomize:
+ value = self.get_random_value
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def api_info(self) -> dict[str, Any]:
+ return {
+ "type": "number",
+ "description": f"numeric value between {self.minimum} and {self.maximum}",
+ }
+
+ def example_inputs(self) -> Any:
+ return self.minimum
+
+ def get_random_value(self):
+ n_steps = int((self.maximum - self.minimum) / self.step)
+ step = random.randint(0, n_steps)
+ value = self.minimum + step * self.step
+ # Round to number of decimals in step so that UI doesn't display long decimals
+ n_decimals = max(str(self.step)[::-1].find("."), 0)
+ if n_decimals:
+ value = round(value, n_decimals)
+ return value
+
+ def postprocess(self, value: float | None) -> float:
+ return self.minimum if value is None else value
+
+ def preprocess(self, payload: float) -> float:
+ return payload
diff --git a/gradio/components/state.py b/gradio/components/state.py
new file mode 100644
index 0000000000000000000000000000000000000000..4841c108ef304904d3c84b07fdf55517a050d697
--- /dev/null
+++ b/gradio/components/state.py
@@ -0,0 +1,63 @@
+"""gr.State() component."""
+
+from __future__ import annotations
+
+from copy import deepcopy
+from typing import Any
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+
+set_documentation_group("component")
+
+
+@document()
+class State(Component):
+ EVENTS = []
+ """
+ Special hidden component that stores session state across runs of the demo by the
+ same user. The value of the State variable is cleared when the user refreshes the page.
+
+ Preprocessing: No preprocessing is performed
+ Postprocessing: No postprocessing is performed
+ Demos: interface_state, blocks_simple_squares
+ Guides: real-time-speech-recognition
+ """
+
+ allow_string_shortcut = False
+
+ def __init__(
+ self,
+ value: Any = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ value: the initial value (of arbitrary type) of the state. The provided argument is deepcopied. If a callable is provided, the function will be called whenever the app loads to set the initial value of the state.
+ render: has no effect, but is included for consistency with other components.
+ """
+ self.stateful = True
+ try:
+ self.value = deepcopy(value)
+ except TypeError as err:
+ raise TypeError(
+ f"The initial value of `gr.State` must be able to be deepcopied. The initial value of type {type(value)} cannot be deepcopied."
+ ) from err
+ super().__init__(value=self.value)
+
+ def preprocess(self, payload: Any) -> Any:
+ return payload
+
+ def postprocess(self, value: Any) -> Any:
+ return value
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": {}, "description": "any valid json"}
+
+ def example_inputs(self) -> Any:
+ return None
+
+ @property
+ def skip_api(self):
+ return True
diff --git a/gradio/components/textbox.py b/gradio/components/textbox.py
new file mode 100644
index 0000000000000000000000000000000000000000..c16cb651b379c024ad2e0cb26584e12301077742
--- /dev/null
+++ b/gradio/components/textbox.py
@@ -0,0 +1,130 @@
+"""gr.Textbox() component."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import (
+ FormComponent,
+)
+from gradio.events import Events
+
+set_documentation_group("component")
+
+
+@document()
+class Textbox(FormComponent):
+ """
+ Creates a textarea for user to enter string input or display string output.
+ Preprocessing: passes textarea value as a {str} into the function.
+ Postprocessing: expects a {str} returned from function and sets textarea value to it.
+ Examples-format: a {str} representing the textbox input.
+
+ Demos: hello_world, diff_texts, sentence_builder
+ Guides: creating-a-chatbot, real-time-speech-recognition
+ """
+
+ EVENTS = [
+ Events.change,
+ Events.input,
+ Events.select,
+ Events.submit,
+ Events.focus,
+ Events.blur,
+ ]
+
+ def __init__(
+ self,
+ value: str | Callable | None = "",
+ *,
+ lines: int = 1,
+ max_lines: int = 20,
+ placeholder: str | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ autofocus: bool = False,
+ autoscroll: bool = True,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ type: Literal["text", "password", "email"] = "text",
+ text_align: Literal["left", "right"] | None = None,
+ rtl: bool = False,
+ show_copy_button: bool = False,
+ ):
+ """
+ Parameters:
+ value: default text to provide in textarea. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ lines: minimum number of line rows to provide in textarea.
+ max_lines: maximum number of line rows to provide in textarea.
+ placeholder: placeholder hint to provide behind textarea.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will be rendered as an editable textbox; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ autofocus: If True, will focus on the textbox when the page loads. Use this carefully, as it can cause usability issues for sighted and non-sighted users.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ type: The type of textbox. One of: 'text', 'password', 'email', Default is 'text'.
+ text_align: How to align the text in the textbox, can be: "left", "right", or None (default). If None, the alignment is left if `rtl` is False, or right if `rtl` is True. Can only be changed if `type` is "text".
+ rtl: If True and `type` is "text", sets the direction of the text to right-to-left (cursor appears on the left of the text). Default is False, which renders cursor on the right.
+ show_copy_button: If True, includes a copy button to copy the text in the textbox. Only applies if show_label is True.
+ autoscroll: If True, will automatically scroll to the bottom of the textbox when the value changes, unless the user scrolls up. If False, will not scroll to the bottom of the textbox when the value changes.
+ """
+ if type not in ["text", "password", "email"]:
+ raise ValueError('`type` must be one of "text", "password", or "email".')
+
+ self.lines = lines
+ if type == "text":
+ self.max_lines = max(lines, max_lines)
+ else:
+ self.max_lines = 1
+ self.placeholder = placeholder
+ self.show_copy_button = show_copy_button
+ self.autofocus = autofocus
+ self.autoscroll = autoscroll
+ super().__init__(
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+ self.type = type
+ self.rtl = rtl
+ self.text_align = text_align
+
+ def preprocess(self, payload: str | None) -> str | None:
+ return None if payload is None else str(payload)
+
+ def postprocess(self, value: str | None) -> str | None:
+ return None if value is None else str(value)
+
+ def api_info(self) -> dict[str, Any]:
+ return {"type": "string"}
+
+ def example_inputs(self) -> Any:
+ return "Hello!!"
diff --git a/gradio/components/upload_button.py b/gradio/components/upload_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..62da9d44dec8d98ad7a78fd6ecdf6902e2b6138f
--- /dev/null
+++ b/gradio/components/upload_button.py
@@ -0,0 +1,180 @@
+"""gr.UploadButton() component."""
+
+from __future__ import annotations
+
+import tempfile
+import warnings
+from pathlib import Path
+from typing import Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.components.base import Component
+from gradio.data_classes import FileData, ListFiles
+from gradio.events import Events
+from gradio.utils import NamedString
+
+set_documentation_group("component")
+
+
+@document()
+class UploadButton(Component):
+ """
+ Used to create an upload button, when clicked allows a user to upload files that satisfy the specified file type or generic files (if file_type not set).
+ Preprocessing: passes the uploaded file as a {file-object} or {List[file-object]} depending on `file_count` (or a {bytes}/{List[bytes]} depending on `type`)
+ Postprocessing: expects function to return a {str} path to a file, or {List[str]} consisting of paths to files.
+ Examples-format: a {str} path to a local file that populates the component.
+ Demos: upload_button
+ """
+
+ EVENTS = [Events.click, Events.upload]
+
+ def __init__(
+ self,
+ label: str = "Upload a File",
+ value: str | list[str] | Callable | None = None,
+ *,
+ every: float | None = None,
+ variant: Literal["primary", "secondary", "stop"] = "secondary",
+ visible: bool = True,
+ size: Literal["sm", "lg"] | None = None,
+ icon: str | None = None,
+ scale: int | None = None,
+ min_width: int | None = None,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ type: Literal["filepath", "bytes"] = "filepath",
+ file_count: Literal["single", "multiple", "directory"] = "single",
+ file_types: list[str] | None = None,
+ ):
+ """
+ Parameters:
+ label: Text to display on the button. Defaults to "Upload a File".
+ value: File or list of files to upload by default.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ variant: 'primary' for main call-to-action, 'secondary' for a more subdued style, 'stop' for a stop button.
+ visible: If False, component will be hidden.
+ size: Size of the button. Can be "sm" or "lg".
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: If False, the UploadButton will be in a disabled state.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
+ file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
+ file_types: List of type of files to be uploaded. "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
+ """
+ valid_types = [
+ "filepath",
+ "binary",
+ ]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.file_count = file_count
+ if file_count == "directory" and file_types is not None:
+ warnings.warn(
+ "The `file_types` parameter is ignored when `file_count` is 'directory'."
+ )
+ if file_types is not None and not isinstance(file_types, list):
+ raise ValueError(
+ f"Parameter file_types must be a list. Received {file_types.__class__.__name__}"
+ )
+ if self.file_count in ["multiple", "directory"]:
+ self.data_model = ListFiles
+ else:
+ self.data_model = FileData
+ self.size = size
+ self.file_types = file_types
+ self.label = label
+ self.variant = variant
+ super().__init__(
+ label=label,
+ every=every,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ )
+ self.icon = self.move_resource_to_block_cache(icon)
+
+ def api_info(self) -> dict[str, list[str]]:
+ if self.file_count == "single":
+ return FileData.model_json_schema()
+ else:
+ return ListFiles.model_json_schema()
+
+ def example_inputs(self) -> Any:
+ if self.file_count == "single":
+ return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
+ else:
+ return [
+ "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
+ ]
+
+ def _process_single_file(self, f: FileData) -> bytes | NamedString:
+ file_name = f.path
+ if self.type == "filepath":
+ file = tempfile.NamedTemporaryFile(delete=False, dir=self.GRADIO_CACHE)
+ file.name = file_name
+ return NamedString(file_name)
+ elif self.type == "binary":
+ with open(file_name, "rb") as file_data:
+ return file_data.read()
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(type)
+ + ". Please choose from: 'filepath', 'binary'."
+ )
+
+ def preprocess(
+ self, payload: ListFiles | FileData | None
+ ) -> bytes | NamedString | list[bytes | NamedString] | None:
+ if payload is None:
+ return None
+
+ if self.file_count == "single":
+ if isinstance(payload, ListFiles):
+ return self._process_single_file(payload[0])
+ else:
+ return self._process_single_file(payload)
+ else:
+ if isinstance(payload, ListFiles):
+ return [self._process_single_file(f) for f in payload]
+ else:
+ return [self._process_single_file(payload)]
+
+ def postprocess(self, value: str | list[str] | None) -> ListFiles | FileData | None:
+ if value is None:
+ return None
+ if isinstance(value, list):
+ return ListFiles(
+ root=[
+ FileData(
+ path=file,
+ orig_name=Path(file).name,
+ size=Path(file).stat().st_size,
+ )
+ for file in value
+ ]
+ )
+ else:
+ return FileData(
+ path=value,
+ orig_name=Path(value).name,
+ size=Path(value).stat().st_size,
+ )
+
+ @property
+ def skip_api(self):
+ return False
diff --git a/gradio/components/video.py b/gradio/components/video.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef02697de32060228e3b1cfab246f07757a088d4
--- /dev/null
+++ b/gradio/components/video.py
@@ -0,0 +1,343 @@
+"""gr.Video() component."""
+
+from __future__ import annotations
+
+import tempfile
+import warnings
+from pathlib import Path
+from typing import Any, Callable, Literal, Optional
+
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+import gradio as gr
+from gradio import processing_utils, utils, wasm_utils
+from gradio.components.base import Component
+from gradio.data_classes import FileData, GradioModel
+from gradio.events import Events
+
+if not wasm_utils.IS_WASM:
+ # TODO: Support ffmpeg on Wasm
+ from ffmpy import FFmpeg
+
+set_documentation_group("component")
+
+
+class VideoData(GradioModel):
+ video: FileData
+ subtitles: Optional[FileData] = None
+
+
+@document()
+class Video(Component):
+ """
+ Creates a video component that can be used to upload/record videos (as an input) or display videos (as an output).
+ For the video to be playable in the browser it must have a compatible container and codec combination. Allowed
+ combinations are .mp4 with h264 codec, .ogg with theora codec, and .webm with vp9 codec. If the component detects
+ that the output video would not be playable in the browser it will attempt to convert it to a playable mp4 video.
+ If the conversion fails, the original video is returned.
+ Preprocessing: passes the uploaded video as a {str} filepath or URL whose extension can be modified by `format`.
+ Postprocessing: expects a {str} or {pathlib.Path} filepath to a video which is displayed, or a {Tuple[str | pathlib.Path, str | pathlib.Path | None]} where the first element is a filepath to a video and the second element is an optional filepath to a subtitle file.
+ Examples-format: a {str} filepath to a local file that contains the video, or a {Tuple[str, str]} where the first element is a filepath to a video file and the second element is a filepath to a subtitle file.
+ Demos: video_identity, video_subtitle
+ """
+
+ data_model = VideoData
+
+ EVENTS = [
+ Events.change,
+ Events.clear,
+ Events.start_recording,
+ Events.stop_recording,
+ Events.stop,
+ Events.play,
+ Events.pause,
+ Events.end,
+ Events.upload,
+ ]
+
+ def __init__(
+ self,
+ value: str
+ | Path
+ | tuple[str | Path, str | Path | None]
+ | Callable
+ | None = None,
+ *,
+ format: str | None = None,
+ sources: list[Literal["upload", "webcam"]] | None = None,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ include_audio: bool | None = None,
+ autoplay: bool = False,
+ show_share_button: bool | None = None,
+ show_download_button: bool | None = None,
+ min_length: int | None = None,
+ max_length: int | None = None,
+ ):
+ """
+ Parameters:
+ value: A path or URL for the default value that Video component is going to take. Can also be a tuple consisting of (video filepath, subtitle filepath). If a subtitle file is provided, it should be of type .srt or .vtt. Or can be callable, in which case the function will be called whenever the app loads to set the initial value of the component.
+ format: Format of video format to be returned by component, such as 'avi' or 'mp4'. Use 'mp4' to ensure browser playability. If set to None, video will keep uploaded format.
+ sources: A list of sources permitted for video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam. If None, defaults to ["upload, "webcam"].
+ height: The height of the displayed video, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ width: The width of the displayed video, specified in pixels if a number is passed, or in CSS units if a string is passed.
+ label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
+ min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
+ interactive: if True, will allow users to upload a video; if False, can only be used to display videos. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ mirror_webcam: If True webcam will be mirrored. Default is True.
+ include_audio: Whether the component should record/retain the audio track for a video. By default, audio is excluded for webcam videos and included for uploaded videos.
+ autoplay: Whether to automatically play the video when the component is used as an output. Note: browsers will not autoplay video files if the user has not interacted with the page yet.
+ show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
+ show_download_button: If True, will show a download icon in the corner of the component that allows user to download the output. If False, icon does not appear. By default, it will be True for output components and False for input components.
+ min_length: The minimum length of video (in seconds) that the user can pass into the prediction function. If None, there is no minimum length.
+ max_length: The maximum length of video (in seconds) that the user can pass into the prediction function. If None, there is no maximum length.
+ """
+ valid_sources: list[Literal["upload", "webcam"]] = ["upload", "webcam"]
+ if sources is None:
+ self.sources = valid_sources
+ elif isinstance(sources, str) and sources in valid_sources:
+ self.sources = [sources]
+ elif isinstance(sources, list):
+ self.sources = sources
+ else:
+ raise ValueError(
+ f"`sources` must be a list consisting of elements in {valid_sources}"
+ )
+ for source in self.sources:
+ if source not in valid_sources:
+ raise ValueError(
+ f"`sources` must a list consisting of elements in {valid_sources}"
+ )
+ self.format = format
+ self.autoplay = autoplay
+ self.height = height
+ self.width = width
+ self.mirror_webcam = mirror_webcam
+ self.include_audio = (
+ include_audio if include_audio is not None else "upload" in self.sources
+ )
+ self.show_share_button = (
+ (utils.get_space() is not None)
+ if show_share_button is None
+ else show_share_button
+ )
+ self.show_download_button = show_download_button
+ self.min_length = min_length
+ self.max_length = max_length
+ super().__init__(
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ value=value,
+ )
+
+ def preprocess(self, payload: VideoData | None) -> str | None:
+ if payload is None:
+ return None
+ assert payload.video.path
+ file_name = Path(payload.video.path)
+ uploaded_format = file_name.suffix.replace(".", "")
+ needs_formatting = self.format is not None and uploaded_format != self.format
+ flip = self.sources == ["webcam"] and self.mirror_webcam
+
+ if self.min_length is not None or self.max_length is not None:
+ # With this if-clause, avoid unnecessary execution of `processing_utils.get_video_length`.
+ # This is necessary for the Wasm-mode, because it uses ffprobe, which is not available in the browser.
+ duration = processing_utils.get_video_length(file_name)
+ if self.min_length is not None and duration < self.min_length:
+ raise gr.Error(
+ f"Video is too short, and must be at least {self.min_length} seconds"
+ )
+ if self.max_length is not None and duration > self.max_length:
+ raise gr.Error(
+ f"Video is too long, and must be at most {self.max_length} seconds"
+ )
+
+ if needs_formatting or flip:
+ format = f".{self.format if needs_formatting else uploaded_format}"
+ output_options = ["-vf", "hflip", "-c:a", "copy"] if flip else []
+ output_options += ["-an"] if not self.include_audio else []
+ flip_suffix = "_flip" if flip else ""
+ output_file_name = str(
+ file_name.with_name(f"{file_name.stem}{flip_suffix}{format}")
+ )
+ output_filepath = Path(output_file_name)
+ if output_filepath.exists():
+ return str(output_filepath.resolve())
+ if wasm_utils.IS_WASM:
+ raise wasm_utils.WasmUnsupportedError(
+ "Video formatting is not supported in the Wasm mode."
+ )
+ ff = FFmpeg(
+ inputs={str(file_name): None},
+ outputs={output_file_name: output_options},
+ )
+ ff.run()
+ return str(output_filepath.resolve())
+ elif not self.include_audio:
+ output_file_name = str(file_name.with_name(f"muted_{file_name.name}"))
+ if Path(output_file_name).exists():
+ return output_file_name
+ if wasm_utils.IS_WASM:
+ raise wasm_utils.WasmUnsupportedError(
+ "include_audio=False is not supported in the Wasm mode."
+ )
+ ff = FFmpeg(
+ inputs={str(file_name): None},
+ outputs={output_file_name: ["-an"]},
+ )
+ ff.run()
+ return output_file_name
+ else:
+ return str(file_name)
+
+ def postprocess(
+ self, y: str | Path | tuple[str | Path, str | Path | None] | None
+ ) -> VideoData | None:
+ if y is None or y == [None, None] or y == (None, None):
+ return None
+ if isinstance(y, (str, Path)):
+ processed_files = (self._format_video(y), None)
+
+ elif isinstance(y, (tuple, list)):
+ if len(y) != 2:
+ raise ValueError(
+ f"Expected lists of length 2 or tuples of length 2. Received: {y}"
+ )
+
+ if not (isinstance(y[0], (str, Path)) and isinstance(y[1], (str, Path))):
+ raise TypeError(
+ f"If a tuple is provided, both elements must be strings or Path objects. Received: {y}"
+ )
+ video = y[0]
+ subtitle = y[1]
+ processed_files = (
+ self._format_video(video),
+ self._format_subtitle(subtitle),
+ )
+
+ else:
+ raise Exception(f"Cannot process type as video: {type(y)}")
+ assert processed_files[0]
+ return VideoData(video=processed_files[0], subtitles=processed_files[1])
+
+ def _format_video(self, video: str | Path | None) -> FileData | None:
+ """
+ Processes a video to ensure that it is in the correct format.
+ """
+ if video is None:
+ return None
+ video = str(video)
+ returned_format = video.split(".")[-1].lower()
+ if self.format is None or returned_format == self.format:
+ conversion_needed = False
+ else:
+ conversion_needed = True
+
+ is_url = client_utils.is_http_url_like(video)
+
+ # For cases where the video is a URL and does not need to be converted to another format, we can just return the URL
+ if is_url and not (conversion_needed):
+ return FileData(path=video)
+
+ # For cases where the video needs to be converted to another format
+ if is_url:
+ video = processing_utils.save_url_to_cache(
+ video, cache_dir=self.GRADIO_CACHE
+ )
+ if (
+ processing_utils.ffmpeg_installed()
+ and not processing_utils.video_is_playable(video)
+ ):
+ warnings.warn(
+ "Video does not have browser-compatible container or codec. Converting to mp4"
+ )
+ video = processing_utils.convert_video_to_playable_mp4(video)
+ # Recalculate the format in case convert_video_to_playable_mp4 already made it the selected format
+ returned_format = utils.get_extension_from_file_path_or_url(video).lower()
+ if self.format is not None and returned_format != self.format:
+ if wasm_utils.IS_WASM:
+ raise wasm_utils.WasmUnsupportedError(
+ "Returning a video in a different format is not supported in the Wasm mode."
+ )
+ output_file_name = video[0 : video.rindex(".") + 1] + self.format
+ ff = FFmpeg(
+ inputs={video: None},
+ outputs={output_file_name: None},
+ global_options="-y",
+ )
+ ff.run()
+ video = output_file_name
+
+ return FileData(path=video, orig_name=Path(video).name)
+
+ def _format_subtitle(self, subtitle: str | Path | None) -> FileData | None:
+ """
+ Convert subtitle format to VTT and process the video to ensure it meets the HTML5 requirements.
+ """
+
+ def srt_to_vtt(srt_file_path, vtt_file_path):
+ """Convert an SRT subtitle file to a VTT subtitle file"""
+ with open(srt_file_path, encoding="utf-8") as srt_file, open(
+ vtt_file_path, "w", encoding="utf-8"
+ ) as vtt_file:
+ vtt_file.write("WEBVTT\n\n")
+ for subtitle_block in srt_file.read().strip().split("\n\n"):
+ subtitle_lines = subtitle_block.split("\n")
+ subtitle_timing = subtitle_lines[1].replace(",", ".")
+ subtitle_text = "\n".join(subtitle_lines[2:])
+ vtt_file.write(f"{subtitle_timing} --> {subtitle_timing}\n")
+ vtt_file.write(f"{subtitle_text}\n\n")
+
+ if subtitle is None:
+ return None
+
+ valid_extensions = (".srt", ".vtt")
+
+ if Path(subtitle).suffix not in valid_extensions:
+ raise ValueError(
+ f"Invalid value for parameter `subtitle`: {subtitle}. Please choose a file with one of these extensions: {valid_extensions}"
+ )
+
+ # HTML5 only support vtt format
+ if Path(subtitle).suffix == ".srt":
+ temp_file = tempfile.NamedTemporaryFile(
+ delete=False, suffix=".vtt", dir=self.GRADIO_CACHE
+ )
+
+ srt_to_vtt(subtitle, temp_file.name)
+ subtitle = temp_file.name
+
+ return FileData(path=str(subtitle))
+
+ def example_inputs(self) -> Any:
+ return "https://github.com/gradio-app/gradio/raw/main/demo/video_component/files/world.mp4"
diff --git a/gradio/context.py b/gradio/context.py
new file mode 100644
index 0000000000000000000000000000000000000000..9fb7fff8312ab2564714485c35940f2c77bd3f02
--- /dev/null
+++ b/gradio/context.py
@@ -0,0 +1,27 @@
+# Defines the Context class, which is used to store the state of all Blocks that are being rendered.
+
+from __future__ import annotations
+
+from contextvars import ContextVar
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from gradio.blocks import BlockContext, Blocks
+ from gradio.helpers import Progress
+ from gradio.routes import Request
+
+
+class Context:
+ root_block: Blocks | None = None # The current root block that holds all blocks.
+ block: BlockContext | None = None # The current block that children are added to.
+ id: int = 0 # Running id to uniquely refer to any block that gets defined
+ ip_address: str | None = None # The IP address of the user.
+ hf_token: str | None = None # The token provided when loading private HF repos
+
+
+class LocalContext:
+ blocks: ContextVar[Blocks | None] = ContextVar("blocks", default=None)
+ in_event_listener: ContextVar[bool] = ContextVar("in_event_listener", default=False)
+ event_id: ContextVar[str | None] = ContextVar("event_id", default=None)
+ request: ContextVar[Request | None] = ContextVar("request", default=None)
+ progress: ContextVar[Progress | None] = ContextVar("progress", default=None)
diff --git a/gradio/data_classes.py b/gradio/data_classes.py
new file mode 100644
index 0000000000000000000000000000000000000000..abbc898f17cc87c72477cf4ce6c514c949318753
--- /dev/null
+++ b/gradio/data_classes.py
@@ -0,0 +1,216 @@
+"""Pydantic data models and other dataclasses. This is the only file that uses Optional[]
+typing syntax instead of | None syntax to work with pydantic"""
+from __future__ import annotations
+
+import pathlib
+import secrets
+import shutil
+from abc import ABC, abstractmethod
+from enum import Enum, auto
+from typing import Any, List, Optional, Union
+
+from fastapi import Request
+from gradio_client.utils import traverse
+from typing_extensions import Literal
+
+from . import wasm_utils
+
+if not wasm_utils.IS_WASM:
+ from pydantic import BaseModel, RootModel, ValidationError # type: ignore
+else:
+ # XXX: Currently Pyodide V2 is not available on Pyodide,
+ # so we install V1 for the Wasm version.
+ from typing import Generic, TypeVar
+
+ from pydantic import BaseModel as BaseModelV1
+ from pydantic import ValidationError, schema_of
+
+ # Map V2 method calls to V1 implementations.
+ # Ref: https://docs.pydantic.dev/latest/migration/#changes-to-pydanticbasemodel
+ class BaseModel(BaseModelV1):
+ pass
+
+ BaseModel.model_dump = BaseModel.dict # type: ignore
+ BaseModel.model_json_schema = BaseModel.schema # type: ignore
+
+ # RootModel is not available in V1, so we create a dummy class.
+ PydanticUndefined = object()
+ RootModelRootType = TypeVar("RootModelRootType")
+
+ class RootModel(BaseModel, Generic[RootModelRootType]):
+ root: RootModelRootType
+
+ def __init__(self, root: RootModelRootType = PydanticUndefined, **data):
+ if data:
+ if root is not PydanticUndefined:
+ raise ValueError(
+ '"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments'
+ )
+ root = data # type: ignore
+ # XXX: No runtime validation is executed.
+ super().__init__(root=root) # type: ignore
+
+ def dict(self, **kwargs):
+ return super().dict(**kwargs)["root"]
+
+ @classmethod
+ def schema(cls, **kwargs):
+ # XXX: kwargs are ignored.
+ return schema_of(cls.__fields__["root"].type_) # type: ignore
+
+ RootModel.model_dump = RootModel.dict # type: ignore
+ RootModel.model_json_schema = RootModel.schema # type: ignore
+
+
+class PredictBody(BaseModel):
+ class Config:
+ arbitrary_types_allowed = True
+
+ session_hash: Optional[str] = None
+ event_id: Optional[str] = None
+ data: List[Any]
+ event_data: Optional[Any] = None
+ fn_index: Optional[int] = None
+ trigger_id: Optional[int] = None
+ batched: Optional[
+ bool
+ ] = False # Whether the data is a batch of samples (i.e. called from the queue if batch=True) or a single sample (i.e. called from the UI)
+ request: Optional[
+ Request
+ ] = None # dictionary of request headers, query parameters, url, etc. (used to to pass in request for queuing)
+
+
+class ResetBody(BaseModel):
+ event_id: str
+
+
+class ComponentServerBody(BaseModel):
+ session_hash: str
+ component_id: int
+ fn_name: str
+ data: Any
+
+
+class InterfaceTypes(Enum):
+ STANDARD = auto()
+ INPUT_ONLY = auto()
+ OUTPUT_ONLY = auto()
+ UNIFIED = auto()
+
+
+class Estimation(BaseModel):
+ rank: Optional[int] = None
+ queue_size: int
+ rank_eta: Optional[float] = None
+
+
+class ProgressUnit(BaseModel):
+ index: Optional[int] = None
+ length: Optional[int] = None
+ unit: Optional[str] = None
+ progress: Optional[float] = None
+ desc: Optional[str] = None
+
+
+class Progress(BaseModel):
+ progress_data: List[ProgressUnit] = []
+
+
+class LogMessage(BaseModel):
+ log: str
+ level: Literal["info", "warning"]
+
+
+class GradioBaseModel(ABC):
+ def copy_to_dir(self, dir: str | pathlib.Path) -> GradioDataModel:
+ assert isinstance(self, (BaseModel, RootModel))
+ if isinstance(dir, str):
+ dir = pathlib.Path(dir)
+
+ # TODO: Making sure path is unique should be done in caller
+ def unique_copy(obj: dict):
+ data = FileData(**obj)
+ return data._copy_to_dir(
+ str(pathlib.Path(dir / secrets.token_hex(10)))
+ ).model_dump()
+
+ return self.__class__.from_json(
+ x=traverse(
+ self.model_dump(),
+ unique_copy,
+ FileData.is_file_data,
+ )
+ )
+
+ @classmethod
+ @abstractmethod
+ def from_json(cls, x) -> GradioDataModel:
+ pass
+
+
+class GradioModel(GradioBaseModel, BaseModel):
+ @classmethod
+ def from_json(cls, x) -> GradioModel:
+ return cls(**x)
+
+
+class GradioRootModel(GradioBaseModel, RootModel):
+ @classmethod
+ def from_json(cls, x) -> GradioRootModel:
+ return cls(root=x)
+
+
+GradioDataModel = Union[GradioModel, GradioRootModel]
+
+
+class FileData(GradioModel):
+ path: str # server filepath
+ url: Optional[str] = None # normalised server url
+ size: Optional[int] = None # size in bytes
+ orig_name: Optional[str] = None # original filename
+ mime_type: Optional[str] = None
+
+ @property
+ def is_none(self):
+ return all(
+ f is None
+ for f in [
+ self.path,
+ self.url,
+ self.size,
+ self.orig_name,
+ self.mime_type,
+ ]
+ )
+
+ @classmethod
+ def from_path(cls, path: str) -> FileData:
+ return cls(path=path)
+
+ def _copy_to_dir(self, dir: str) -> FileData:
+ pathlib.Path(dir).mkdir(exist_ok=True)
+ new_obj = dict(self)
+
+ assert self.path
+ new_name = shutil.copy(self.path, dir)
+ new_obj["path"] = new_name
+ return self.__class__(**new_obj)
+
+ @classmethod
+ def is_file_data(cls, obj: Any):
+ if isinstance(obj, dict):
+ try:
+ return not FileData(**obj).is_none
+ except (TypeError, ValidationError):
+ return False
+ return False
+
+
+class ListFiles(GradioRootModel):
+ root: List[FileData]
+
+ def __getitem__(self, index):
+ return self.root[index]
+
+ def __iter__(self):
+ return iter(self.root)
diff --git a/gradio/deploy_space_action.yaml b/gradio/deploy_space_action.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..74f4cbdbde13728e57729531ca5de692b8521b69
--- /dev/null
+++ b/gradio/deploy_space_action.yaml
@@ -0,0 +1,28 @@
+name: Run Python script
+
+on:
+ push:
+ branches:
+ - $branch
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.9'
+
+ - name: Install Gradio
+ run: python -m pip install gradio
+
+ - name: Log in to Hugging Face
+ run: python -c 'import huggingface_hub; huggingface_hub.login(token="${{ secrets.hf_token }}")'
+
+ - name: Deploy to Spaces
+ run: gradio deploy
diff --git a/gradio/events.py b/gradio/events.py
new file mode 100644
index 0000000000000000000000000000000000000000..751f82b9c6db0375b2aababdd3158adeeed6a2fc
--- /dev/null
+++ b/gradio/events.py
@@ -0,0 +1,535 @@
+"""Contains all of the events that can be triggered in a gr.Blocks() app, with the exception
+of the on-page-load event, which is defined in gr.Blocks().load()."""
+
+from __future__ import annotations
+
+import dataclasses
+from functools import partial, wraps
+from typing import TYPE_CHECKING, Any, Callable, Literal, Sequence
+
+from gradio_client.documentation import document
+from jinja2 import Template
+
+if TYPE_CHECKING:
+ from gradio.blocks import Block, Component
+
+from gradio.context import Context
+from gradio.utils import get_cancel_function
+
+
+def set_cancel_events(
+ triggers: Sequence[EventListenerMethod],
+ cancels: None | dict[str, Any] | list[dict[str, Any]],
+):
+ if cancels:
+ if not isinstance(cancels, list):
+ cancels = [cancels]
+ cancel_fn, fn_indices_to_cancel = get_cancel_function(cancels)
+
+ if Context.root_block is None:
+ raise AttributeError("Cannot cancel outside of a gradio.Blocks context.")
+
+ Context.root_block.set_event_trigger(
+ triggers,
+ cancel_fn,
+ inputs=None,
+ outputs=None,
+ queue=False,
+ preprocess=False,
+ show_api=False,
+ cancels=fn_indices_to_cancel,
+ )
+
+
+class Dependency(dict):
+ def __init__(self, trigger, key_vals, dep_index, fn):
+ super().__init__(key_vals)
+ self.fn = fn
+ self.then = partial(
+ EventListener(
+ "then",
+ trigger_after=dep_index,
+ trigger_only_on_success=False,
+ has_trigger=False,
+ ).listener,
+ trigger,
+ )
+ """
+ Triggered after directly preceding event is completed, regardless of success or failure.
+ """
+ self.success = partial(
+ EventListener(
+ "success",
+ trigger_after=dep_index,
+ trigger_only_on_success=True,
+ has_trigger=False,
+ ).listener,
+ trigger,
+ )
+ """
+ Triggered after directly preceding event is completed, if it was successful.
+ """
+
+ def __call__(self, *args, **kwargs):
+ return self.fn(*args, **kwargs)
+
+
+@document()
+class EventData:
+ """
+ When a subclass of EventData is added as a type hint to an argument of an event listener method, this object will be passed as that argument.
+ It contains information about the event that triggered the listener, such the target object, and other data related to the specific event that are attributes of the subclass.
+
+ Example:
+ table = gr.Dataframe([[1, 2, 3], [4, 5, 6]])
+ gallery = gr.Gallery([("cat.jpg", "Cat"), ("dog.jpg", "Dog")])
+ textbox = gr.Textbox("Hello World!")
+
+ statement = gr.Textbox()
+
+ def on_select(evt: gr.SelectData): # SelectData is a subclass of EventData
+ return f"You selected {evt.value} at {evt.index} from {evt.target}"
+
+ table.select(on_select, None, statement)
+ gallery.select(on_select, None, statement)
+ textbox.select(on_select, None, statement)
+ Demos: gallery_selections, tictactoe
+ """
+
+ def __init__(self, target: Block | None, _data: Any):
+ """
+ Parameters:
+ target: The target object that triggered the event. Can be used to distinguish if multiple components are bound to the same listener.
+ """
+ self.target = target
+ self._data = _data
+
+
+class SelectData(EventData):
+ def __init__(self, target: Block | None, data: Any):
+ super().__init__(target, data)
+ self.index: int | tuple[int, int] = data["index"]
+ """
+ The index of the selected item. Is a tuple if the component is two dimensional or selection is a range.
+ """
+ self.value: Any = data["value"]
+ """
+ The value of the selected item.
+ """
+ self.selected: bool = data.get("selected", True)
+ """
+ True if the item was selected, False if deselected.
+ """
+
+
+@dataclasses.dataclass
+class EventListenerMethod:
+ block: Block | None
+ event_name: str
+
+
+class EventListener(str):
+ def __new__(cls, event_name, *args, **kwargs):
+ return super().__new__(cls, event_name)
+
+ def __init__(
+ self,
+ event_name: str,
+ has_trigger: bool = True,
+ config_data: Callable[..., dict[str, Any]] = lambda: {},
+ show_progress: Literal["full", "minimal", "hidden"] = "full",
+ callback: Callable | None = None,
+ trigger_after: int | None = None,
+ trigger_only_on_success: bool = False,
+ doc: str = "",
+ ):
+ super().__init__()
+ self.has_trigger = has_trigger
+ self.config_data = config_data
+ self.event_name = event_name
+ self.show_progress = show_progress
+ self.trigger_after = trigger_after
+ self.trigger_only_on_success = trigger_only_on_success
+ self.callback = callback
+ self.doc = doc
+ self.listener = self._setup(
+ event_name,
+ has_trigger,
+ show_progress,
+ callback,
+ trigger_after,
+ trigger_only_on_success,
+ )
+ if doc and self.listener.__doc__:
+ self.listener.__doc__ = doc + self.listener.__doc__
+
+ def set_doc(self, component: str):
+ if self.listener.__doc__:
+ doc = Template(self.listener.__doc__).render(component=component)
+ self.listener.__doc__ = doc
+
+ def copy(self):
+ return EventListener(
+ self.event_name,
+ self.has_trigger,
+ self.config_data,
+ self.show_progress, # type: ignore
+ self.callback,
+ self.trigger_after,
+ self.trigger_only_on_success,
+ self.doc,
+ )
+
+ @staticmethod
+ def _setup(
+ _event_name: str,
+ _has_trigger: bool,
+ _show_progress: Literal["full", "minimal", "hidden"],
+ _callback: Callable | None,
+ _trigger_after: int | None,
+ _trigger_only_on_success: bool,
+ ):
+ def event_trigger(
+ block: Block | None,
+ fn: Callable | None | Literal["decorator"] = "decorator",
+ inputs: Component | list[Component] | set[Component] | None = None,
+ outputs: Component | list[Component] | None = None,
+ api_name: str | None | Literal[False] = None,
+ scroll_to_output: bool = False,
+ show_progress: Literal["full", "minimal", "hidden"] = _show_progress,
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ cancels: dict[str, Any] | list[dict[str, Any]] | None = None,
+ every: float | None = None,
+ trigger_mode: Literal["once", "multiple", "always_last"] | None = None,
+ js: str | None = None,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ concurrency_id: str | None = None,
+ show_api: bool = True,
+ ) -> Dependency:
+ """
+ Parameters:
+ fn: the function to call when this event is triggered. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: List of gradio.components to use as inputs. If the function takes no inputs, this should be an empty list.
+ outputs: List of gradio.components to use as outputs. If the function returns no outputs, this should be an empty list.
+ api_name: defines how the endpoint appears in the API docs. Can be a string, None, or False. If set to a string, the endpoint will be exposed in the API docs with the given name. If None (default), the name of the function will be used as the API endpoint. If False, the endpoint will not be exposed in the API docs and downstream apps (including those that `gr.load` this app) will not be able to use this event.
+ scroll_to_output: If True, will scroll to output component on completion
+ show_progress: If True, will show progress animation while pending
+ queue: If True, will place the request on the queue, if the queue has been enabled. If False, will not put this event on the queue, even if the queue has been enabled. If None, will use the queue setting of the gradio app.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ preprocess: If False, will not run preprocessing of component data before running 'fn' (e.g. leaving it as a base64 string if this method is called with the `Image` component).
+ postprocess: If False, will not run postprocessing of component data before returning 'fn' output to the browser.
+ cancels: A list of other events to cancel when this listener is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method. Functions that have not yet run (or generators that are iterating) will be cancelled, but functions that are currently running will be allowed to finish.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ trigger_mode: If "once" (default for all events except `.change()`) would not allow any submissions while an event is pending. If set to "multiple", unlimited submissions are allowed while pending, and "always_last" (default for `.change()` event) would allow a second submission after the pending event is complete.
+ js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ concurrency_limit: If set, this is the maximum number of this event that can be running simultaneously. Can be set to None to mean no concurrency_limit (any number of this event can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `Blocks.queue()`, which itself is 1 by default).
+ concurrency_id: If set, this is the id of the concurrency group. Events with the same concurrency_id will be limited by the lowest set concurrency_limit.
+ show_api: whether to show this event in the "view API" page of the Gradio app, or in the ".view_api()" method of the Gradio clients. Unlike setting api_name to False, setting show_api to False will still allow downstream apps to use this event. If fn is None, show_api will automatically be set to False.
+ """
+
+ if fn == "decorator":
+
+ def wrapper(func):
+ event_trigger(
+ block=block,
+ fn=func,
+ inputs=inputs,
+ outputs=outputs,
+ api_name=api_name,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ cancels=cancels,
+ every=every,
+ trigger_mode=trigger_mode,
+ js=js,
+ concurrency_limit=concurrency_limit,
+ concurrency_id=concurrency_id,
+ show_api=show_api,
+ )
+
+ @wraps(func)
+ def inner(*args, **kwargs):
+ return func(*args, **kwargs)
+
+ return inner
+
+ return Dependency(None, {}, None, wrapper)
+
+ from gradio.components.base import StreamingInput
+
+ if isinstance(block, StreamingInput) and "stream" in block.events:
+ block.check_streamable() # type: ignore
+ if isinstance(show_progress, bool):
+ show_progress = "full" if show_progress else "hidden"
+
+ if Context.root_block is None:
+ raise AttributeError(
+ f"Cannot call {_event_name} outside of a gradio.Blocks context."
+ )
+
+ dep, dep_index = Context.root_block.set_event_trigger(
+ [EventListenerMethod(block if _has_trigger else None, _event_name)],
+ fn,
+ inputs,
+ outputs,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress,
+ api_name=api_name,
+ js=js,
+ concurrency_limit=concurrency_limit,
+ concurrency_id=concurrency_id,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ every=every,
+ trigger_after=_trigger_after,
+ trigger_only_on_success=_trigger_only_on_success,
+ trigger_mode=trigger_mode,
+ show_api=show_api,
+ )
+ set_cancel_events(
+ [EventListenerMethod(block if _has_trigger else None, _event_name)],
+ cancels,
+ )
+ if _callback:
+ _callback(block)
+ return Dependency(block, dep, dep_index, fn)
+
+ event_trigger.event_name = _event_name
+ event_trigger.has_trigger = _has_trigger
+ return event_trigger
+
+
+def on(
+ triggers: Sequence[Any] | Any | None = None,
+ fn: Callable | None | Literal["decorator"] = "decorator",
+ inputs: Component | list[Component] | set[Component] | None = None,
+ outputs: Component | list[Component] | None = None,
+ *,
+ api_name: str | None | Literal[False] = None,
+ scroll_to_output: bool = False,
+ show_progress: Literal["full", "minimal", "hidden"] = "full",
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ cancels: dict[str, Any] | list[dict[str, Any]] | None = None,
+ every: float | None = None,
+ js: str | None = None,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ concurrency_id: str | None = None,
+ show_api: bool = True,
+) -> Dependency:
+ """
+ Parameters:
+ triggers: List of triggers to listen to, e.g. [btn.click, number.change]. If None, will listen to changes to any inputs.
+ fn: the function to call when this event is triggered. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: List of gradio.components to use as inputs. If the function takes no inputs, this should be an empty list.
+ outputs: List of gradio.components to use as outputs. If the function returns no outputs, this should be an empty list.
+ api_name: Defines how the endpoint appears in the API docs. Can be a string, None, or False. If False, the endpoint will not be exposed in the api docs. If set to None, the endpoint will be exposed in the api docs as an unnamed endpoint, although this behavior will be changed in Gradio 4.0. If set to a string, the endpoint will be exposed in the api docs with the given name.
+ scroll_to_output: If True, will scroll to output component on completion
+ show_progress: If True, will show progress animation while pending
+ queue: If True, will place the request on the queue, if the queue has been enabled. If False, will not put this event on the queue, even if the queue has been enabled. If None, will use the queue setting of the gradio app.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ preprocess: If False, will not run preprocessing of component data before running 'fn' (e.g. leaving it as a base64 string if this method is called with the `Image` component).
+ postprocess: If False, will not run postprocessing of component data before returning 'fn' output to the browser.
+ cancels: A list of other events to cancel when this listener is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method. Functions that have not yet run (or generators that are iterating) will be cancelled, but functions that are currently running will be allowed to finish.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs', return should be a list of values for output components.
+ concurrency_limit: If set, this is the maximum number of this event that can be running simultaneously. Can be set to None to mean no concurrency_limit (any number of this event can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `Blocks.queue()`, which itself is 1 by default).
+ concurrency_id: If set, this is the id of the concurrency group. Events with the same concurrency_id will be limited by the lowest set concurrency_limit.
+ show_api: whether to show this event in the "view API" page of the Gradio app, or in the ".view_api()" method of the Gradio clients. Unlike setting api_name to False, setting show_api to False will still allow downstream apps to use this event. If fn is None, show_api will automatically be set to False.
+ """
+ from gradio.components.base import Component
+
+ if isinstance(triggers, EventListener):
+ triggers = [triggers]
+ if isinstance(inputs, Component):
+ inputs = [inputs]
+
+ if fn == "decorator":
+
+ def wrapper(func):
+ on(
+ triggers,
+ fn=func,
+ inputs=inputs,
+ outputs=outputs,
+ api_name=api_name,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ cancels=cancels,
+ every=every,
+ js=js,
+ concurrency_limit=concurrency_limit,
+ concurrency_id=concurrency_id,
+ show_api=show_api,
+ )
+
+ @wraps(func)
+ def inner(*args, **kwargs):
+ return func(*args, **kwargs)
+
+ return inner
+
+ return Dependency(None, {}, None, wrapper)
+
+ if Context.root_block is None:
+ raise Exception("Cannot call on() outside of a gradio.Blocks context.")
+ if triggers is None:
+ triggers = (
+ [EventListenerMethod(input, "change") for input in inputs]
+ if inputs is not None
+ else []
+ ) # type: ignore
+ else:
+ triggers = [
+ EventListenerMethod(t.__self__ if t.has_trigger else None, t.event_name)
+ for t in triggers
+ ] # type: ignore
+ dep, dep_index = Context.root_block.set_event_trigger(
+ triggers,
+ fn,
+ inputs,
+ outputs,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress,
+ api_name=api_name,
+ js=js,
+ concurrency_limit=concurrency_limit,
+ concurrency_id=concurrency_id,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ every=every,
+ show_api=show_api,
+ )
+ set_cancel_events(triggers, cancels)
+ return Dependency(None, dep, dep_index, fn)
+
+
+class Events:
+ change = EventListener(
+ "change",
+ doc="Triggered when the value of the {{ component }} changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.",
+ )
+ input = EventListener(
+ "input",
+ doc="This listener is triggered when the user changes the value of the {{ component }}.",
+ )
+ click = EventListener("click", doc="Triggered when the {{ component }} is clicked.")
+ submit = EventListener(
+ "submit",
+ doc="This listener is triggered when the user presses the Enter key while the {{ component }} is focused.",
+ )
+ edit = EventListener(
+ "edit",
+ doc="This listener is triggered when the user edits the {{ component }} (e.g. image) using the built-in editor.",
+ )
+ clear = EventListener(
+ "clear",
+ doc="This listener is triggered when the user clears the {{ component }} using the X button for the component.",
+ )
+ play = EventListener(
+ "play",
+ doc="This listener is triggered when the user plays the media in the {{ component }}.",
+ )
+ pause = EventListener(
+ "pause",
+ doc="This listener is triggered when the media in the {{ component }} stops for any reason.",
+ )
+ stop = EventListener(
+ "stop",
+ doc="This listener is triggered when the user reaches the end of the media playing in the {{ component }}.",
+ )
+ end = EventListener(
+ "end",
+ doc="This listener is triggered when the user reaches the end of the media playing in the {{ component }}.",
+ )
+ start_recording = EventListener(
+ "start_recording",
+ doc="This listener is triggered when the user starts recording with the {{ component }}.",
+ )
+ pause_recording = EventListener(
+ "pause_recording",
+ doc="This listener is triggered when the user pauses recording with the {{ component }}.",
+ )
+ stop_recording = EventListener(
+ "stop_recording",
+ doc="This listener is triggered when the user stops recording with the {{ component }}.",
+ )
+ focus = EventListener(
+ "focus", doc="This listener is triggered when the {{ component }} is focused."
+ )
+ blur = EventListener(
+ "blur",
+ doc="This listener is triggered when the {{ component }} is unfocused/blurred.",
+ )
+ upload = EventListener(
+ "upload",
+ doc="This listener is triggered when the user uploads a file into the {{ component }}.",
+ )
+ release = EventListener(
+ "release",
+ doc="This listener is triggered when the user releases the mouse on this {{ component }}.",
+ )
+ select = EventListener(
+ "select",
+ callback=lambda block: setattr(block, "_selectable", True),
+ doc="Event listener for when the user selects or deselects the {{ component }}. Uses event data gradio.SelectData to carry `value` referring to the label of the {{ component }}, and `selected` to refer to state of the {{ component }}. See EventData documentation on how to use this event data",
+ )
+ stream = EventListener(
+ "stream",
+ show_progress="hidden",
+ config_data=lambda: {"streamable": False},
+ callback=lambda block: setattr(block, "streaming", True),
+ doc="This listener is triggered when the user streams the {{ component }}.",
+ )
+ like = EventListener(
+ "like",
+ config_data=lambda: {"likeable": False},
+ callback=lambda block: setattr(block, "likeable", True),
+ doc="This listener is triggered when the user likes/dislikes from within the {{ component }}. This event has EventData of type gradio.LikeData that carries information, accessible through LikeData.index and LikeData.value. See EventData documentation on how to use this event data.",
+ )
+ load = EventListener(
+ "load",
+ doc="This listener is triggered when the {{ component }} initially loads in the browser.",
+ )
+
+
+class LikeData(EventData):
+ def __init__(self, target: Block | None, data: Any):
+ super().__init__(target, data)
+ self.index: int | tuple[int, int] = data["index"]
+ """
+ The index of the liked/disliked item. Is a tuple if the component is two dimensional.
+ """
+ self.value: Any = data["value"]
+ """
+ The value of the liked/disliked item.
+ """
+ self.liked: bool = data.get("liked", True)
+ """
+ True if the item was liked, False if disliked.
+ """
diff --git a/gradio/exceptions.py b/gradio/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..b337cd8db43a18fdac50254b528731a4898d0aa9
--- /dev/null
+++ b/gradio/exceptions.py
@@ -0,0 +1,93 @@
+from gradio_client.documentation import document, set_documentation_group
+
+set_documentation_group("helpers")
+
+
+class DuplicateBlockError(ValueError):
+ """Raised when a Blocks contains more than one Block with the same id"""
+
+ pass
+
+
+class InvalidComponentError(ValueError):
+ """Raised when invalid components are used."""
+
+ pass
+
+
+class TooManyRequestsError(Exception):
+ """Raised when the Hugging Face API returns a 429 status code."""
+
+ pass
+
+
+class ModelNotFoundError(Exception):
+ """Raised when the provided model doesn't exists or is not found by the provided api url."""
+
+ pass
+
+
+class RenderError(Exception):
+ """Raised when a component has not been rendered in the current Blocks but is expected to have been rendered."""
+
+ pass
+
+
+class InvalidApiNameError(ValueError):
+ pass
+
+
+class ServerFailedToStartError(Exception):
+ pass
+
+
+class InvalidBlockError(ValueError):
+ """Raised when an event in a Blocks contains a reference to a Block that is not in the original Blocks"""
+
+ pass
+
+
+class ReloadError(ValueError):
+ """Raised when something goes wrong when reloading the gradio app."""
+
+ pass
+
+
+class GradioVersionIncompatibleError(Exception):
+ """Raised when loading a 3.x space with 4.0"""
+
+ pass
+
+
+InvalidApiName = InvalidApiNameError # backwards compatibility
+
+set_documentation_group("modals")
+
+
+@document()
+class Error(Exception):
+ """
+ This class allows you to pass custom error messages to the user. You can do so by raising a gr.Error("custom message") anywhere in the code, and when that line is executed the custom message will appear in a modal on the demo.
+ Example:
+ import gradio as gr
+ def divide(numerator, denominator):
+ if denominator == 0:
+ raise gr.Error("Cannot divide by zero!")
+ gr.Interface(divide, ["number", "number"], "number").launch()
+ Demos: calculator, blocks_chained_events
+ """
+
+ def __init__(self, message: str = "Error raised."):
+ """
+ Parameters:
+ message: The error message to be displayed to the user.
+ """
+ self.message = message
+ super().__init__(self.message)
+
+ def __str__(self):
+ return repr(self.message)
+
+
+class ComponentDefinitionError(NotImplementedError):
+ pass
diff --git a/gradio/external.py b/gradio/external.py
new file mode 100644
index 0000000000000000000000000000000000000000..44f4e6afb942f7b0add2ca24a23dbdc8b855ea7f
--- /dev/null
+++ b/gradio/external.py
@@ -0,0 +1,592 @@
+"""This module should not be used directly as its API is subject to change. Instead,
+use the `gr.Blocks.load()` or `gr.load()` functions."""
+
+from __future__ import annotations
+
+import json
+import os
+import re
+import tempfile
+import warnings
+from pathlib import Path
+from typing import TYPE_CHECKING, Callable
+
+import httpx
+from gradio_client import Client
+from gradio_client import utils as client_utils
+from gradio_client.client import Endpoint
+from gradio_client.documentation import document, set_documentation_group
+from packaging import version
+
+import gradio
+from gradio import components, utils
+from gradio.context import Context
+from gradio.exceptions import (
+ Error,
+ GradioVersionIncompatibleError,
+ ModelNotFoundError,
+ TooManyRequestsError,
+)
+from gradio.external_utils import (
+ cols_to_rows,
+ encode_to_base64,
+ get_tabular_examples,
+ postprocess_label,
+ rows_to_cols,
+ streamline_spaces_interface,
+)
+from gradio.processing_utils import extract_base64_data, save_base64_to_cache, to_binary
+
+if TYPE_CHECKING:
+ from gradio.blocks import Blocks
+ from gradio.interface import Interface
+
+
+set_documentation_group("helpers")
+
+
+@document()
+def load(
+ name: str,
+ src: str | None = None,
+ hf_token: str | None = None,
+ alias: str | None = None,
+ **kwargs,
+) -> Blocks:
+ """
+ Method that constructs a Blocks from a Hugging Face repo. Can accept
+ model repos (if src is "models") or Space repos (if src is "spaces"). The input
+ and output components are automatically loaded from the repo.
+ Parameters:
+ name: the name of the model (e.g. "gpt2" or "facebook/bart-base") or space (e.g. "flax-community/spanish-gpt2"), can include the `src` as prefix (e.g. "models/facebook/bart-base")
+ src: the source of the model: `models` or `spaces` (or leave empty if source is provided as a prefix in `name`)
+ hf_token: optional access token for loading private Hugging Face Hub models or spaces. Find your token here: https://huggingface.co/settings/tokens. Warning: only provide this if you are loading a trusted private Space as it can be read by the Space you are loading.
+ alias: optional string used as the name of the loaded model instead of the default name (only applies if loading a Space running Gradio 2.x)
+ Returns:
+ a Gradio Blocks object for the given model
+ Example:
+ import gradio as gr
+ demo = gr.load("gradio/question-answering", src="spaces")
+ demo.launch()
+ """
+ return load_blocks_from_repo(
+ name=name, src=src, hf_token=hf_token, alias=alias, **kwargs
+ )
+
+
+def load_blocks_from_repo(
+ name: str,
+ src: str | None = None,
+ hf_token: str | None = None,
+ alias: str | None = None,
+ **kwargs,
+) -> Blocks:
+ """Creates and returns a Blocks instance from a Hugging Face model or Space repo."""
+ if src is None:
+ # Separate the repo type (e.g. "model") from repo name (e.g. "google/vit-base-patch16-224")
+ tokens = name.split("/")
+ if len(tokens) <= 1:
+ raise ValueError(
+ "Either `src` parameter must be provided, or `name` must be formatted as {src}/{repo name}"
+ )
+ src = tokens[0]
+ name = "/".join(tokens[1:])
+
+ factory_methods: dict[str, Callable] = {
+ # for each repo type, we have a method that returns the Interface given the model name & optionally an hf_token
+ "huggingface": from_model,
+ "models": from_model,
+ "spaces": from_spaces,
+ }
+ if src.lower() not in factory_methods:
+ raise ValueError(f"parameter: src must be one of {factory_methods.keys()}")
+
+ if hf_token is not None:
+ if Context.hf_token is not None and Context.hf_token != hf_token:
+ warnings.warn(
+ """You are loading a model/Space with a different access token than the one you used to load a previous model/Space. This is not recommended, as it may cause unexpected behavior."""
+ )
+ Context.hf_token = hf_token
+
+ blocks: gradio.Blocks = factory_methods[src](name, hf_token, alias, **kwargs)
+ return blocks
+
+
+def chatbot_preprocess(text, state):
+ payload = {
+ "inputs": {"generated_responses": None, "past_user_inputs": None, "text": text}
+ }
+ if state is not None:
+ payload["inputs"]["generated_responses"] = state["conversation"][
+ "generated_responses"
+ ]
+ payload["inputs"]["past_user_inputs"] = state["conversation"][
+ "past_user_inputs"
+ ]
+
+ return payload
+
+
+def chatbot_postprocess(response):
+ response_json = response.json()
+ chatbot_value = list(
+ zip(
+ response_json["conversation"]["past_user_inputs"],
+ response_json["conversation"]["generated_responses"],
+ )
+ )
+ return chatbot_value, response_json
+
+
+def from_model(model_name: str, hf_token: str | None, alias: str | None, **kwargs):
+ model_url = f"https://huggingface.co/{model_name}"
+ api_url = f"https://api-inference.huggingface.co/models/{model_name}"
+ print(f"Fetching model from: {model_url}")
+
+ headers = {"Authorization": f"Bearer {hf_token}"} if hf_token is not None else {}
+
+ # Checking if model exists, and if so, it gets the pipeline
+ response = httpx.request("GET", api_url, headers=headers)
+ if response.status_code != 200:
+ raise ModelNotFoundError(
+ f"Could not find model: {model_name}. If it is a private or gated model, please provide your Hugging Face access token (https://huggingface.co/settings/tokens) as the argument for the `hf_token` parameter."
+ )
+ p = response.json().get("pipeline_tag")
+ GRADIO_CACHE = os.environ.get("GRADIO_TEMP_DIR") or str( # noqa: N806
+ Path(tempfile.gettempdir()) / "gradio"
+ )
+
+ pipelines = {
+ "audio-classification": {
+ # example model: ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition
+ "inputs": components.Audio(
+ sources=["upload"], type="filepath", label="Input", render=False
+ ),
+ "outputs": components.Label(label="Class", render=False),
+ "preprocess": lambda i: to_binary,
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()}
+ ),
+ },
+ "audio-to-audio": {
+ # example model: facebook/xm_transformer_sm_all-en
+ "inputs": components.Audio(
+ sources=["upload"], type="filepath", label="Input", render=False
+ ),
+ "outputs": components.Audio(label="Output", render=False),
+ "preprocess": to_binary,
+ "postprocess": lambda x: save_base64_to_cache(
+ encode_to_base64(x), cache_dir=GRADIO_CACHE, file_name="output.wav"
+ ),
+ },
+ "automatic-speech-recognition": {
+ # example model: facebook/wav2vec2-base-960h
+ "inputs": components.Audio(
+ sources=["upload"], type="filepath", label="Input", render=False
+ ),
+ "outputs": components.Textbox(label="Output", render=False),
+ "preprocess": to_binary,
+ "postprocess": lambda r: r.json()["text"],
+ },
+ "conversational": {
+ "inputs": [
+ components.Textbox(render=False),
+ components.State(render=False),
+ ], # type: ignore
+ "outputs": [
+ components.Chatbot(render=False),
+ components.State(render=False),
+ ], # type: ignore
+ "preprocess": chatbot_preprocess,
+ "postprocess": chatbot_postprocess,
+ },
+ "feature-extraction": {
+ # example model: julien-c/distilbert-feature-extraction
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Dataframe(label="Output", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0],
+ },
+ "fill-mask": {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: postprocess_label(
+ {i["token_str"]: i["score"] for i in r.json()}
+ ),
+ },
+ "image-classification": {
+ # Example: google/vit-base-patch16-224
+ "inputs": components.Image(
+ type="filepath", label="Input Image", render=False
+ ),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": to_binary,
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()}
+ ),
+ },
+ "question-answering": {
+ # Example: deepset/xlm-roberta-base-squad2
+ "inputs": [
+ components.Textbox(lines=7, label="Context", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": [
+ components.Textbox(label="Answer", render=False),
+ components.Label(label="Score", render=False),
+ ],
+ "preprocess": lambda c, q: {"inputs": {"context": c, "question": q}},
+ "postprocess": lambda r: (r.json()["answer"], {"label": r.json()["score"]}),
+ },
+ "summarization": {
+ # Example: facebook/bart-large-cnn
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Summary", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["summary_text"],
+ },
+ "text-classification": {
+ # Example: distilbert-base-uncased-finetuned-sst-2-english
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()[0]}
+ ),
+ },
+ "text-generation": {
+ # Example: gpt2
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Output", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ "text2text-generation": {
+ # Example: valhalla/t5-small-qa-qg-hl
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Generated Text", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ "translation": {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Translation", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["translation_text"],
+ },
+ "zero-shot-classification": {
+ # Example: facebook/bart-large-mnli
+ "inputs": [
+ components.Textbox(label="Input", render=False),
+ components.Textbox(
+ label="Possible class names (" "comma-separated)", render=False
+ ),
+ components.Checkbox(label="Allow multiple true classes", render=False),
+ ],
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda i, c, m: {
+ "inputs": i,
+ "parameters": {"candidate_labels": c, "multi_class": m},
+ },
+ "postprocess": lambda r: postprocess_label(
+ {
+ r.json()["labels"][i]: r.json()["scores"][i]
+ for i in range(len(r.json()["labels"]))
+ }
+ ),
+ },
+ "sentence-similarity": {
+ # Example: sentence-transformers/distilbert-base-nli-stsb-mean-tokens
+ "inputs": [
+ components.Textbox(
+ value="That is a happy person",
+ label="Source Sentence",
+ render=False,
+ ),
+ components.Textbox(
+ lines=7,
+ placeholder="Separate each sentence by a newline",
+ label="Sentences to compare to",
+ render=False,
+ ),
+ ],
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda src, sentences: {
+ "inputs": {
+ "source_sentence": src,
+ "sentences": [s for s in sentences.splitlines() if s != ""],
+ }
+ },
+ "postprocess": lambda r: postprocess_label(
+ {f"sentence {i}": v for i, v in enumerate(r.json())}
+ ),
+ },
+ "text-to-speech": {
+ # Example: julien-c/ljspeech_tts_train_tacotron2_raw_phn_tacotron_g2p_en_no_space_train
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Audio(label="Audio", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda x: save_base64_to_cache(
+ encode_to_base64(x), cache_dir=GRADIO_CACHE, file_name="output.wav"
+ ),
+ },
+ "text-to-image": {
+ # example model: osanseviero/BigGAN-deep-128
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Image(label="Output", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda x: save_base64_to_cache(
+ encode_to_base64(x), cache_dir=GRADIO_CACHE, file_name="output.jpg"
+ ),
+ },
+ "token-classification": {
+ # example model: huggingface-course/bert-finetuned-ner
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.HighlightedText(label="Output", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r, # Handled as a special case in query_huggingface_api()
+ },
+ "document-question-answering": {
+ # example model: impira/layoutlm-document-qa
+ "inputs": [
+ components.Image(type="filepath", label="Input Document", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": components.Label(label="Label", render=False),
+ "preprocess": lambda img, q: {
+ "inputs": {
+ "image": extract_base64_data(
+ client_utils.encode_url_or_file_to_base64(img["path"])
+ ), # Extract base64 data
+ "question": q,
+ }
+ },
+ "postprocess": lambda r: postprocess_label(
+ {i["answer"]: i["score"] for i in r.json()}
+ ),
+ },
+ "visual-question-answering": {
+ # example model: dandelin/vilt-b32-finetuned-vqa
+ "inputs": [
+ components.Image(type="filepath", label="Input Image", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": components.Label(label="Label", render=False),
+ "preprocess": lambda img, q: {
+ "inputs": {
+ "image": extract_base64_data(
+ client_utils.encode_url_or_file_to_base64(img["path"])
+ ),
+ "question": q,
+ }
+ },
+ "postprocess": lambda r: postprocess_label(
+ {i["answer"]: i["score"] for i in r.json()}
+ ),
+ },
+ "image-to-text": {
+ # example model: Salesforce/blip-image-captioning-base
+ "inputs": components.Image(
+ type="filepath", label="Input Image", render=False
+ ),
+ "outputs": components.Textbox(label="Generated Text", render=False),
+ "preprocess": to_binary,
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ }
+
+ if p in ["tabular-classification", "tabular-regression"]:
+ example_data = get_tabular_examples(model_name)
+ col_names, example_data = cols_to_rows(example_data)
+ example_data = [[example_data]] if example_data else None
+
+ pipelines[p] = {
+ "inputs": components.Dataframe(
+ label="Input Rows",
+ type="pandas",
+ headers=col_names,
+ col_count=(len(col_names), "fixed"),
+ render=False,
+ ),
+ "outputs": components.Dataframe(
+ label="Predictions", type="array", headers=["prediction"], render=False
+ ),
+ "preprocess": rows_to_cols,
+ "postprocess": lambda r: {
+ "headers": ["prediction"],
+ "data": [[pred] for pred in json.loads(r.text)],
+ },
+ "examples": example_data,
+ }
+
+ if p is None or p not in pipelines:
+ raise ValueError(f"Unsupported pipeline type: {p}")
+
+ pipeline = pipelines[p]
+
+ def query_huggingface_api(*params):
+ # Convert to a list of input components
+ data = pipeline["preprocess"](*params)
+ if isinstance(
+ data, dict
+ ): # HF doesn't allow additional parameters for binary files (e.g. images or audio files)
+ data.update({"options": {"wait_for_model": True}})
+ data = json.dumps(data)
+ response = httpx.request("POST", api_url, headers=headers, data=data) # type: ignore
+ if response.status_code != 200:
+ errors_json = response.json()
+ errors, warns = "", ""
+ if errors_json.get("error"):
+ errors = f", Error: {errors_json.get('error')}"
+ if errors_json.get("warnings"):
+ warns = f", Warnings: {errors_json.get('warnings')}"
+ raise Error(
+ f"Could not complete request to HuggingFace API, Status Code: {response.status_code}"
+ + errors
+ + warns
+ )
+ if (
+ p == "token-classification"
+ ): # Handle as a special case since HF API only returns the named entities and we need the input as well
+ ner_groups = response.json()
+ input_string = params[0]
+ response = utils.format_ner_list(input_string, ner_groups)
+ output = pipeline["postprocess"](response)
+ return output
+
+ if alias is None:
+ query_huggingface_api.__name__ = model_name
+ else:
+ query_huggingface_api.__name__ = alias
+
+ interface_info = {
+ "fn": query_huggingface_api,
+ "inputs": pipeline["inputs"],
+ "outputs": pipeline["outputs"],
+ "title": model_name,
+ "examples": pipeline.get("examples"),
+ }
+
+ kwargs = dict(interface_info, **kwargs)
+
+ # So interface doesn't run pre/postprocess
+ # except for conversational interfaces which
+ # are stateful
+ kwargs["_api_mode"] = p != "conversational"
+
+ interface = gradio.Interface(**kwargs)
+ return interface
+
+
+def from_spaces(
+ space_name: str, hf_token: str | None, alias: str | None, **kwargs
+) -> Blocks:
+ space_url = f"https://huggingface.co/spaces/{space_name}"
+
+ print(f"Fetching Space from: {space_url}")
+
+ headers = {}
+ if hf_token is not None:
+ headers["Authorization"] = f"Bearer {hf_token}"
+
+ iframe_url = (
+ httpx.get(
+ f"https://huggingface.co/api/spaces/{space_name}/host", headers=headers
+ )
+ .json()
+ .get("host")
+ )
+
+ if iframe_url is None:
+ raise ValueError(
+ f"Could not find Space: {space_name}. If it is a private or gated Space, please provide your Hugging Face access token (https://huggingface.co/settings/tokens) as the argument for the `hf_token` parameter."
+ )
+
+ r = httpx.get(iframe_url, headers=headers)
+
+ result = re.search(
+ r"window.gradio_config = (.*?);[\s]*", r.text
+ ) # some basic regex to extract the config
+ try:
+ config = json.loads(result.group(1)) # type: ignore
+ except AttributeError as ae:
+ raise ValueError(f"Could not load the Space: {space_name}") from ae
+ if "allow_flagging" in config: # Create an Interface for Gradio 2.x Spaces
+ return from_spaces_interface(
+ space_name, config, alias, hf_token, iframe_url, **kwargs
+ )
+ else: # Create a Blocks for Gradio 3.x Spaces
+ if kwargs:
+ warnings.warn(
+ "You cannot override parameters for this Space by passing in kwargs. "
+ "Instead, please load the Space as a function and use it to create a "
+ "Blocks or Interface locally. You may find this Guide helpful: "
+ "https://gradio.app/using_blocks_like_functions/"
+ )
+ return from_spaces_blocks(space=space_name, hf_token=hf_token)
+
+
+def from_spaces_blocks(space: str, hf_token: str | None) -> Blocks:
+ client = Client(space, hf_token=hf_token)
+ if client.app_version < version.Version("4.0.0b14"):
+ raise GradioVersionIncompatibleError(
+ f"Gradio version 4.x cannot load spaces with versions less than 4.x ({client.app_version})."
+ "Please downgrade to version 3 to load this space."
+ )
+ # Use end_to_end_fn here to properly upload/download all files
+ predict_fns = []
+ for fn_index, endpoint in enumerate(client.endpoints):
+ assert isinstance(endpoint, Endpoint)
+ helper = client.new_helper(fn_index)
+ if endpoint.backend_fn:
+ predict_fns.append(endpoint.make_end_to_end_fn(helper))
+ else:
+ predict_fns.append(None)
+ return gradio.Blocks.from_config(client.config, predict_fns, client.src)
+
+
+def from_spaces_interface(
+ model_name: str,
+ config: dict,
+ alias: str | None,
+ hf_token: str | None,
+ iframe_url: str,
+ **kwargs,
+) -> Interface:
+ config = streamline_spaces_interface(config)
+ api_url = f"{iframe_url}/api/predict/"
+ headers = {"Content-Type": "application/json"}
+ if hf_token is not None:
+ headers["Authorization"] = f"Bearer {hf_token}"
+
+ # The function should call the API with preprocessed data
+ def fn(*data):
+ data = json.dumps({"data": data})
+ response = httpx.post(api_url, headers=headers, data=data) # type: ignore
+ result = json.loads(response.content.decode("utf-8"))
+ if "error" in result and "429" in result["error"]:
+ raise TooManyRequestsError("Too many requests to the Hugging Face API")
+ try:
+ output = result["data"]
+ except KeyError as ke:
+ raise KeyError(
+ f"Could not find 'data' key in response from external Space. Response received: {result}"
+ ) from ke
+ if (
+ len(config["outputs"]) == 1
+ ): # if the fn is supposed to return a single value, pop it
+ output = output[0]
+ if (
+ len(config["outputs"]) == 1 and isinstance(output, list)
+ ): # Needed to support Output.Image() returning bounding boxes as well (TODO: handle different versions of gradio since they have slightly different APIs)
+ output = output[0]
+ return output
+
+ fn.__name__ = alias if (alias is not None) else model_name
+ config["fn"] = fn
+
+ kwargs = dict(config, **kwargs)
+ kwargs["_api_mode"] = True
+ interface = gradio.Interface(**kwargs)
+ return interface
diff --git a/gradio/external_utils.py b/gradio/external_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..b46ffcac5269ee07b2f209e62f1307f592afded7
--- /dev/null
+++ b/gradio/external_utils.py
@@ -0,0 +1,140 @@
+"""Utility function for gradio/external.py"""
+
+import base64
+import math
+import operator
+import re
+import warnings
+from typing import Dict, List, Tuple
+
+import httpx
+import yaml
+
+from gradio import components
+
+##################
+# Helper functions for processing tabular data
+##################
+
+
+def get_tabular_examples(model_name: str) -> Dict[str, List[float]]:
+ readme = httpx.get(f"https://huggingface.co/{model_name}/resolve/main/README.md")
+ if readme.status_code != 200:
+ warnings.warn(f"Cannot load examples from README for {model_name}", UserWarning)
+ example_data = {}
+ else:
+ yaml_regex = re.search(
+ "(?:^|[\r\n])---[\n\r]+([\\S\\s]*?)[\n\r]+---([\n\r]|$)", readme.text
+ )
+ if yaml_regex is None:
+ example_data = {}
+ else:
+ example_yaml = next(
+ yaml.safe_load_all(readme.text[: yaml_regex.span()[-1]])
+ )
+ example_data = example_yaml.get("widget", {}).get("structuredData", {})
+ if not example_data:
+ raise ValueError(
+ f"No example data found in README.md of {model_name} - Cannot build gradio demo. "
+ "See the README.md here: https://huggingface.co/scikit-learn/tabular-playground/blob/main/README.md "
+ "for a reference on how to provide example data to your model."
+ )
+ # replace nan with string NaN for inference API
+ for data in example_data.values():
+ for i, val in enumerate(data):
+ if isinstance(val, float) and math.isnan(val):
+ data[i] = "NaN"
+ return example_data
+
+
+def cols_to_rows(
+ example_data: Dict[str, List[float]],
+) -> Tuple[List[str], List[List[float]]]:
+ headers = list(example_data.keys())
+ n_rows = max(len(example_data[header] or []) for header in headers)
+ data = []
+ for row_index in range(n_rows):
+ row_data = []
+ for header in headers:
+ col = example_data[header] or []
+ if row_index >= len(col):
+ row_data.append("NaN")
+ else:
+ row_data.append(col[row_index])
+ data.append(row_data)
+ return headers, data
+
+
+def rows_to_cols(incoming_data: Dict) -> Dict[str, Dict[str, Dict[str, List[str]]]]:
+ data_column_wise = {}
+ for i, header in enumerate(incoming_data["headers"]):
+ data_column_wise[header] = [str(row[i]) for row in incoming_data["data"]]
+ return {"inputs": {"data": data_column_wise}}
+
+
+##################
+# Helper functions for processing other kinds of data
+##################
+
+
+def postprocess_label(scores: Dict) -> Dict:
+ sorted_pred = sorted(scores.items(), key=operator.itemgetter(1), reverse=True)
+ return {
+ "label": sorted_pred[0][0],
+ "confidences": [
+ {"label": pred[0], "confidence": pred[1]} for pred in sorted_pred
+ ],
+ }
+
+
+def encode_to_base64(r: httpx.Response) -> str:
+ # Handles the different ways HF API returns the prediction
+ base64_repr = base64.b64encode(r.content).decode("utf-8")
+ data_prefix = ";base64,"
+ # Case 1: base64 representation already includes data prefix
+ if data_prefix in base64_repr:
+ return base64_repr
+ else:
+ content_type = r.headers.get("content-type")
+ # Case 2: the data prefix is a key in the response
+ if content_type == "application/json":
+ try:
+ data = r.json()[0]
+ content_type = data["content-type"]
+ base64_repr = data["blob"]
+ except KeyError as ke:
+ raise ValueError(
+ "Cannot determine content type returned by external API."
+ ) from ke
+ # Case 3: the data prefix is included in the response headers
+ else:
+ pass
+ new_base64 = f"data:{content_type};base64,{base64_repr}"
+ return new_base64
+
+
+##################
+# Helper function for cleaning up an Interface loaded from HF Spaces
+##################
+
+
+def streamline_spaces_interface(config: Dict) -> Dict:
+ """Streamlines the interface config dictionary to remove unnecessary keys."""
+ config["inputs"] = [
+ components.get_component_instance(component)
+ for component in config["input_components"]
+ ]
+ config["outputs"] = [
+ components.get_component_instance(component)
+ for component in config["output_components"]
+ ]
+ parameters = {
+ "article",
+ "description",
+ "flagging_options",
+ "inputs",
+ "outputs",
+ "title",
+ }
+ config = {k: config[k] for k in parameters}
+ return config
diff --git a/gradio/flagging.py b/gradio/flagging.py
new file mode 100644
index 0000000000000000000000000000000000000000..4f45057bc534e8760a562a129aa5c5d68d644a98
--- /dev/null
+++ b/gradio/flagging.py
@@ -0,0 +1,493 @@
+from __future__ import annotations
+
+import csv
+import datetime
+import json
+import os
+import time
+import uuid
+from abc import ABC, abstractmethod
+from collections import OrderedDict
+from pathlib import Path
+from typing import TYPE_CHECKING, Any
+
+import filelock
+import huggingface_hub
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+
+import gradio as gr
+from gradio import utils
+
+if TYPE_CHECKING:
+ from gradio.components import Component
+
+set_documentation_group("flagging")
+
+
+class FlaggingCallback(ABC):
+ """
+ An abstract class for defining the methods that any FlaggingCallback should have.
+ """
+
+ @abstractmethod
+ def setup(self, components: list[Component], flagging_dir: str):
+ """
+ This method should be overridden and ensure that everything is set up correctly for flag().
+ This method gets called once at the beginning of the Interface.launch() method.
+ Parameters:
+ components: Set of components that will provide flagged data.
+ flagging_dir: A string, typically containing the path to the directory where the flagging file should be stored (provided as an argument to Interface.__init__()).
+ """
+ pass
+
+ @abstractmethod
+ def flag(
+ self,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ """
+ This method should be overridden by the FlaggingCallback subclass and may contain optional additional arguments.
+ This gets called every time the button is pressed.
+ Parameters:
+ interface: The Interface object that is being used to launch the flagging interface.
+ flag_data: The data to be flagged.
+ flag_option (optional): In the case that flagging_options are provided, the flag option that is being used.
+ username (optional): The username of the user that is flagging the data, if logged in.
+ Returns:
+ (int) The total number of samples that have been flagged.
+ """
+ pass
+
+
+@document()
+class SimpleCSVLogger(FlaggingCallback):
+ """
+ A simplified implementation of the FlaggingCallback abstract class
+ provided for illustrative purposes. Each flagged sample (both the input and output data)
+ is logged to a CSV file on the machine running the gradio app.
+ Example:
+ import gradio as gr
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ flagging_callback=SimpleCSVLogger())
+ """
+
+ def __init__(self):
+ pass
+
+ def setup(self, components: list[Component], flagging_dir: str | Path):
+ self.components = components
+ self.flagging_dir = flagging_dir
+ os.makedirs(flagging_dir, exist_ok=True)
+
+ def flag(
+ self,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ flagging_dir = self.flagging_dir
+ log_filepath = Path(flagging_dir) / "log.csv"
+
+ csv_data = []
+ for component, sample in zip(self.components, flag_data):
+ save_dir = Path(
+ flagging_dir
+ ) / client_utils.strip_invalid_filename_characters(component.label or "")
+ save_dir.mkdir(exist_ok=True)
+ csv_data.append(
+ component.flag(
+ sample,
+ save_dir,
+ )
+ )
+
+ with open(log_filepath, "a", newline="") as csvfile:
+ writer = csv.writer(csvfile)
+ writer.writerow(utils.sanitize_list_for_csv(csv_data))
+
+ with open(log_filepath) as csvfile:
+ line_count = len(list(csv.reader(csvfile))) - 1
+ return line_count
+
+
+@document()
+class CSVLogger(FlaggingCallback):
+ """
+ The default implementation of the FlaggingCallback abstract class. Each flagged
+ sample (both the input and output data) is logged to a CSV file with headers on the machine running the gradio app.
+ Example:
+ import gradio as gr
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ flagging_callback=CSVLogger())
+ Guides: using-flagging
+ """
+
+ def __init__(self):
+ pass
+
+ def setup(
+ self,
+ components: list[Component],
+ flagging_dir: str | Path,
+ ):
+ self.components = components
+ self.flagging_dir = flagging_dir
+ os.makedirs(flagging_dir, exist_ok=True)
+
+ def flag(
+ self,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ flagging_dir = self.flagging_dir
+ log_filepath = Path(flagging_dir) / "log.csv"
+ is_new = not Path(log_filepath).exists()
+ headers = [
+ getattr(component, "label", None) or f"component {idx}"
+ for idx, component in enumerate(self.components)
+ ] + [
+ "flag",
+ "username",
+ "timestamp",
+ ]
+
+ csv_data = []
+ for idx, (component, sample) in enumerate(zip(self.components, flag_data)):
+ save_dir = Path(
+ flagging_dir
+ ) / client_utils.strip_invalid_filename_characters(
+ getattr(component, "label", None) or f"component {idx}"
+ )
+ if utils.is_update(sample):
+ csv_data.append(str(sample))
+ else:
+ csv_data.append(
+ component.flag(sample, flag_dir=save_dir)
+ if sample is not None
+ else ""
+ )
+ csv_data.append(flag_option)
+ csv_data.append(username if username is not None else "")
+ csv_data.append(str(datetime.datetime.now()))
+
+ with open(log_filepath, "a", newline="", encoding="utf-8") as csvfile:
+ writer = csv.writer(csvfile)
+ if is_new:
+ writer.writerow(utils.sanitize_list_for_csv(headers))
+ writer.writerow(utils.sanitize_list_for_csv(csv_data))
+
+ with open(log_filepath, encoding="utf-8") as csvfile:
+ line_count = len(list(csv.reader(csvfile))) - 1
+ return line_count
+
+
+@document()
+class HuggingFaceDatasetSaver(FlaggingCallback):
+ """
+ A callback that saves each flagged sample (both the input and output data) to a HuggingFace dataset.
+
+ Example:
+ import gradio as gr
+ hf_writer = gr.HuggingFaceDatasetSaver(HF_API_TOKEN, "image-classification-mistakes")
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ allow_flagging="manual", flagging_callback=hf_writer)
+ Guides: using-flagging
+ """
+
+ def __init__(
+ self,
+ hf_token: str,
+ dataset_name: str,
+ private: bool = False,
+ info_filename: str = "dataset_info.json",
+ separate_dirs: bool = False,
+ ):
+ """
+ Parameters:
+ hf_token: The HuggingFace token to use to create (and write the flagged sample to) the HuggingFace dataset (defaults to the registered one).
+ dataset_name: The repo_id of the dataset to save the data to, e.g. "image-classifier-1" or "username/image-classifier-1".
+ private: Whether the dataset should be private (defaults to False).
+ info_filename: The name of the file to save the dataset info (defaults to "dataset_infos.json").
+ separate_dirs: If True, each flagged item will be saved in a separate directory. This makes the flagging more robust to concurrent editing, but may be less convenient to use.
+ """
+ self.hf_token = hf_token
+ self.dataset_id = dataset_name # TODO: rename parameter (but ensure backward compatibility somehow)
+ self.dataset_private = private
+ self.info_filename = info_filename
+ self.separate_dirs = separate_dirs
+
+ def setup(self, components: list[Component], flagging_dir: str):
+ """
+ Params:
+ flagging_dir (str): local directory where the dataset is cloned,
+ updated, and pushed from.
+ """
+ # Setup dataset on the Hub
+ self.dataset_id = huggingface_hub.create_repo(
+ repo_id=self.dataset_id,
+ token=self.hf_token,
+ private=self.dataset_private,
+ repo_type="dataset",
+ exist_ok=True,
+ ).repo_id
+ path_glob = "**/*.jsonl" if self.separate_dirs else "data.csv"
+ huggingface_hub.metadata_update(
+ repo_id=self.dataset_id,
+ repo_type="dataset",
+ metadata={
+ "configs": [
+ {
+ "config_name": "default",
+ "data_files": [{"split": "train", "path": path_glob}],
+ }
+ ]
+ },
+ overwrite=True,
+ token=self.hf_token,
+ )
+
+ # Setup flagging dir
+ self.components = components
+ self.dataset_dir = (
+ Path(flagging_dir).absolute() / self.dataset_id.split("/")[-1]
+ )
+ self.dataset_dir.mkdir(parents=True, exist_ok=True)
+ self.infos_file = self.dataset_dir / self.info_filename
+
+ # Download remote files to local
+ remote_files = [self.info_filename]
+ if not self.separate_dirs:
+ # No separate dirs => means all data is in the same CSV file => download it to get its current content
+ remote_files.append("data.csv")
+
+ for filename in remote_files:
+ try:
+ huggingface_hub.hf_hub_download(
+ repo_id=self.dataset_id,
+ repo_type="dataset",
+ filename=filename,
+ local_dir=self.dataset_dir,
+ token=self.hf_token,
+ )
+ except huggingface_hub.utils.EntryNotFoundError:
+ pass
+
+ def flag(
+ self,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ if self.separate_dirs:
+ # JSONL files to support dataset preview on the Hub
+ unique_id = str(uuid.uuid4())
+ components_dir = self.dataset_dir / unique_id
+ data_file = components_dir / "metadata.jsonl"
+ path_in_repo = unique_id # upload in sub folder (safer for concurrency)
+ else:
+ # Unique CSV file
+ components_dir = self.dataset_dir
+ data_file = components_dir / "data.csv"
+ path_in_repo = None # upload at root level
+
+ return self._flag_in_dir(
+ data_file=data_file,
+ components_dir=components_dir,
+ path_in_repo=path_in_repo,
+ flag_data=flag_data,
+ flag_option=flag_option,
+ username=username or "",
+ )
+
+ def _flag_in_dir(
+ self,
+ data_file: Path,
+ components_dir: Path,
+ path_in_repo: str | None,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str = "",
+ ) -> int:
+ # Deserialize components (write images/audio to files)
+ features, row = self._deserialize_components(
+ components_dir, flag_data, flag_option, username
+ )
+
+ # Write generic info to dataset_infos.json + upload
+ with filelock.FileLock(str(self.infos_file) + ".lock"):
+ if not self.infos_file.exists():
+ self.infos_file.write_text(
+ json.dumps({"flagged": {"features": features}})
+ )
+
+ huggingface_hub.upload_file(
+ repo_id=self.dataset_id,
+ repo_type="dataset",
+ token=self.hf_token,
+ path_in_repo=self.infos_file.name,
+ path_or_fileobj=self.infos_file,
+ )
+
+ headers = list(features.keys())
+
+ if not self.separate_dirs:
+ with filelock.FileLock(components_dir / ".lock"):
+ sample_nb = self._save_as_csv(data_file, headers=headers, row=row)
+ sample_name = str(sample_nb)
+ huggingface_hub.upload_folder(
+ repo_id=self.dataset_id,
+ repo_type="dataset",
+ commit_message=f"Flagged sample #{sample_name}",
+ path_in_repo=path_in_repo,
+ ignore_patterns="*.lock",
+ folder_path=components_dir,
+ token=self.hf_token,
+ )
+ else:
+ sample_name = self._save_as_jsonl(data_file, headers=headers, row=row)
+ sample_nb = len(
+ [path for path in self.dataset_dir.iterdir() if path.is_dir()]
+ )
+ huggingface_hub.upload_folder(
+ repo_id=self.dataset_id,
+ repo_type="dataset",
+ commit_message=f"Flagged sample #{sample_name}",
+ path_in_repo=path_in_repo,
+ ignore_patterns="*.lock",
+ folder_path=components_dir,
+ token=self.hf_token,
+ )
+
+ return sample_nb
+
+ @staticmethod
+ def _save_as_csv(data_file: Path, headers: list[str], row: list[Any]) -> int:
+ """Save data as CSV and return the sample name (row number)."""
+ is_new = not data_file.exists()
+
+ with data_file.open("a", newline="", encoding="utf-8") as csvfile:
+ writer = csv.writer(csvfile)
+
+ # Write CSV headers if new file
+ if is_new:
+ writer.writerow(utils.sanitize_list_for_csv(headers))
+
+ # Write CSV row for flagged sample
+ writer.writerow(utils.sanitize_list_for_csv(row))
+
+ with data_file.open(encoding="utf-8") as csvfile:
+ return sum(1 for _ in csv.reader(csvfile)) - 1
+
+ @staticmethod
+ def _save_as_jsonl(data_file: Path, headers: list[str], row: list[Any]) -> str:
+ """Save data as JSONL and return the sample name (uuid)."""
+ Path.mkdir(data_file.parent, parents=True, exist_ok=True)
+ with open(data_file, "w") as f:
+ json.dump(dict(zip(headers, row)), f)
+ return data_file.parent.name
+
+ def _deserialize_components(
+ self,
+ data_dir: Path,
+ flag_data: list[Any],
+ flag_option: str = "",
+ username: str = "",
+ ) -> tuple[dict[Any, Any], list[Any]]:
+ """Deserialize components and return the corresponding row for the flagged sample.
+
+ Images/audio are saved to disk as individual files.
+ """
+ # Components that can have a preview on dataset repos
+ file_preview_types = {gr.Audio: "Audio", gr.Image: "Image"}
+
+ # Generate the row corresponding to the flagged sample
+ features = OrderedDict()
+ row = []
+ for component, sample in zip(self.components, flag_data):
+ # Get deserialized object (will save sample to disk if applicable -file, audio, image,...-)
+ label = component.label or ""
+ save_dir = data_dir / client_utils.strip_invalid_filename_characters(label)
+ save_dir.mkdir(exist_ok=True, parents=True)
+ deserialized = component.flag(sample, save_dir)
+
+ # Add deserialized object to row
+ features[label] = {"dtype": "string", "_type": "Value"}
+ try:
+ assert Path(deserialized).exists()
+ row.append(str(Path(deserialized).relative_to(self.dataset_dir)))
+ except (AssertionError, TypeError, ValueError):
+ deserialized = "" if deserialized is None else str(deserialized)
+ row.append(deserialized)
+
+ # If component is eligible for a preview, add the URL of the file
+ # Be mindful that images and audio can be None
+ if isinstance(component, tuple(file_preview_types)): # type: ignore
+ for _component, _type in file_preview_types.items():
+ if isinstance(component, _component):
+ features[label + " file"] = {"_type": _type}
+ break
+ if deserialized:
+ path_in_repo = str( # returned filepath is absolute, we want it relative to compute URL
+ Path(deserialized).relative_to(self.dataset_dir)
+ ).replace("\\", "/")
+ row.append(
+ huggingface_hub.hf_hub_url(
+ repo_id=self.dataset_id,
+ filename=path_in_repo,
+ repo_type="dataset",
+ )
+ )
+ else:
+ row.append("")
+ features["flag"] = {"dtype": "string", "_type": "Value"}
+ features["username"] = {"dtype": "string", "_type": "Value"}
+ row.append(flag_option)
+ row.append(username)
+ return features, row
+
+
+class FlagMethod:
+ """
+ Helper class that contains the flagging options and calls the flagging method. Also
+ provides visual feedback to the user when flag is clicked.
+ """
+
+ def __init__(
+ self,
+ flagging_callback: FlaggingCallback,
+ label: str,
+ value: str,
+ visual_feedback: bool = True,
+ ):
+ self.flagging_callback = flagging_callback
+ self.label = label
+ self.value = value
+ self.__name__ = "Flag"
+ self.visual_feedback = visual_feedback
+
+ def __call__(self, request: gr.Request, *flag_data):
+ try:
+ self.flagging_callback.flag(
+ list(flag_data), flag_option=self.value, username=request.username
+ )
+ except Exception as e:
+ print(f"Error while flagging: {e}")
+ if self.visual_feedback:
+ return "Error!"
+ if not self.visual_feedback:
+ return
+ time.sleep(0.8) # to provide enough time for the user to observe button change
+ return self.reset()
+
+ def reset(self):
+ return gr.Button(value=self.label, interactive=True)
diff --git a/gradio/helpers.py b/gradio/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..faf5bb3a900c8f89c0a24d236702afb2c45e4d42
--- /dev/null
+++ b/gradio/helpers.py
@@ -0,0 +1,1171 @@
+"""
+Defines helper methods useful for loading and caching Interface examples.
+"""
+from __future__ import annotations
+
+import ast
+import csv
+import inspect
+import os
+import shutil
+import subprocess
+import tempfile
+import warnings
+from functools import partial
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, Optional
+
+import matplotlib.pyplot as plt
+import numpy as np
+import PIL
+import PIL.Image
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+from matplotlib import animation
+
+from gradio import components, oauth, processing_utils, routes, utils, wasm_utils
+from gradio.context import Context, LocalContext
+from gradio.data_classes import GradioModel, GradioRootModel
+from gradio.events import EventData
+from gradio.exceptions import Error
+from gradio.flagging import CSVLogger
+
+if TYPE_CHECKING: # Only import for type checking (to avoid circular imports).
+ from gradio.components import Component
+
+LOG_FILE = "log.csv"
+
+set_documentation_group("helpers")
+
+
+def create_examples(
+ examples: list[Any] | list[list[Any]] | str,
+ inputs: Component | list[Component],
+ outputs: Component | list[Component] | None = None,
+ fn: Callable | None = None,
+ cache_examples: bool = False,
+ examples_per_page: int = 10,
+ _api_mode: bool = False,
+ label: str | None = None,
+ elem_id: str | None = None,
+ run_on_click: bool = False,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ api_name: str | Literal[False] = "load_example",
+ batch: bool = False,
+):
+ """Top-level synchronous function that creates Examples. Provided for backwards compatibility, i.e. so that gr.Examples(...) can be used to create the Examples component."""
+ examples_obj = Examples(
+ examples=examples,
+ inputs=inputs,
+ outputs=outputs,
+ fn=fn,
+ cache_examples=cache_examples,
+ examples_per_page=examples_per_page,
+ _api_mode=_api_mode,
+ label=label,
+ elem_id=elem_id,
+ run_on_click=run_on_click,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ api_name=api_name,
+ batch=batch,
+ _initiated_directly=False,
+ )
+ examples_obj.create()
+ return examples_obj
+
+
+@document()
+class Examples:
+ """
+ This class is a wrapper over the Dataset component and can be used to create Examples
+ for Blocks / Interfaces. Populates the Dataset component with examples and
+ assigns event listener so that clicking on an example populates the input/output
+ components. Optionally handles example caching for fast inference.
+
+ Demos: blocks_inputs, fake_gan
+ Guides: more-on-examples-and-flagging, using-hugging-face-integrations, image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers, create-your-own-friends-with-a-gan
+ """
+
+ def __init__(
+ self,
+ examples: list[Any] | list[list[Any]] | str,
+ inputs: Component | list[Component],
+ outputs: Component | list[Component] | None = None,
+ fn: Callable | None = None,
+ cache_examples: bool = False,
+ examples_per_page: int = 10,
+ _api_mode: bool = False,
+ label: str | None = "Examples",
+ elem_id: str | None = None,
+ run_on_click: bool = False,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ api_name: str | Literal[False] = "load_example",
+ batch: bool = False,
+ _initiated_directly: bool = True,
+ ):
+ """
+ Parameters:
+ examples: example inputs that can be clicked to populate specific components. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component. A string path to a directory of examples can also be provided but it should be within the directory with the python file running the gradio app. If there are multiple input components and a directory is provided, a log.csv file must be present in the directory to link corresponding inputs.
+ inputs: the component or list of components corresponding to the examples
+ outputs: optionally, provide the component or list of components corresponding to the output of the examples. Required if `cache_examples` is True.
+ fn: optionally, provide the function to run to generate the outputs corresponding to the examples. Required if `cache_examples` is True.
+ cache_examples: if True, caches examples for fast runtime. If True, then `fn` and `outputs` must be provided. If `fn` is a generator function, then the last yielded value will be used as the output.
+ examples_per_page: how many examples to show per page.
+ label: the label to use for the examples component (by default, "Examples")
+ elem_id: an optional string that is assigned as the id of this component in the HTML DOM.
+ run_on_click: if cache_examples is False, clicking on an example does not run the function when an example is clicked. Set this to True to run the function when an example is clicked. Has no effect if cache_examples is True.
+ preprocess: if True, preprocesses the example input before running the prediction function and caching the output. Only applies if `cache_examples` is True.
+ postprocess: if True, postprocesses the example output after running the prediction function and before caching. Only applies if `cache_examples` is True.
+ api_name: Defines how the event associated with clicking on the examples appears in the API docs. Can be a string or False. If set to a string, the endpoint will be exposed in the API docs with the given name. If False, the endpoint will not be exposed in the API docs and downstream apps (including those that `gr.load` this app) will not be able to use the example function.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. Used only if cache_examples is True.
+ """
+ if _initiated_directly:
+ warnings.warn(
+ "Please use gr.Examples(...) instead of gr.examples.Examples(...) to create the Examples.",
+ )
+
+ if cache_examples and (fn is None or outputs is None):
+ raise ValueError("If caching examples, `fn` and `outputs` must be provided")
+
+ if not isinstance(inputs, list):
+ inputs = [inputs]
+ if outputs and not isinstance(outputs, list):
+ outputs = [outputs]
+
+ working_directory = Path().absolute()
+
+ if examples is None:
+ raise ValueError("The parameter `examples` cannot be None")
+ elif isinstance(examples, list) and (
+ len(examples) == 0 or isinstance(examples[0], list)
+ ):
+ pass
+ elif (
+ isinstance(examples, list) and len(inputs) == 1
+ ): # If there is only one input component, examples can be provided as a regular list instead of a list of lists
+ examples = [[e] for e in examples]
+ elif isinstance(examples, str):
+ if not Path(examples).exists():
+ raise FileNotFoundError(
+ f"Could not find examples directory: {examples}"
+ )
+ working_directory = examples
+ if not (Path(examples) / LOG_FILE).exists():
+ if len(inputs) == 1:
+ examples = [[e] for e in os.listdir(examples)]
+ else:
+ raise FileNotFoundError(
+ "Could not find log file (required for multiple inputs): "
+ + LOG_FILE
+ )
+ else:
+ with open(Path(examples) / LOG_FILE) as logs:
+ examples = list(csv.reader(logs))
+ examples = [
+ examples[i][: len(inputs)] for i in range(1, len(examples))
+ ] # remove header and unnecessary columns
+
+ else:
+ raise ValueError(
+ "The parameter `examples` must either be a string directory or a list"
+ "(if there is only 1 input component) or (more generally), a nested "
+ "list, where each sublist represents a set of inputs."
+ )
+
+ input_has_examples = [False] * len(inputs)
+ for example in examples:
+ for idx, example_for_input in enumerate(example):
+ if example_for_input is not None:
+ try:
+ input_has_examples[idx] = True
+ except IndexError:
+ pass # If there are more example components than inputs, ignore. This can sometimes be intentional (e.g. loading from a log file where outputs and timestamps are also logged)
+
+ inputs_with_examples = [
+ inp for (inp, keep) in zip(inputs, input_has_examples) if keep
+ ]
+ non_none_examples = [
+ [ex for (ex, keep) in zip(example, input_has_examples) if keep]
+ for example in examples
+ ]
+
+ self.examples = examples
+ self.non_none_examples = non_none_examples
+ self.inputs = inputs
+ self.inputs_with_examples = inputs_with_examples
+ self.outputs = outputs or []
+ self.fn = fn
+ self.cache_examples = cache_examples
+ self._api_mode = _api_mode
+ self.preprocess = preprocess
+ self.postprocess = postprocess
+ self.api_name: str | Literal[False] = api_name
+ self.batch = batch
+
+ with utils.set_directory(working_directory):
+ self.processed_examples = []
+ for example in examples:
+ sub = []
+ for component, sample in zip(inputs, example):
+ prediction_value = component.postprocess(sample)
+ if isinstance(prediction_value, (GradioRootModel, GradioModel)):
+ prediction_value = prediction_value.model_dump()
+ prediction_value = processing_utils.move_files_to_cache(
+ prediction_value, component, postprocess=True
+ )
+ sub.append(prediction_value)
+ self.processed_examples.append(sub)
+
+ self.non_none_processed_examples = [
+ [ex for (ex, keep) in zip(example, input_has_examples) if keep]
+ for example in self.processed_examples
+ ]
+ if cache_examples:
+ for example in self.examples:
+ if len([ex for ex in example if ex is not None]) != len(self.inputs):
+ warnings.warn(
+ "Examples are being cached but not all input components have "
+ "example values. This may result in an exception being thrown by "
+ "your function. If you do get an error while caching examples, make "
+ "sure all of your inputs have example values for all of your examples "
+ "or you provide default values for those particular parameters in your function."
+ )
+ break
+
+ from gradio import components
+
+ with utils.set_directory(working_directory):
+ self.dataset = components.Dataset(
+ components=inputs_with_examples,
+ samples=non_none_examples,
+ type="index",
+ label=label,
+ samples_per_page=examples_per_page,
+ elem_id=elem_id,
+ )
+
+ self.cached_folder = utils.get_cache_folder() / str(self.dataset._id)
+ self.cached_file = Path(self.cached_folder) / "log.csv"
+ self.cache_examples = cache_examples
+ self.run_on_click = run_on_click
+
+ def create(self) -> None:
+ """Caches the examples if self.cache_examples is True and creates the Dataset
+ component to hold the examples"""
+
+ async def load_example(example_id):
+ processed_example = self.non_none_processed_examples[example_id]
+ if len(self.inputs_with_examples) == 1:
+ return update(
+ value=processed_example[0], **self.dataset.component_props[0]
+ )
+ return [
+ update(value=processed_example[i], **self.dataset.component_props[i])
+ for i in range(len(self.inputs_with_examples))
+ ]
+
+ if Context.root_block:
+ self.load_input_event = self.dataset.click(
+ load_example,
+ inputs=[self.dataset],
+ outputs=self.inputs_with_examples, # type: ignore
+ show_progress="hidden",
+ postprocess=False,
+ queue=False,
+ api_name=self.api_name,
+ show_api=False,
+ )
+ if self.run_on_click and not self.cache_examples:
+ if self.fn is None:
+ raise ValueError("Cannot run_on_click if no function is provided")
+ self.load_input_event.then(
+ self.fn,
+ inputs=self.inputs, # type: ignore
+ outputs=self.outputs, # type: ignore
+ show_api=False,
+ )
+
+ if self.cache_examples:
+ if wasm_utils.IS_WASM:
+ # In the Wasm mode, the `threading` module is not supported,
+ # so `client_utils.synchronize_async` is also not available.
+ # And `self.cache()` should be waited for to complete before this method returns,
+ # (otherwise, an error "Cannot cache examples if not in a Blocks context" will be raised anyway)
+ # so `eventloop.create_task(self.cache())` is also not an option.
+ raise wasm_utils.WasmUnsupportedError(
+ "Caching examples is not supported in the Wasm mode."
+ )
+ client_utils.synchronize_async(self.cache)
+
+ async def cache(self) -> None:
+ """
+ Caches all of the examples so that their predictions can be shown immediately.
+ """
+ if Context.root_block is None:
+ raise ValueError("Cannot cache examples if not in a Blocks context")
+ if Path(self.cached_file).exists():
+ print(
+ f"Using cache from '{utils.abspath(self.cached_folder)}' directory. If method or examples have changed since last caching, delete this folder to clear cache.\n"
+ )
+ else:
+ print(f"Caching examples at: '{utils.abspath(self.cached_folder)}'")
+ cache_logger = CSVLogger()
+
+ generated_values = []
+ if inspect.isgeneratorfunction(self.fn):
+
+ def get_final_item(*args): # type: ignore
+ x = None
+ generated_values.clear()
+ for x in self.fn(*args): # noqa: B007 # type: ignore
+ generated_values.append(x)
+ return x
+
+ fn = get_final_item
+ elif inspect.isasyncgenfunction(self.fn):
+
+ async def get_final_item(*args):
+ x = None
+ generated_values.clear()
+ async for x in self.fn(*args): # noqa: B007 # type: ignore
+ generated_values.append(x)
+ return x
+
+ fn = get_final_item
+ else:
+ fn = self.fn
+
+ # create a fake dependency to process the examples and get the predictions
+ from gradio.events import EventListenerMethod
+
+ dependency, fn_index = Context.root_block.set_event_trigger(
+ [EventListenerMethod(Context.root_block, "load")],
+ fn=fn,
+ inputs=self.inputs_with_examples, # type: ignore
+ outputs=self.outputs, # type: ignore
+ preprocess=self.preprocess and not self._api_mode,
+ postprocess=self.postprocess and not self._api_mode,
+ batch=self.batch,
+ )
+
+ assert self.outputs is not None
+ cache_logger.setup(self.outputs, self.cached_folder)
+ for example_id, _ in enumerate(self.examples):
+ print(f"Caching example {example_id + 1}/{len(self.examples)}")
+ processed_input = self.processed_examples[example_id]
+ if self.batch:
+ processed_input = [[value] for value in processed_input]
+ with utils.MatplotlibBackendMananger():
+ prediction = await Context.root_block.process_api(
+ fn_index=fn_index,
+ inputs=processed_input,
+ request=None,
+ )
+ output = prediction["data"]
+ if len(generated_values):
+ output = merge_generated_values_into_output(
+ self.outputs, generated_values, output
+ )
+
+ if self.batch:
+ output = [value[0] for value in output]
+ cache_logger.flag(output)
+ # Remove the "fake_event" to prevent bugs in loading interfaces from spaces
+ Context.root_block.dependencies.remove(dependency)
+ Context.root_block.fns.pop(fn_index)
+
+ # Remove the original load_input_event and replace it with one that
+ # also populates the input. We do it this way to to allow the cache()
+ # method to be called independently of the create() method
+ index = Context.root_block.dependencies.index(self.load_input_event)
+ Context.root_block.dependencies.pop(index)
+ Context.root_block.fns.pop(index)
+
+ def load_example(example_id):
+ processed_example = self.non_none_processed_examples[
+ example_id
+ ] + self.load_from_cache(example_id)
+ return utils.resolve_singleton(processed_example)
+
+ self.load_input_event = self.dataset.click(
+ load_example,
+ inputs=[self.dataset],
+ outputs=self.inputs_with_examples + self.outputs, # type: ignore
+ show_progress="hidden",
+ postprocess=False,
+ queue=False,
+ api_name=self.api_name,
+ show_api=False,
+ )
+
+ def load_from_cache(self, example_id: int) -> list[Any]:
+ """Loads a particular cached example for the interface.
+ Parameters:
+ example_id: The id of the example to process (zero-indexed).
+ """
+ with open(self.cached_file, encoding="utf-8") as cache:
+ examples = list(csv.reader(cache))
+ example = examples[example_id + 1] # +1 to adjust for header
+ output = []
+ assert self.outputs is not None
+ for component, value in zip(self.outputs, example):
+ value_to_use = value
+ try:
+ value_as_dict = ast.literal_eval(value)
+ # File components that output multiple files get saved as a python list
+ # need to pass the parsed list to serialize
+ # TODO: Better file serialization in 4.0
+ if isinstance(value_as_dict, list) and isinstance(
+ component, components.File
+ ):
+ value_to_use = value_as_dict
+ assert utils.is_update(value_as_dict)
+ output.append(value_as_dict)
+ except (ValueError, TypeError, SyntaxError, AssertionError):
+ output.append(
+ component.read_from_flag(
+ value_to_use,
+ self.cached_folder,
+ )
+ )
+ return output
+
+
+def merge_generated_values_into_output(
+ components: list[Component], generated_values: list, output: list
+):
+ from gradio.components.base import StreamingOutput
+
+ for output_index, output_component in enumerate(components):
+ if isinstance(output_component, StreamingOutput) and output_component.streaming:
+ binary_chunks = []
+ for i, chunk in enumerate(generated_values):
+ if len(components) > 1:
+ chunk = chunk[output_index]
+ processed_chunk = output_component.postprocess(chunk)
+ if isinstance(processed_chunk, (GradioModel, GradioRootModel)):
+ processed_chunk = processed_chunk.model_dump()
+ binary_chunks.append(
+ output_component.stream_output(processed_chunk, "", i == 0)[0]
+ )
+ binary_data = b"".join(binary_chunks)
+ tempdir = os.environ.get("GRADIO_TEMP_DIR") or str(
+ Path(tempfile.gettempdir()) / "gradio"
+ )
+ os.makedirs(tempdir, exist_ok=True)
+ temp_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
+ with open(temp_file.name, "wb") as f:
+ f.write(binary_data)
+
+ output[output_index] = {
+ "path": temp_file.name,
+ }
+
+ return output
+
+
+class TrackedIterable:
+ def __init__(
+ self,
+ iterable: Iterable | None,
+ index: int | None,
+ length: int | None,
+ desc: str | None,
+ unit: str | None,
+ _tqdm=None,
+ progress: float | None = None,
+ ) -> None:
+ self.iterable = iterable
+ self.index = index
+ self.length = length
+ self.desc = desc
+ self.unit = unit
+ self._tqdm = _tqdm
+ self.progress = progress
+
+
+@document("__call__", "tqdm")
+class Progress(Iterable):
+ """
+ The Progress class provides a custom progress tracker that is used in a function signature.
+ To attach a Progress tracker to a function, simply add a parameter right after the input parameters that has a default value set to a `gradio.Progress()` instance.
+ The Progress tracker can then be updated in the function by calling the Progress object or using the `tqdm` method on an Iterable.
+ The Progress tracker is currently only available with `queue()`.
+ Example:
+ import gradio as gr
+ import time
+ def my_function(x, progress=gr.Progress()):
+ progress(0, desc="Starting...")
+ time.sleep(1)
+ for i in progress.tqdm(range(100)):
+ time.sleep(0.1)
+ return x
+ gr.Interface(my_function, gr.Textbox(), gr.Textbox()).queue().launch()
+ Demos: progress
+ """
+
+ def __init__(
+ self,
+ track_tqdm: bool = False,
+ ):
+ """
+ Parameters:
+ track_tqdm: If True, the Progress object will track any tqdm.tqdm iterations with the tqdm library in the function.
+ """
+ if track_tqdm:
+ patch_tqdm()
+ self.track_tqdm = track_tqdm
+ self.iterables: list[TrackedIterable] = []
+
+ def __len__(self):
+ return self.iterables[-1].length
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Updates progress tracker with next item in iterable.
+ """
+ callback = self._progress_callback()
+ if callback:
+ current_iterable = self.iterables[-1]
+ while (
+ not hasattr(current_iterable.iterable, "__next__")
+ and len(self.iterables) > 0
+ ):
+ current_iterable = self.iterables.pop()
+ callback(self.iterables)
+ if current_iterable.index is None:
+ raise IndexError("Index not set.")
+ current_iterable.index += 1
+ try:
+ return next(current_iterable.iterable) # type: ignore
+ except StopIteration:
+ self.iterables.pop()
+ raise
+ else:
+ return self
+
+ def __call__(
+ self,
+ progress: float | tuple[int, int | None] | None,
+ desc: str | None = None,
+ total: int | None = None,
+ unit: str = "steps",
+ _tqdm=None,
+ ):
+ """
+ Updates progress tracker with progress and message text.
+ Parameters:
+ progress: If float, should be between 0 and 1 representing completion. If Tuple, first number represents steps completed, and second value represents total steps or None if unknown. If None, hides progress bar.
+ desc: description to display.
+ total: estimated total number of steps.
+ unit: unit of iterations.
+ """
+ callback = self._progress_callback()
+ if callback:
+ if isinstance(progress, tuple):
+ index, total = progress
+ progress = None
+ else:
+ index = None
+ callback(
+ self.iterables
+ + [TrackedIterable(None, index, total, desc, unit, _tqdm, progress)]
+ )
+ else:
+ return progress
+
+ def tqdm(
+ self,
+ iterable: Iterable | None,
+ desc: str | None = None,
+ total: int | None = None,
+ unit: str = "steps",
+ _tqdm=None,
+ ):
+ """
+ Attaches progress tracker to iterable, like tqdm.
+ Parameters:
+ iterable: iterable to attach progress tracker to.
+ desc: description to display.
+ total: estimated total number of steps.
+ unit: unit of iterations.
+ """
+ callback = self._progress_callback()
+ if callback:
+ if iterable is None:
+ new_iterable = TrackedIterable(None, 0, total, desc, unit, _tqdm)
+ self.iterables.append(new_iterable)
+ callback(self.iterables)
+ return self
+ length = len(iterable) if hasattr(iterable, "__len__") else None # type: ignore
+ self.iterables.append(
+ TrackedIterable(iter(iterable), 0, length, desc, unit, _tqdm)
+ )
+ return self
+
+ def update(self, n=1):
+ """
+ Increases latest iterable with specified number of steps.
+ Parameters:
+ n: number of steps completed.
+ """
+ callback = self._progress_callback()
+ if callback and len(self.iterables) > 0:
+ current_iterable = self.iterables[-1]
+ if current_iterable.index is None:
+ raise IndexError("Index not set.")
+ current_iterable.index += n
+ callback(self.iterables)
+ else:
+ return
+
+ def close(self, _tqdm):
+ """
+ Removes iterable with given _tqdm.
+ """
+ callback = self._progress_callback()
+ if callback:
+ for i in range(len(self.iterables)):
+ if id(self.iterables[i]._tqdm) == id(_tqdm):
+ self.iterables.pop(i)
+ break
+ callback(self.iterables)
+ else:
+ return
+
+ @staticmethod
+ def _progress_callback():
+ blocks = LocalContext.blocks.get()
+ event_id = LocalContext.event_id.get()
+ if not (blocks and event_id):
+ return None
+ return partial(blocks._queue.set_progress, event_id)
+
+
+def patch_tqdm() -> None:
+ try:
+ _tqdm = __import__("tqdm")
+ except ModuleNotFoundError:
+ return
+
+ def init_tqdm(
+ self, iterable=None, desc=None, total=None, unit="steps", *args, **kwargs
+ ):
+ self._progress = LocalContext.progress.get()
+ if self._progress is not None:
+ self._progress.tqdm(iterable, desc, total, unit, _tqdm=self)
+ kwargs["file"] = open(os.devnull, "w") # noqa: SIM115
+ self.__init__orig__(iterable, desc, total, *args, unit=unit, **kwargs)
+
+ def iter_tqdm(self):
+ if self._progress is not None:
+ return self._progress
+ return self.__iter__orig__()
+
+ def update_tqdm(self, n=1):
+ if self._progress is not None:
+ self._progress.update(n)
+ return self.__update__orig__(n)
+
+ def close_tqdm(self):
+ if self._progress is not None:
+ self._progress.close(self)
+ return self.__close__orig__()
+
+ def exit_tqdm(self, exc_type, exc_value, traceback):
+ if self._progress is not None:
+ self._progress.close(self)
+ return self.__exit__orig__(exc_type, exc_value, traceback)
+
+ # Backup
+ if not hasattr(_tqdm.tqdm, "__init__orig__"):
+ _tqdm.tqdm.__init__orig__ = _tqdm.tqdm.__init__
+ if not hasattr(_tqdm.tqdm, "__update__orig__"):
+ _tqdm.tqdm.__update__orig__ = _tqdm.tqdm.update
+ if not hasattr(_tqdm.tqdm, "__close__orig__"):
+ _tqdm.tqdm.__close__orig__ = _tqdm.tqdm.close
+ if not hasattr(_tqdm.tqdm, "__exit__orig__"):
+ _tqdm.tqdm.__exit__orig__ = _tqdm.tqdm.__exit__
+ if not hasattr(_tqdm.tqdm, "__iter__orig__"):
+ _tqdm.tqdm.__iter__orig__ = _tqdm.tqdm.__iter__
+
+ # Patch
+ _tqdm.tqdm.__init__ = init_tqdm
+ _tqdm.tqdm.update = update_tqdm
+ _tqdm.tqdm.close = close_tqdm
+ _tqdm.tqdm.__exit__ = exit_tqdm
+ _tqdm.tqdm.__iter__ = iter_tqdm
+
+ if hasattr(_tqdm, "auto") and hasattr(_tqdm.auto, "tqdm"):
+ _tqdm.auto.tqdm = _tqdm.tqdm
+
+
+def create_tracker(fn, track_tqdm):
+ progress = Progress(track_tqdm=track_tqdm)
+ if not track_tqdm:
+ return progress, fn
+ return progress, utils.function_wrapper(
+ f=fn,
+ before_fn=LocalContext.progress.set,
+ before_args=(progress,),
+ after_fn=LocalContext.progress.set,
+ after_args=(None,),
+ )
+
+
+def special_args(
+ fn: Callable,
+ inputs: list[Any] | None = None,
+ request: routes.Request | None = None,
+ event_data: EventData | None = None,
+) -> tuple[list, int | None, int | None]:
+ """
+ Checks if function has special arguments Request or EventData (via annotation) or Progress (via default value).
+ If inputs is provided, these values will be loaded into the inputs array.
+ Parameters:
+ fn: function to check.
+ inputs: array to load special arguments into.
+ request: request to load into inputs.
+ event_data: event-related data to load into inputs.
+ Returns:
+ updated inputs, progress index, event data index.
+ """
+ try:
+ signature = inspect.signature(fn)
+ except ValueError:
+ return inputs or [], None, None
+ type_hints = utils.get_type_hints(fn)
+ positional_args = []
+ for param in signature.parameters.values():
+ if param.kind not in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):
+ break
+ positional_args.append(param)
+ progress_index = None
+ event_data_index = None
+ for i, param in enumerate(positional_args):
+ type_hint = type_hints.get(param.name)
+ if isinstance(param.default, Progress):
+ progress_index = i
+ if inputs is not None:
+ inputs.insert(i, param.default)
+ elif type_hint == routes.Request:
+ if inputs is not None:
+ inputs.insert(i, request)
+ elif (
+ type_hint == Optional[oauth.OAuthProfile]
+ or type_hint == oauth.OAuthProfile
+ or type_hint == Optional[oauth.OAuthToken]
+ or type_hint == oauth.OAuthToken
+ # Note: "OAuthProfile | None" is equals to Optional[OAuthProfile] in Python
+ # => it is automatically handled as well by the above condition
+ # (adding explicit "OAuthProfile | None" would break in Python3.9)
+ # (same for "OAuthToken")
+ ):
+ if inputs is not None:
+ # Retrieve session from gr.Request, if it exists (i.e. if user is logged in)
+ session = (
+ # request.session (if fastapi.Request obj i.e. direct call)
+ getattr(request, "session", {})
+ or
+ # or request.request.session (if gr.Request obj i.e. websocket call)
+ getattr(getattr(request, "request", None), "session", {})
+ )
+
+ # Inject user profile
+ if (
+ type_hint == Optional[oauth.OAuthProfile]
+ or type_hint == oauth.OAuthProfile
+ ):
+ oauth_profile = (
+ session["oauth_info"]["userinfo"]
+ if "oauth_info" in session
+ else None
+ )
+ if oauth_profile is not None:
+ oauth_profile = oauth.OAuthProfile(oauth_profile)
+ elif type_hint == oauth.OAuthProfile:
+ raise Error(
+ "This action requires a logged in user. Please sign in and retry."
+ )
+ inputs.insert(i, oauth_profile)
+
+ # Inject user token
+ elif (
+ type_hint == Optional[oauth.OAuthToken]
+ or type_hint == oauth.OAuthToken
+ ):
+ oauth_info = (
+ session["oauth_info"] if "oauth_info" in session else None
+ )
+ oauth_token = (
+ oauth.OAuthToken(
+ token=oauth_info["access_token"],
+ scope=oauth_info["scope"],
+ expires_at=oauth_info["expires_at"],
+ )
+ if oauth_info is not None
+ else None
+ )
+ if oauth_token is None and type_hint == oauth.OAuthToken:
+ raise Error(
+ "This action requires a logged in user. Please sign in and retry."
+ )
+ inputs.insert(i, oauth_token)
+ elif (
+ type_hint
+ and inspect.isclass(type_hint)
+ and issubclass(type_hint, EventData)
+ ):
+ event_data_index = i
+ if inputs is not None and event_data is not None:
+ inputs.insert(i, type_hint(event_data.target, event_data._data))
+ elif (
+ param.default is not param.empty and inputs is not None and len(inputs) <= i
+ ):
+ inputs.insert(i, param.default)
+ if inputs is not None:
+ while len(inputs) < len(positional_args):
+ i = len(inputs)
+ param = positional_args[i]
+ if param.default == param.empty:
+ warnings.warn("Unexpected argument. Filling with None.")
+ inputs.append(None)
+ else:
+ inputs.append(param.default)
+ return inputs or [], progress_index, event_data_index
+
+
+def update(
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ visible: bool | None = None,
+ **kwargs,
+) -> dict:
+ """
+ Updates a component's properties. When a function passed into a Gradio Interface or a Blocks events returns a value, it typically updates the value of the output component. But it is also possible to update the *properties* of an output component (such as the number of lines of a `Textbox` or the visibility of an `Row`) by returning a component and passing in the parameters to update in the constructor of the component. Alternatively, you can return `gr.update(...)` with any arbitrary parameters to update. (This is useful as a shorthand or if the same function can be called with different components to update.)
+
+ Parameters:
+ elem_id: Use this to update the id of the component in the HTML DOM
+ elem_classes: Use this to update the classes of the component in the HTML DOM
+ visible: Use this to update the visibility of the component
+ kwargs: Any other keyword arguments to update the component's properties.
+ Example:
+ import gradio as gr
+ with gr.Blocks() as demo:
+ radio = gr.Radio([1, 2, 4], label="Set the value of the number")
+ number = gr.Number(value=2, interactive=True)
+ radio.change(fn=lambda value: gr.update(value=value), inputs=radio, outputs=number)
+ demo.launch()
+ """
+ kwargs["__type__"] = "update"
+ if elem_id is not None:
+ kwargs["elem_id"] = elem_id
+ if elem_classes is not None:
+ kwargs["elem_classes"] = elem_classes
+ if visible is not None:
+ kwargs["visible"] = visible
+ return kwargs
+
+
+def skip() -> dict:
+ return {"__type__": "update"}
+
+
+@document()
+def make_waveform(
+ audio: str | tuple[int, np.ndarray],
+ *,
+ bg_color: str = "#f3f4f6",
+ bg_image: str | None = None,
+ fg_alpha: float = 0.75,
+ bars_color: str | tuple[str, str] = ("#fbbf24", "#ea580c"),
+ bar_count: int = 50,
+ bar_width: float = 0.6,
+ animate: bool = False,
+) -> str:
+ """
+ Generates a waveform video from an audio file. Useful for creating an easy to share audio visualization. The output should be passed into a `gr.Video` component.
+ Parameters:
+ audio: Audio file path or tuple of (sample_rate, audio_data)
+ bg_color: Background color of waveform (ignored if bg_image is provided)
+ bg_image: Background image of waveform
+ fg_alpha: Opacity of foreground waveform
+ bars_color: Color of waveform bars. Can be a single color or a tuple of (start_color, end_color) of gradient
+ bar_count: Number of bars in waveform
+ bar_width: Width of bars in waveform. 1 represents full width, 0.5 represents half width, etc.
+ animate: If true, the audio waveform overlay will be animated, if false, it will be static.
+ Returns:
+ A filepath to the output video in mp4 format.
+ """
+ if isinstance(audio, str):
+ audio_file = audio
+ audio = processing_utils.audio_from_file(audio)
+ else:
+ tmp_wav = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
+ processing_utils.audio_to_file(audio[0], audio[1], tmp_wav.name, format="wav")
+ audio_file = tmp_wav.name
+
+ if not os.path.isfile(audio_file):
+ raise ValueError("Audio file not found.")
+
+ ffmpeg = shutil.which("ffmpeg")
+ if not ffmpeg:
+ raise RuntimeError("ffmpeg not found.")
+
+ duration = round(len(audio[1]) / audio[0], 4)
+
+ # Helper methods to create waveform
+ def hex_to_rgb(hex_str):
+ return [int(hex_str[i : i + 2], 16) for i in range(1, 6, 2)]
+
+ def get_color_gradient(c1, c2, n):
+ assert n > 1
+ c1_rgb = np.array(hex_to_rgb(c1)) / 255
+ c2_rgb = np.array(hex_to_rgb(c2)) / 255
+ mix_pcts = [x / (n - 1) for x in range(n)]
+ rgb_colors = [((1 - mix) * c1_rgb + (mix * c2_rgb)) for mix in mix_pcts]
+ return [
+ "#" + "".join(f"{int(round(val * 255)):02x}" for val in item)
+ for item in rgb_colors
+ ]
+
+ # Reshape audio to have a fixed number of bars
+ samples = audio[1]
+ if len(samples.shape) > 1:
+ samples = np.mean(samples, 1)
+ bins_to_pad = bar_count - (len(samples) % bar_count)
+ samples = np.pad(samples, [(0, bins_to_pad)])
+ samples = np.reshape(samples, (bar_count, -1))
+ samples = np.abs(samples)
+ samples = np.max(samples, 1)
+
+ with utils.MatplotlibBackendMananger():
+ plt.clf()
+ # Plot waveform
+ color = (
+ bars_color
+ if isinstance(bars_color, str)
+ else get_color_gradient(bars_color[0], bars_color[1], bar_count)
+ )
+
+ if animate:
+ fig = plt.figure(figsize=(5, 1), dpi=200, frameon=False)
+ fig.subplots_adjust(left=0, bottom=0, right=1, top=1)
+ plt.axis("off")
+ plt.margins(x=0)
+
+ bar_alpha = fg_alpha if animate else 1.0
+ barcollection = plt.bar(
+ np.arange(0, bar_count),
+ samples * 2,
+ bottom=(-1 * samples),
+ width=bar_width,
+ color=color,
+ alpha=bar_alpha,
+ )
+
+ tmp_img = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
+
+ savefig_kwargs: dict[str, Any] = {"bbox_inches": "tight"}
+ if bg_image is not None:
+ savefig_kwargs["transparent"] = True
+ if animate:
+ savefig_kwargs["facecolor"] = "none"
+ else:
+ savefig_kwargs["facecolor"] = bg_color
+ plt.savefig(tmp_img.name, **savefig_kwargs)
+
+ if not animate:
+ waveform_img = PIL.Image.open(tmp_img.name)
+ waveform_img = waveform_img.resize((1000, 400))
+
+ # Composite waveform with background image
+ if bg_image is not None:
+ waveform_array = np.array(waveform_img)
+ waveform_array[:, :, 3] = waveform_array[:, :, 3] * fg_alpha
+ waveform_img = PIL.Image.fromarray(waveform_array)
+
+ bg_img = PIL.Image.open(bg_image)
+ waveform_width, waveform_height = waveform_img.size
+ bg_width, bg_height = bg_img.size
+ if waveform_width != bg_width:
+ bg_img = bg_img.resize(
+ (
+ waveform_width,
+ 2 * int(bg_height * waveform_width / bg_width / 2),
+ )
+ )
+ bg_width, bg_height = bg_img.size
+ composite_height = max(bg_height, waveform_height)
+ composite = PIL.Image.new(
+ "RGBA", (waveform_width, composite_height), "#FFFFFF"
+ )
+ composite.paste(bg_img, (0, composite_height - bg_height))
+ composite.paste(
+ waveform_img, (0, composite_height - waveform_height), waveform_img
+ )
+ composite.save(tmp_img.name)
+ img_width, img_height = composite.size
+ else:
+ img_width, img_height = waveform_img.size
+ waveform_img.save(tmp_img.name)
+ else:
+
+ def _animate(_):
+ for idx, b in enumerate(barcollection):
+ rand_height = np.random.uniform(0.8, 1.2)
+ b.set_height(samples[idx] * rand_height * 2)
+ b.set_y((-rand_height * samples)[idx])
+
+ frames = int(duration * 10)
+ anim = animation.FuncAnimation(
+ fig, # type: ignore
+ _animate,
+ repeat=False,
+ blit=False,
+ frames=frames,
+ interval=100,
+ )
+ anim.save(
+ tmp_img.name,
+ writer="pillow",
+ fps=10,
+ codec="png",
+ savefig_kwargs=savefig_kwargs,
+ )
+
+ # Convert waveform to video with ffmpeg
+ output_mp4 = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
+
+ if animate and bg_image is not None:
+ ffmpeg_cmd = [
+ ffmpeg,
+ "-loop",
+ "1",
+ "-i",
+ bg_image,
+ "-i",
+ tmp_img.name,
+ "-i",
+ audio_file,
+ "-filter_complex",
+ "[0:v]scale=w=trunc(iw/2)*2:h=trunc(ih/2)*2[bg];[1:v]format=rgba,colorchannelmixer=aa=1.0[ov];[bg][ov]overlay=(main_w-overlay_w*0.9)/2:main_h-overlay_h*0.9/2[output]",
+ "-t",
+ str(duration),
+ "-map",
+ "[output]",
+ "-map",
+ "2:a",
+ "-c:v",
+ "libx264",
+ "-c:a",
+ "aac",
+ "-shortest",
+ "-y",
+ output_mp4.name,
+ ]
+ elif animate and bg_image is None:
+ ffmpeg_cmd = [
+ ffmpeg,
+ "-i",
+ tmp_img.name,
+ "-i",
+ audio_file,
+ "-filter_complex",
+ "[0:v][1:a]concat=n=1:v=1:a=1[v];[v]scale=1000:400,format=yuv420p[v_scaled]",
+ "-map",
+ "[v_scaled]",
+ "-map",
+ "1:a",
+ "-c:v",
+ "libx264",
+ "-c:a",
+ "aac",
+ "-shortest",
+ "-y",
+ output_mp4.name,
+ ]
+ else:
+ ffmpeg_cmd = [
+ ffmpeg,
+ "-loop",
+ "1",
+ "-i",
+ tmp_img.name,
+ "-i",
+ audio_file,
+ "-vf",
+ f"color=c=#FFFFFF77:s={img_width}x{img_height}[bar];[0][bar]overlay=-w+(w/{duration})*t:H-h:shortest=1", # type: ignore
+ "-t",
+ str(duration),
+ "-y",
+ output_mp4.name,
+ ]
+
+ subprocess.check_call(ffmpeg_cmd)
+ return output_mp4.name
+
+
+def log_message(message: str, level: Literal["info", "warning"] = "info"):
+ from gradio.context import LocalContext
+
+ blocks = LocalContext.blocks.get()
+ event_id = LocalContext.event_id.get()
+ if blocks is None or event_id is None:
+ # Function called outside of Gradio if blocks is None
+ # Or from /api/predict if event_id is None
+ if level == "info":
+ print(message)
+ elif level == "warning":
+ warnings.warn(message)
+ return
+ blocks._queue.log_message(event_id=event_id, log=message, level=level)
+
+
+set_documentation_group("modals")
+
+
+@document()
+def Warning(message: str = "Warning issued."): # noqa: N802
+ """
+ This function allows you to pass custom warning messages to the user. You can do so simply by writing `gr.Warning('message here')` in your function, and when that line is executed the custom message will appear in a modal on the demo. The modal is yellow by default and has the heading: "Warning." Queue must be enabled for this behavior; otherwise, the warning will be printed to the console using the `warnings` library.
+ Demos: blocks_chained_events
+ Parameters:
+ message: The warning message to be displayed to the user.
+ Example:
+ import gradio as gr
+ def hello_world():
+ gr.Warning('This is a warning message.')
+ return "hello world"
+ with gr.Blocks() as demo:
+ md = gr.Markdown()
+ demo.load(hello_world, inputs=None, outputs=[md])
+ demo.queue().launch()
+ """
+ log_message(message, level="warning")
+
+
+@document()
+def Info(message: str = "Info issued."): # noqa: N802
+ """
+ This function allows you to pass custom info messages to the user. You can do so simply by writing `gr.Info('message here')` in your function, and when that line is executed the custom message will appear in a modal on the demo. The modal is gray by default and has the heading: "Info." Queue must be enabled for this behavior; otherwise, the message will be printed to the console.
+ Demos: blocks_chained_events
+ Parameters:
+ message: The info message to be displayed to the user.
+ Example:
+ import gradio as gr
+ def hello_world():
+ gr.Info('This is some info.')
+ return "hello world"
+ with gr.Blocks() as demo:
+ md = gr.Markdown()
+ demo.load(hello_world, inputs=None, outputs=[md])
+ demo.queue().launch()
+ """
+ log_message(message, level="info")
diff --git a/gradio/image_utils.py b/gradio/image_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..045f8212bcf2905a29b1be688f0a4d778e3d1e33
--- /dev/null
+++ b/gradio/image_utils.py
@@ -0,0 +1,104 @@
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Literal
+
+import numpy as np
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+from gradio import processing_utils
+
+_Image.init()
+
+
+def format_image(
+ im: _Image.Image | None,
+ type: Literal["numpy", "pil", "filepath"],
+ cache_dir: str,
+ name: str = "image",
+ format: str = "png",
+) -> np.ndarray | _Image.Image | str | None:
+ """Helper method to format an image based on self.type"""
+ if im is None:
+ return im
+ fmt = im.format
+ if type == "pil":
+ return im
+ elif type == "numpy":
+ return np.array(im)
+ elif type == "filepath":
+ try:
+ path = processing_utils.save_pil_to_cache(
+ im,
+ cache_dir=cache_dir,
+ name=name,
+ format=fmt or format, # type: ignore
+ )
+ # Catch error if format is not supported by PIL
+ except (KeyError, ValueError):
+ path = processing_utils.save_pil_to_cache(
+ im,
+ cache_dir=cache_dir,
+ name=name,
+ format="png", # type: ignore
+ )
+ return path
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(type)
+ + ". Please choose from: 'numpy', 'pil', 'filepath'."
+ )
+
+
+def save_image(y: np.ndarray | _Image.Image | str | Path, cache_dir: str):
+ # numpy gets saved to png as default format
+ # PIL gets saved to its original format if possible
+ if isinstance(y, np.ndarray):
+ path = processing_utils.save_img_array_to_cache(y, cache_dir=cache_dir)
+ elif isinstance(y, _Image.Image):
+ fmt = y.format
+ try:
+ path = processing_utils.save_pil_to_cache(
+ y,
+ cache_dir=cache_dir,
+ format=fmt, # type: ignore
+ )
+ # Catch error if format is not supported by PIL
+ except (KeyError, ValueError):
+ path = processing_utils.save_pil_to_cache(
+ y, cache_dir=cache_dir, format="png"
+ )
+ elif isinstance(y, Path):
+ path = str(y)
+ elif isinstance(y, str):
+ path = y
+ else:
+ raise ValueError(
+ "Cannot process this value as an Image, it is of type: " + str(type(y))
+ )
+
+ return path
+
+
+def crop_scale(img: _Image.Image, final_width: int, final_height: int):
+ original_width, original_height = img.size
+ target_aspect_ratio = final_width / final_height
+
+ if original_width / original_height > target_aspect_ratio:
+ crop_height = original_height
+ crop_width = crop_height * target_aspect_ratio
+ else:
+ crop_width = original_width
+ crop_height = crop_width / target_aspect_ratio
+
+ left = (original_width - crop_width) / 2
+ top = (original_height - crop_height) / 2
+
+ img_cropped = img.crop(
+ (int(left), int(top), int(left + crop_width), int(top + crop_height))
+ )
+
+ img_resized = img_cropped.resize((final_width, final_height))
+
+ return img_resized
diff --git a/gradio/interface.py b/gradio/interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..544e45ea3906c9cd0d6cf792715bd3855ec46a54
--- /dev/null
+++ b/gradio/interface.py
@@ -0,0 +1,901 @@
+"""
+This file defines two useful high-level abstractions to build Gradio apps: Interface and TabbedInterface.
+"""
+
+from __future__ import annotations
+
+import inspect
+import json
+import os
+import warnings
+import weakref
+from typing import TYPE_CHECKING, Any, Callable, Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio import Examples, utils
+from gradio.blocks import Blocks
+from gradio.components import (
+ Button,
+ ClearButton,
+ Component,
+ DuplicateButton,
+ Markdown,
+ State,
+ get_component_instance,
+)
+from gradio.data_classes import InterfaceTypes
+from gradio.events import Events, on
+from gradio.exceptions import RenderError
+from gradio.flagging import CSVLogger, FlaggingCallback, FlagMethod
+from gradio.layouts import Accordion, Column, Row, Tab, Tabs
+from gradio.pipelines import load_from_pipeline
+from gradio.themes import ThemeClass as Theme
+
+set_documentation_group("interface")
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from transformers.pipelines.base import Pipeline
+
+
+@document("launch", "load", "from_pipeline", "integrate", "queue")
+class Interface(Blocks):
+ """
+ Interface is Gradio's main high-level class, and allows you to create a web-based GUI / demo
+ around a machine learning model (or any Python function) in a few lines of code.
+ You must specify three parameters: (1) the function to create a GUI for (2) the desired input components and
+ (3) the desired output components. Additional parameters can be used to control the appearance
+ and behavior of the demo.
+
+ Example:
+ import gradio as gr
+
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label")
+ demo.launch()
+ Demos: hello_world, hello_world_3, gpt2_xl
+ Guides: quickstart, key-features, sharing-your-app, interface-state, reactive-interfaces, advanced-interface-features, setting-up-a-gradio-demo-for-maximum-performance
+ """
+
+ # stores references to all currently existing Interface instances
+ instances: weakref.WeakSet = weakref.WeakSet()
+
+ @classmethod
+ def get_instances(cls) -> list[Interface]:
+ """
+ :return: list of all current instances.
+ """
+ return list(Interface.instances)
+
+ @classmethod
+ def from_pipeline(cls, pipeline: Pipeline, **kwargs) -> Interface:
+ """
+ Class method that constructs an Interface from a Hugging Face transformers.Pipeline object.
+ The input and output components are automatically determined from the pipeline.
+ Parameters:
+ pipeline: the pipeline object to use.
+ Returns:
+ a Gradio Interface object from the given Pipeline
+ Example:
+ import gradio as gr
+ from transformers import pipeline
+ pipe = pipeline("image-classification")
+ gr.Interface.from_pipeline(pipe).launch()
+ """
+ interface_info = load_from_pipeline(pipeline)
+ kwargs = dict(interface_info, **kwargs)
+ interface = cls(**kwargs)
+ return interface
+
+ def __init__(
+ self,
+ fn: Callable,
+ inputs: str | Component | list[str | Component] | None,
+ outputs: str | Component | list[str | Component] | None,
+ examples: list[Any] | list[list[Any]] | str | None = None,
+ cache_examples: bool | None = None,
+ examples_per_page: int = 10,
+ live: bool = False,
+ title: str | None = None,
+ description: str | None = None,
+ article: str | None = None,
+ thumbnail: str | None = None,
+ theme: Theme | str | None = None,
+ css: str | None = None,
+ allow_flagging: str | None = None,
+ flagging_options: list[str] | list[tuple[str, str]] | None = None,
+ flagging_dir: str = "flagged",
+ flagging_callback: FlaggingCallback | None = None,
+ analytics_enabled: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ api_name: str | Literal[False] | None = "predict",
+ _api_mode: bool = False,
+ allow_duplication: bool = False,
+ concurrency_limit: int | None | Literal["default"] = "default",
+ js: str | None = None,
+ head: str | None = None,
+ additional_inputs: str | Component | list[str | Component] | None = None,
+ additional_inputs_accordion: str | Accordion | None = None,
+ *,
+ submit_btn: str | Button = "Submit",
+ stop_btn: str | Button = "Stop",
+ clear_btn: str | Button = "Clear",
+ **kwargs,
+ ):
+ """
+ Parameters:
+ fn: The function to wrap an interface around. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: A single Gradio component, or list of Gradio components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of input components should match the number of parameters in fn. If set to None, then only the output components will be displayed.
+ outputs: A single Gradio component, or list of Gradio components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of output components should match the number of values returned by fn. If set to None, then only the input components will be displayed.
+ examples: Sample inputs for the function; if provided, appear below the UI components and can be clicked to populate the interface. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component. A string path to a directory of examples can also be provided, but it should be within the directory with the python file running the gradio app. If there are multiple input components and a directory is provided, a log.csv file must be present in the directory to link corresponding inputs.
+ cache_examples: If True, caches examples in the server for fast runtime in examples. If `fn` is a generator function, then the last yielded value will be used as the output. The default option in HuggingFace Spaces is True. The default option elsewhere is False.
+ examples_per_page: If examples are provided, how many to display per page.
+ live: Whether the interface should automatically rerun if any of the inputs change.
+ title: A title for the interface; if provided, appears above the input and output components in large font. Also used as the tab title when opened in a browser window.
+ description: A description for the interface; if provided, appears above the input and output components and beneath the title in regular font. Accepts Markdown and HTML content.
+ article: An expanded article explaining the interface; if provided, appears below the input and output components in regular font. Accepts Markdown and HTML content.
+ thumbnail: String path or url to image to use as display image when the web demo is shared on social media.
+ theme: Theme to use, loaded from gradio.themes.
+ css: Custom css as a string or path to a css file. This css will be included in the demo webpage.
+ allow_flagging: One of "never", "auto", or "manual". If "never" or "auto", users will not see a button to flag an input and output. If "manual", users will see a button to flag. If "auto", every input the user submits will be automatically flagged (outputs are not flagged). If "manual", both the input and outputs are flagged when the user clicks flag button. This parameter can be set with environmental variable GRADIO_ALLOW_FLAGGING; otherwise defaults to "manual".
+ flagging_options: If provided, allows user to select from the list of options when flagging. Only applies if allow_flagging is "manual". Can either be a list of tuples of the form (label, value), where label is the string that will be displayed on the button and value is the string that will be stored in the flagging CSV; or it can be a list of strings ["X", "Y"], in which case the values will be the list of strings and the labels will ["Flag as X", "Flag as Y"], etc.
+ flagging_dir: What to name the directory where flagged data is stored.
+ flagging_callback: None or an instance of a subclass of FlaggingCallback which will be called when a sample is flagged. If set to None, an instance of gradio.flagging.CSVLogger will be created and logs will be saved to a local CSV file in flagging_dir. Default to None.
+ analytics_enabled: Whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable if defined, or default to True.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ api_name: Defines how the endpoint appears in the API docs. Can be a string, None, or False. If set to a string, the endpoint will be exposed in the API docs with the given name. If None, the name of the prediction function will be used as the API endpoint. If False, the endpoint will not be exposed in the API docs and downstream apps (including those that `gr.load` this app) will not be able to use this event.
+ allow_duplication: If True, then will show a 'Duplicate Spaces' button on Hugging Face Spaces.
+ concurrency_limit: If set, this is the maximum number of this event that can be running simultaneously. Can be set to None to mean no concurrency_limit (any number of this event can be running simultaneously). Set to "default" to use the default concurrency limit (defined by the `default_concurrency_limit` parameter in `.queue()`, which itself is 1 by default).
+ js: Custom js or path to js file to run when demo is first loaded. This javascript will be included in the demo webpage.
+ head: Custom html to insert into the head of the demo webpage. This can be used to add custom meta tags, scripts, stylesheets, etc. to the page.
+ additional_inputs: A single Gradio component, or list of Gradio components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. These components will be rendered in an accordion below the main input components. By default, no additional input components will be displayed.
+ additional_inputs_accordion: If a string is provided, this is the label of the `gr.Accordion` to use to contain additional inputs. A `gr.Accordion` object can be provided as well to configure other properties of the container holding the additional inputs. Defaults to a `gr.Accordion(label="Additional Inputs", open=False)`. This parameter is only used if `additional_inputs` is provided.
+ submit_btn: The button to use for submitting inputs. Defaults to a `gr.Button("Submit", variant="primary")`. This parameter does not apply if the Interface is output-only, in which case the submit button always displays "Generate". Can be set to a string (which becomes the button label) or a `gr.Button` object (which allows for more customization).
+ stop_btn: The button to use for stopping the interface. Defaults to a `gr.Button("Stop", variant="stop", visible=False)`. Can be set to a string (which becomes the button label) or a `gr.Button` object (which allows for more customization).
+ clear_btn: The button to use for clearing the inputs. Defaults to a `gr.Button("Clear", variant="secondary")`. Can be set to a string (which becomes the button label) or a `gr.Button` object (which allows for more customization).
+ """
+ super().__init__(
+ analytics_enabled=analytics_enabled,
+ mode="interface",
+ css=css,
+ title=title or "Gradio",
+ theme=theme,
+ js=js,
+ head=head,
+ **kwargs,
+ )
+ self.api_name: str | Literal[False] | None = api_name
+ self.interface_type = InterfaceTypes.STANDARD
+ if (inputs is None or inputs == []) and (outputs is None or outputs == []):
+ raise ValueError("Must provide at least one of `inputs` or `outputs`")
+ elif outputs is None or outputs == []:
+ outputs = []
+ self.interface_type = InterfaceTypes.INPUT_ONLY
+ elif inputs is None or inputs == []:
+ inputs = []
+ self.interface_type = InterfaceTypes.OUTPUT_ONLY
+ if additional_inputs is None:
+ additional_inputs = []
+
+ assert isinstance(inputs, (str, list, Component))
+ assert isinstance(outputs, (str, list, Component))
+
+ if not isinstance(inputs, list):
+ inputs = [inputs]
+ if not isinstance(outputs, list):
+ outputs = [outputs]
+ if not isinstance(additional_inputs, list):
+ additional_inputs = [additional_inputs]
+
+ if self.space_id and cache_examples is None:
+ self.cache_examples = True
+ else:
+ self.cache_examples = cache_examples or False
+
+ state_input_indexes = [
+ idx for idx, i in enumerate(inputs) if i == "state" or isinstance(i, State)
+ ]
+ state_output_indexes = [
+ idx for idx, o in enumerate(outputs) if o == "state" or isinstance(o, State)
+ ]
+
+ if len(state_input_indexes) == 0 and len(state_output_indexes) == 0:
+ pass
+ elif len(state_input_indexes) != 1 or len(state_output_indexes) != 1:
+ raise ValueError(
+ "If using 'state', there must be exactly one state input and one state output."
+ )
+ else:
+ state_input_index = state_input_indexes[0]
+ state_output_index = state_output_indexes[0]
+ if inputs[state_input_index] == "state":
+ default = utils.get_default_args(fn)[state_input_index]
+ state_variable = State(value=default) # type: ignore
+ else:
+ state_variable = inputs[state_input_index]
+
+ inputs[state_input_index] = state_variable
+ outputs[state_output_index] = state_variable
+
+ if cache_examples:
+ warnings.warn(
+ "Cache examples cannot be used with state inputs and outputs."
+ "Setting cache_examples to False."
+ )
+ self.cache_examples = False
+
+ self.main_input_components = [
+ get_component_instance(i, unrender=True)
+ for i in inputs # type: ignore
+ ]
+ self.additional_input_components = [
+ get_component_instance(i, unrender=True)
+ for i in additional_inputs # type: ignore
+ ]
+ if additional_inputs_accordion is None:
+ self.additional_inputs_accordion_params = {
+ "label": "Additional Inputs",
+ "open": False,
+ }
+ elif isinstance(additional_inputs_accordion, str):
+ self.additional_inputs_accordion_params = {
+ "label": additional_inputs_accordion
+ }
+ elif isinstance(additional_inputs_accordion, Accordion):
+ self.additional_inputs_accordion_params = (
+ additional_inputs_accordion.recover_kwargs(
+ additional_inputs_accordion.get_config()
+ )
+ )
+ else:
+ raise ValueError(
+ f"The `additional_inputs_accordion` parameter must be a string or gr.Accordion, not {type(additional_inputs_accordion)}"
+ )
+ self.input_components = (
+ self.main_input_components + self.additional_input_components
+ )
+ self.output_components = [
+ get_component_instance(o, unrender=True)
+ for o in outputs # type: ignore
+ ]
+
+ for component in self.input_components + self.output_components:
+ if not (isinstance(component, Component)):
+ raise ValueError(
+ f"{component} is not a valid input/output component for Interface."
+ )
+
+ if len(self.input_components) == len(self.output_components):
+ same_components = [
+ i is o for i, o in zip(self.input_components, self.output_components)
+ ]
+ if all(same_components):
+ self.interface_type = InterfaceTypes.UNIFIED
+
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ ]:
+ for o in self.output_components:
+ assert isinstance(o, Component)
+ if o.interactive is None:
+ # Unless explicitly otherwise specified, force output components to
+ # be non-interactive
+ o.interactive = False
+
+ self.api_mode = _api_mode
+ self.fn = fn
+ self.fn_durations = [0, 0]
+ self.__name__ = getattr(fn, "__name__", "fn")
+ self.live = live
+ self.title = title
+
+ self.simple_description = utils.remove_html_tags(description)
+ self.description = description
+ if article is not None:
+ article = utils.readme_to_html(article)
+ self.article = article
+
+ self.thumbnail = thumbnail
+
+ self.examples = examples
+ self.examples_per_page = examples_per_page
+
+ if isinstance(submit_btn, Button):
+ self.submit_btn_parms = submit_btn.recover_kwargs(submit_btn.get_config())
+ elif isinstance(submit_btn, str):
+ self.submit_btn_parms = {
+ "value": submit_btn,
+ "variant": "primary",
+ }
+ else:
+ raise ValueError(
+ f"The submit_btn parameter must be a gr.Button or string, not {type(submit_btn)}"
+ )
+
+ if isinstance(stop_btn, Button):
+ self.stop_btn_parms = stop_btn.recover_kwargs(stop_btn.get_config())
+ elif isinstance(stop_btn, str):
+ self.stop_btn_parms = {
+ "value": stop_btn,
+ "variant": "stop",
+ "visible": False,
+ }
+ else:
+ raise ValueError(
+ f"The stop_btn parameter must be a gr.Button or string, not {type(stop_btn)}"
+ )
+
+ if isinstance(clear_btn, Button):
+ self.clear_btn_params = clear_btn.recover_kwargs(clear_btn.get_config())
+ elif isinstance(clear_btn, str):
+ self.clear_btn_params = {
+ "value": clear_btn,
+ "variant": "secondary",
+ }
+ else:
+ raise ValueError(
+ f"The clear_btn parameter must be a gr.Button or string, not {type(clear_btn)}"
+ )
+
+ self.simple_server = None
+
+ # For allow_flagging: (1) first check for parameter,
+ # (2) check for env variable, (3) default to True/"manual"
+ if allow_flagging is None:
+ allow_flagging = os.getenv("GRADIO_ALLOW_FLAGGING", "manual")
+ if allow_flagging is True:
+ warnings.warn(
+ "The `allow_flagging` parameter in `Interface` now"
+ "takes a string value ('auto', 'manual', or 'never')"
+ ", not a boolean. Setting parameter to: 'manual'."
+ )
+ self.allow_flagging = "manual"
+ elif allow_flagging == "manual":
+ self.allow_flagging = "manual"
+ elif allow_flagging is False:
+ warnings.warn(
+ "The `allow_flagging` parameter in `Interface` now"
+ "takes a string value ('auto', 'manual', or 'never')"
+ ", not a boolean. Setting parameter to: 'never'."
+ )
+ self.allow_flagging = "never"
+ elif allow_flagging == "never":
+ self.allow_flagging = "never"
+ elif allow_flagging == "auto":
+ self.allow_flagging = "auto"
+ else:
+ raise ValueError(
+ "Invalid value for `allow_flagging` parameter."
+ "Must be: 'auto', 'manual', or 'never'."
+ )
+
+ if flagging_options is None:
+ self.flagging_options = [("Flag", "")]
+ elif not (isinstance(flagging_options, list)):
+ raise ValueError(
+ "flagging_options must be a list of strings or list of (string, string) tuples."
+ )
+ elif all(isinstance(x, str) for x in flagging_options):
+ self.flagging_options = [(f"Flag as {x}", x) for x in flagging_options]
+ elif all(isinstance(x, tuple) for x in flagging_options):
+ self.flagging_options = flagging_options
+ else:
+ raise ValueError(
+ "flagging_options must be a list of strings or list of (string, string) tuples."
+ )
+
+ if flagging_callback is None:
+ flagging_callback = CSVLogger()
+
+ self.flagging_callback = flagging_callback
+ self.flagging_dir = flagging_dir
+
+ self.batch = batch
+ self.max_batch_size = max_batch_size
+ self.allow_duplication = allow_duplication
+ self.concurrency_limit: int | None | Literal["default"] = concurrency_limit
+
+ self.share = None
+ self.share_url = None
+ self.local_url = None
+
+ self.favicon_path = None
+ Interface.instances.add(self)
+
+ param_types = utils.get_type_hints(self.fn)
+ # param_names = inspect.getfullargspec(self.fn)[0]
+ param_names = []
+ try:
+ param_names = inspect.getfullargspec(self.fn)[0]
+ if len(param_names) > 0 and inspect.ismethod(self.fn):
+ param_names = param_names[1:]
+ for param_name in param_names.copy():
+ if utils.is_special_typed_parameter(param_name, param_types):
+ param_names.remove(param_name)
+ except (TypeError, ValueError):
+ param_names = utils.default_input_labels()
+ for component, param_name in zip(self.input_components, param_names):
+ assert isinstance(component, Component)
+ if component.label is None:
+ component.label = param_name
+ for i, component in enumerate(self.output_components):
+ assert isinstance(component, Component)
+ if component.label is None:
+ if len(self.output_components) == 1:
+ component.label = "output"
+ else:
+ component.label = f"output {i}"
+
+ if self.allow_flagging != "never":
+ if (
+ self.interface_type == InterfaceTypes.UNIFIED
+ or self.allow_flagging == "auto"
+ ):
+ self.flagging_callback.setup(self.input_components, self.flagging_dir) # type: ignore
+ elif self.interface_type == InterfaceTypes.INPUT_ONLY:
+ pass
+ else:
+ self.flagging_callback.setup(
+ self.input_components + self.output_components,
+ self.flagging_dir, # type: ignore
+ )
+
+ # Render the Gradio UI
+ with self:
+ self.render_title_description()
+
+ _submit_btn, _clear_btn, _stop_btn, flag_btns, duplicate_btn = (
+ None,
+ None,
+ None,
+ None,
+ None,
+ ) # type: ignore
+ input_component_column = None
+
+ with Row(equal_height=False):
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ ]:
+ (
+ _submit_btn,
+ _clear_btn,
+ _stop_btn,
+ flag_btns,
+ input_component_column,
+ ) = self.render_input_column() # type: ignore
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ ]:
+ (
+ _submit_btn_out,
+ _clear_btn_2_out,
+ duplicate_btn,
+ _stop_btn_2_out,
+ flag_btns_out,
+ ) = self.render_output_column(_submit_btn)
+ _submit_btn = _submit_btn or _submit_btn_out
+ _clear_btn = _clear_btn or _clear_btn_2_out
+ _stop_btn = _stop_btn or _stop_btn_2_out
+ flag_btns = flag_btns or flag_btns_out
+
+ if _clear_btn is None:
+ raise RenderError("Clear button not rendered")
+
+ self.attach_submit_events(_submit_btn, _stop_btn)
+ self.attach_clear_events(_clear_btn, input_component_column)
+ if duplicate_btn is not None:
+ duplicate_btn.activate()
+
+ self.attach_flagging_events(flag_btns, _clear_btn)
+ self.render_examples()
+ self.render_article()
+
+ self.config = self.get_config_file()
+
+ def render_title_description(self) -> None:
+ if self.title:
+ Markdown(
+ f"{self.title} "
+ )
+ if self.description:
+ Markdown(self.description)
+
+ def render_flag_btns(self) -> list[Button]:
+ return [Button(label) for label, _ in self.flagging_options]
+
+ def render_input_column(
+ self,
+ ) -> tuple[
+ Button | None,
+ ClearButton | None,
+ Button | None,
+ list[Button] | None,
+ Column,
+ ]:
+ _submit_btn, _clear_btn, _stop_btn, flag_btns = None, None, None, None
+
+ with Column(variant="panel"):
+ input_component_column = Column()
+ with input_component_column:
+ for component in self.main_input_components:
+ component.render()
+ if self.additional_input_components:
+ with Accordion(**self.additional_inputs_accordion_params): # type: ignore
+ for component in self.additional_input_components:
+ component.render()
+ with Row():
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ ]:
+ _clear_btn = ClearButton(**self.clear_btn_params) # type: ignore
+ if not self.live:
+ _submit_btn = Button(**self.submit_btn_parms) # type: ignore
+ # Stopping jobs only works if the queue is enabled
+ # We don't know if the queue is enabled when the interface
+ # is created. We use whether a generator function is provided
+ # as a proxy of whether the queue will be enabled.
+ # Using a generator function without the queue will raise an error.
+ if inspect.isgeneratorfunction(
+ self.fn
+ ) or inspect.isasyncgenfunction(self.fn):
+ _stop_btn = Button(**self.stop_btn_parms)
+ elif self.interface_type == InterfaceTypes.UNIFIED:
+ _clear_btn = ClearButton(**self.clear_btn_params) # type: ignore
+ _submit_btn = Button(**self.submit_btn_parms) # type: ignore
+ if (
+ inspect.isgeneratorfunction(self.fn)
+ or inspect.isasyncgenfunction(self.fn)
+ ) and not self.live:
+ _stop_btn = Button(**self.stop_btn_parms)
+ if self.allow_flagging == "manual":
+ flag_btns = self.render_flag_btns()
+ elif self.allow_flagging == "auto":
+ flag_btns = [_submit_btn]
+ return (
+ _submit_btn,
+ _clear_btn,
+ _stop_btn,
+ flag_btns,
+ input_component_column,
+ )
+
+ def render_output_column(
+ self,
+ _submit_btn_in: Button | None,
+ ) -> tuple[
+ Button | None,
+ ClearButton | None,
+ DuplicateButton | None,
+ Button | None,
+ list | None,
+ ]:
+ _submit_btn = _submit_btn_in
+ _clear_btn, duplicate_btn, flag_btns, _stop_btn = (
+ None,
+ None,
+ None,
+ None,
+ )
+
+ with Column(variant="panel"):
+ for component in self.output_components:
+ if not (isinstance(component, State)):
+ component.render()
+ with Row():
+ if self.interface_type == InterfaceTypes.OUTPUT_ONLY:
+ _clear_btn = ClearButton(**self.clear_btn_params) # type: ignore
+ _submit_btn = Button("Generate", variant="primary")
+ if (
+ inspect.isgeneratorfunction(self.fn)
+ or inspect.isasyncgenfunction(self.fn)
+ ) and not self.live:
+ # Stopping jobs only works if the queue is enabled
+ # We don't know if the queue is enabled when the interface
+ # is created. We use whether a generator function is provided
+ # as a proxy of whether the queue will be enabled.
+ # Using a generator function without the queue will raise an error.
+ _stop_btn = Button(**self.stop_btn_parms)
+ if self.allow_flagging == "manual":
+ flag_btns = self.render_flag_btns()
+ elif self.allow_flagging == "auto":
+ if _submit_btn is None:
+ raise RenderError("Submit button not rendered")
+ flag_btns = [_submit_btn]
+
+ if self.allow_duplication:
+ duplicate_btn = DuplicateButton(scale=1, size="lg", _activate=False)
+
+ return (
+ _submit_btn,
+ _clear_btn,
+ duplicate_btn,
+ _stop_btn,
+ flag_btns,
+ )
+
+ def render_article(self):
+ if self.article:
+ Markdown(self.article)
+
+ def attach_submit_events(
+ self, _submit_btn: Button | None, _stop_btn: Button | None
+ ):
+ if self.live:
+ if self.interface_type == InterfaceTypes.OUTPUT_ONLY:
+ if _submit_btn is None:
+ raise RenderError("Submit button not rendered")
+ super().load(self.fn, None, self.output_components)
+ # For output-only interfaces, the user probably still want a "generate"
+ # button even if the Interface is live
+ _submit_btn.click(
+ self.fn,
+ None,
+ self.output_components,
+ api_name=self.api_name,
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ batch=self.batch,
+ max_batch_size=self.max_batch_size,
+ )
+ else:
+ events: list[Callable] = []
+ for component in self.input_components:
+ if component.has_event("stream") and component.streaming: # type: ignore
+ events.append(component.stream) # type: ignore
+ elif component.has_event("change"):
+ events.append(component.change) # type: ignore
+ on(
+ events,
+ self.fn,
+ self.input_components,
+ self.output_components,
+ api_name=self.api_name,
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ )
+ else:
+ if _submit_btn is None:
+ raise RenderError("Submit button not rendered")
+ fn = self.fn
+ extra_output = []
+
+ triggers = [_submit_btn.click] + [
+ component.submit # type: ignore
+ for component in self.input_components
+ if component.has_event(Events.submit)
+ ]
+
+ if _stop_btn:
+ extra_output = [_submit_btn, _stop_btn]
+
+ def cleanup():
+ return [Button(visible=True), Button(visible=False)]
+
+ predict_event = on(
+ triggers,
+ lambda: (
+ Button(visible=False),
+ Button(visible=True),
+ ),
+ inputs=None,
+ outputs=[_submit_btn, _stop_btn],
+ queue=False,
+ show_api=False,
+ ).then(
+ self.fn,
+ self.input_components,
+ self.output_components,
+ api_name=self.api_name,
+ scroll_to_output=True,
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ batch=self.batch,
+ max_batch_size=self.max_batch_size,
+ concurrency_limit=self.concurrency_limit,
+ )
+
+ predict_event.then(
+ cleanup,
+ inputs=None,
+ outputs=extra_output, # type: ignore
+ queue=False,
+ show_api=False,
+ )
+
+ _stop_btn.click(
+ cleanup,
+ inputs=None,
+ outputs=[_submit_btn, _stop_btn],
+ cancels=predict_event,
+ queue=False,
+ show_api=False,
+ )
+ else:
+ on(
+ triggers,
+ fn,
+ self.input_components,
+ self.output_components,
+ api_name=self.api_name,
+ scroll_to_output=True,
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ batch=self.batch,
+ max_batch_size=self.max_batch_size,
+ concurrency_limit=self.concurrency_limit,
+ )
+
+ def attach_clear_events(
+ self,
+ _clear_btn: ClearButton,
+ input_component_column: Column | None,
+ ):
+ _clear_btn.add(self.input_components + self.output_components)
+ _clear_btn.click(
+ None,
+ [],
+ ([input_component_column] if input_component_column else []), # type: ignore
+ js=f"""() => {json.dumps(
+
+ [{'variant': None, 'visible': True, '__type__': 'update'}]
+ if self.interface_type
+ in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ ]
+ else []
+
+ )}
+ """,
+ )
+
+ def attach_flagging_events(
+ self, flag_btns: list[Button] | None, _clear_btn: ClearButton
+ ):
+ if not (
+ flag_btns
+ and self.interface_type
+ in (
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ )
+ ):
+ return
+
+ if self.allow_flagging == "auto":
+ flag_method = FlagMethod(
+ self.flagging_callback, "", "", visual_feedback=False
+ )
+ flag_btns[0].click( # flag_btns[0] is just the "Submit" button
+ flag_method,
+ inputs=self.input_components,
+ outputs=None,
+ preprocess=False,
+ queue=False,
+ show_api=False,
+ )
+ return
+
+ if self.interface_type == InterfaceTypes.UNIFIED:
+ flag_components = self.input_components
+ else:
+ flag_components = self.input_components + self.output_components
+
+ for flag_btn, (label, value) in zip(flag_btns, self.flagging_options):
+ assert isinstance(value, str)
+ flag_method = FlagMethod(self.flagging_callback, label, value)
+ flag_btn.click(
+ lambda: Button(value="Saving...", interactive=False),
+ None,
+ flag_btn,
+ queue=False,
+ show_api=False,
+ )
+ flag_btn.click(
+ flag_method,
+ inputs=flag_components,
+ outputs=flag_btn,
+ preprocess=False,
+ queue=False,
+ show_api=False,
+ )
+ _clear_btn.click(
+ flag_method.reset, None, flag_btn, queue=False, show_api=False
+ )
+
+ def render_examples(self):
+ if self.examples:
+ non_state_inputs = [
+ c for c in self.input_components if not isinstance(c, State)
+ ]
+ non_state_outputs = [
+ c for c in self.output_components if not isinstance(c, State)
+ ]
+ self.examples_handler = Examples(
+ examples=self.examples,
+ inputs=non_state_inputs, # type: ignore
+ outputs=non_state_outputs, # type: ignore
+ fn=self.fn,
+ cache_examples=self.cache_examples,
+ examples_per_page=self.examples_per_page,
+ _api_mode=self.api_mode,
+ batch=self.batch,
+ )
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ repr = f"Gradio Interface for: {self.__name__}"
+ repr += f"\n{'-' * len(repr)}"
+ repr += "\ninputs:"
+ for component in self.input_components:
+ repr += f"\n|-{component}"
+ repr += "\noutputs:"
+ for component in self.output_components:
+ repr += f"\n|-{component}"
+ return repr
+
+
+@document()
+class TabbedInterface(Blocks):
+ """
+ A TabbedInterface is created by providing a list of Interfaces, each of which gets
+ rendered in a separate tab.
+ Demos: stt_or_tts
+ """
+
+ def __init__(
+ self,
+ interface_list: list[Interface],
+ tab_names: list[str] | None = None,
+ title: str | None = None,
+ theme: Theme | None = None,
+ analytics_enabled: bool | None = None,
+ css: str | None = None,
+ ):
+ """
+ Parameters:
+ interface_list: a list of interfaces to be rendered in tabs.
+ tab_names: a list of tab names. If None, the tab names will be "Tab 1", "Tab 2", etc.
+ title: a title for the interface; if provided, appears above the input and output components in large font. Also used as the tab title when opened in a browser window.
+ analytics_enabled: whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable or default to True.
+ css: custom css or path to custom css file to apply to entire Blocks
+ Returns:
+ a Gradio Tabbed Interface for the given interfaces
+ """
+ super().__init__(
+ title=title or "Gradio",
+ theme=theme,
+ analytics_enabled=analytics_enabled,
+ mode="tabbed_interface",
+ css=css,
+ )
+ if tab_names is None:
+ tab_names = [f"Tab {i}" for i in range(len(interface_list))]
+ with self:
+ if title:
+ Markdown(
+ f"{title} "
+ )
+ with Tabs():
+ for interface, tab_name in zip(interface_list, tab_names):
+ with Tab(label=tab_name):
+ interface.render()
+
+
+def close_all(verbose: bool = True) -> None:
+ for io in Interface.get_instances():
+ io.close(verbose)
diff --git a/gradio/ipython_ext.py b/gradio/ipython_ext.py
new file mode 100644
index 0000000000000000000000000000000000000000..b6bb8063930f2ff60fba39459ce0b7829987f959
--- /dev/null
+++ b/gradio/ipython_ext.py
@@ -0,0 +1,89 @@
+try:
+ from IPython.core.magic import (
+ needs_local_scope,
+ register_cell_magic,
+ )
+ from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring
+except ImportError:
+ pass
+
+import gradio as gr
+from gradio.networking import App
+from gradio.utils import BaseReloader
+
+
+class CellIdTracker:
+ """Determines the most recently run cell in the notebook.
+
+ Needed to keep track of which demo the user is updating.
+ """
+
+ def __init__(self, ipython):
+ ipython.events.register("pre_run_cell", self.pre_run_cell)
+ self.shell = ipython
+ self.current_cell: str = ""
+
+ def pre_run_cell(self, info):
+ self._current_cell = info.cell_id
+
+
+class JupyterReloader(BaseReloader):
+ """Swap a running blocks class in a notebook with the latest cell contents."""
+
+ def __init__(self, ipython) -> None:
+ super().__init__()
+ self._cell_tracker = CellIdTracker(ipython)
+ self._running: dict[str, gr.Blocks] = {}
+
+ @property
+ def current_cell(self):
+ return self._cell_tracker.current_cell
+
+ @property
+ def running_app(self) -> App:
+ assert self.running_demo.server
+ return self.running_demo.server.running_app # type: ignore
+
+ @property
+ def running_demo(self):
+ return self._running[self.current_cell]
+
+ def demo_tracked(self) -> bool:
+ return self.current_cell in self._running
+
+ def track(self, demo: gr.Blocks):
+ self._running[self.current_cell] = demo
+
+
+def load_ipython_extension(ipython):
+ reloader = JupyterReloader(ipython)
+
+ @magic_arguments()
+ @argument("--demo-name", default="demo", help="Name of gradio blocks instance.")
+ @argument(
+ "--share",
+ default=False,
+ const=True,
+ nargs="?",
+ help="Whether to launch with sharing. Will slow down reloading.",
+ )
+ @register_cell_magic
+ @needs_local_scope
+ def blocks(line, cell, local_ns):
+ """Launch a demo defined in a cell in reload mode."""
+
+ args = parse_argstring(blocks, line)
+
+ exec(cell, None, local_ns)
+ demo: gr.Blocks = local_ns[args.demo_name]
+ if not reloader.demo_tracked():
+ demo.launch(share=args.share)
+ reloader.track(demo)
+ elif reloader.queue_changed(demo):
+ print("Queue got added or removed. Restarting demo.")
+ reloader.running_demo.close()
+ demo.launch()
+ reloader.track(demo)
+ else:
+ reloader.swap_blocks(demo)
+ return reloader.running_demo.artifact
diff --git a/gradio/layouts/__init__.py b/gradio/layouts/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0513b93c6aa6bd147ac88f62a432bab9f45fa88
--- /dev/null
+++ b/gradio/layouts/__init__.py
@@ -0,0 +1,17 @@
+from .accordion import Accordion
+from .column import Column
+from .form import Form
+from .group import Group
+from .row import Row
+from .tabs import Tab, TabItem, Tabs
+
+__all__ = [
+ "Accordion",
+ "Column",
+ "Form",
+ "Row",
+ "Group",
+ "Tabs",
+ "Tab",
+ "TabItem",
+]
diff --git a/gradio/layouts/accordion.py b/gradio/layouts/accordion.py
new file mode 100644
index 0000000000000000000000000000000000000000..5346b7eb927514291843a5c1618f1062ff1963a9
--- /dev/null
+++ b/gradio/layouts/accordion.py
@@ -0,0 +1,53 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+
+if TYPE_CHECKING:
+ pass
+
+set_documentation_group("layout")
+
+
+@document()
+class Accordion(BlockContext, metaclass=ComponentMeta):
+ """
+ Accordion is a layout element which can be toggled to show/hide the contained content.
+ Example:
+ with gr.Accordion("See Details"):
+ gr.Markdown("lorem ipsum")
+ """
+
+ EVENTS = []
+
+ def __init__(
+ self,
+ label: str | None = None,
+ *,
+ open: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ label: name of accordion section.
+ open: if True, accordion is open by default.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.label = label
+ self.open = open
+ BlockContext.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
diff --git a/gradio/layouts/column.py b/gradio/layouts/column.py
new file mode 100644
index 0000000000000000000000000000000000000000..76ad095c4abc0447376bfa714a3188a9ea019e52
--- /dev/null
+++ b/gradio/layouts/column.py
@@ -0,0 +1,70 @@
+from __future__ import annotations
+
+import warnings
+from typing import Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+
+set_documentation_group("layout")
+
+
+@document()
+class Column(BlockContext, metaclass=ComponentMeta):
+ """
+ Column is a layout element within Blocks that renders all children vertically. The widths of columns can be set through the `scale` and `min_width` parameters.
+ If a certain scale results in a column narrower than min_width, the min_width parameter will win.
+ Example:
+ with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column(scale=1):
+ text1 = gr.Textbox()
+ text2 = gr.Textbox()
+ with gr.Column(scale=4):
+ btn1 = gr.Button("Button 1")
+ btn2 = gr.Button("Button 2")
+ Guides: controlling-layout
+ """
+
+ EVENTS = []
+
+ def __init__(
+ self,
+ *,
+ scale: int = 1,
+ min_width: int = 320,
+ variant: Literal["default", "panel", "compact"] = "default",
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ scale: relative width compared to adjacent Columns. For example, if Column A has scale=2, and Column B has scale=1, A will be twice as wide as B.
+ min_width: minimum pixel width of Column, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in a column narrower than min_width, the min_width parameter will be respected first.
+ variant: column type, 'default' (no background), 'panel' (gray background color and rounded corners), or 'compact' (rounded corners and no internal gap).
+ visible: If False, column will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ if scale != round(scale):
+ warnings.warn(
+ f"'scale' value should be an integer. Using {scale} will cause issues."
+ )
+
+ self.scale = scale
+ self.min_width = min_width
+ self.variant = variant
+ if variant == "compact":
+ self.allow_expected_parents = False
+ BlockContext.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
diff --git a/gradio/layouts/form.py b/gradio/layouts/form.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5a676b148395a00f39e557d048136b3305b978c
--- /dev/null
+++ b/gradio/layouts/form.py
@@ -0,0 +1,45 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from gradio_client.documentation import set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+from gradio.layouts.row import Row
+
+if TYPE_CHECKING:
+ from gradio.blocks import Block
+
+set_documentation_group("layout")
+
+
+class Form(BlockContext, metaclass=ComponentMeta):
+ EVENTS = []
+
+ def __init__(
+ self,
+ *,
+ scale: int = 0,
+ min_width: int = 0,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ scale: relative width compared to adjacent Columns. For example, if Column A has scale=2, and Column B has scale=1, A will be twice as wide as B.
+ min_width: minimum pixel width of Column, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in a column narrower than min_width, the min_width parameter will be respected first.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ self.scale = scale
+ self.min_width = min_width
+ BlockContext.__init__(
+ self,
+ render=render,
+ )
+
+ def add_child(self, child: Block):
+ if isinstance(self.parent, Row):
+ scale = getattr(child, "scale", None)
+ self.scale += 1 if scale is None else scale
+ self.min_width += getattr(child, "min_width", 0) or 0
+ BlockContext.add_child(self, child)
diff --git a/gradio/layouts/group.py b/gradio/layouts/group.py
new file mode 100644
index 0000000000000000000000000000000000000000..2be6ad59b2d8701a0f4ca115339ba274be515df1
--- /dev/null
+++ b/gradio/layouts/group.py
@@ -0,0 +1,45 @@
+from __future__ import annotations
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+
+set_documentation_group("layout")
+
+
+@document()
+class Group(BlockContext, metaclass=ComponentMeta):
+ """
+ Group is a layout element within Blocks which groups together children so that
+ they do not have any padding or margin between them.
+ Example:
+ with gr.Group():
+ gr.Textbox(label="First")
+ gr.Textbox(label="Last")
+ """
+
+ EVENTS = []
+
+ def __init__(
+ self,
+ *,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ visible: If False, group will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ BlockContext.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
diff --git a/gradio/layouts/row.py b/gradio/layouts/row.py
new file mode 100644
index 0000000000000000000000000000000000000000..7af6922478118e1fc28569218ac081a6dc3d34a8
--- /dev/null
+++ b/gradio/layouts/row.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from typing import Literal
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+
+set_documentation_group("layout")
+
+
+@document()
+class Row(BlockContext, metaclass=ComponentMeta):
+ """
+ Row is a layout element within Blocks that renders all children horizontally.
+ Example:
+ with gr.Blocks() as demo:
+ with gr.Row():
+ gr.Image("lion.jpg", scale=2)
+ gr.Image("tiger.jpg", scale=1)
+ demo.launch()
+ Guides: controlling-layout
+ """
+
+ EVENTS = []
+
+ def __init__(
+ self,
+ *,
+ variant: Literal["default", "panel", "compact"] = "default",
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ equal_height: bool = True,
+ ):
+ """
+ Parameters:
+ variant: row type, 'default' (no background), 'panel' (gray background color and rounded corners), or 'compact' (rounded corners and no internal gap).
+ visible: If False, row will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ equal_height: If True, makes every child element have equal height
+ """
+ self.variant = variant
+ self.equal_height = equal_height
+ if variant == "compact":
+ self.allow_expected_parents = False
+ BlockContext.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+
+ @staticmethod
+ def update(
+ visible: bool | None = None,
+ ):
+ return {
+ "visible": visible,
+ "__type__": "update",
+ }
diff --git a/gradio/layouts/tabs.py b/gradio/layouts/tabs.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ef86edc2b7774d5f3d8c2ce9519e7364ea97928
--- /dev/null
+++ b/gradio/layouts/tabs.py
@@ -0,0 +1,102 @@
+from __future__ import annotations
+
+from gradio_client.documentation import document, set_documentation_group
+
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+from gradio.events import Events
+
+set_documentation_group("layout")
+
+
+class Tabs(BlockContext, metaclass=ComponentMeta):
+ """
+ Tabs is a layout element within Blocks that can contain multiple "Tab" Components.
+ """
+
+ EVENTS = [Events.change, Events.select]
+
+ def __init__(
+ self,
+ *,
+ selected: int | str | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ selected: The currently selected tab. Must correspond to an id passed to the one of the child TabItems. Defaults to the first TabItem.
+ visible: If False, Tabs will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ """
+ BlockContext.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+ self.selected = selected
+
+
+@document()
+class Tab(BlockContext, metaclass=ComponentMeta):
+ """
+ Tab (or its alias TabItem) is a layout element. Components defined within the Tab will be visible when this tab is selected tab.
+ Example:
+ with gr.Blocks() as demo:
+ with gr.Tab("Lion"):
+ gr.Image("lion.jpg")
+ gr.Button("New Lion")
+ with gr.Tab("Tiger"):
+ gr.Image("tiger.jpg")
+ gr.Button("New Tiger")
+ Guides: controlling-layout
+ """
+
+ EVENTS = [Events.select]
+
+ def __init__(
+ self,
+ label: str | None = None,
+ visible: bool = True,
+ interactive: bool = True,
+ *,
+ id: int | str | None = None,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ """
+ Parameters:
+ label: The visual label for the tab
+ id: An optional identifier for the tab, required if you wish to control the selected tab from a predict function.
+ elem_id: An optional string that is assigned as the id of the containing the contents of the Tab layout. The same string followed by "-button" is attached to the Tab button. Can be used for targeting CSS styles.
+ elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles.
+ render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
+ visible: If False, Tab will be hidden.
+ interactive: If False, Tab will not be clickable.
+ """
+ BlockContext.__init__(
+ self,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+ self.label = label
+ self.id = id
+ self.visible = visible
+ self.interactive = interactive
+
+ def get_expected_parent(self) -> type[Tabs]:
+ return Tabs
+
+ def get_block_name(self):
+ return "tabitem"
+
+
+TabItem = Tab
diff --git a/gradio/networking.py b/gradio/networking.py
new file mode 100644
index 0000000000000000000000000000000000000000..b22d9886ea8697d5987d0b4935c05e1bc29da675
--- /dev/null
+++ b/gradio/networking.py
@@ -0,0 +1,258 @@
+"""
+Defines helper methods useful for setting up ports, launching servers, and
+creating tunnels.
+"""
+from __future__ import annotations
+
+import os
+import socket
+import threading
+import time
+import warnings
+from functools import partial
+from typing import TYPE_CHECKING
+
+import httpx
+import uvicorn
+from uvicorn.config import Config
+
+from gradio.exceptions import ServerFailedToStartError
+from gradio.routes import App
+from gradio.tunneling import Tunnel
+from gradio.utils import SourceFileReloader, watchfn
+
+if TYPE_CHECKING: # Only import for type checking (to avoid circular imports).
+ from gradio.blocks import Blocks
+
+# By default, the local server will try to open on localhost, port 7860.
+# If that is not available, then it will try 7861, 7862, ... 7959.
+INITIAL_PORT_VALUE = int(os.getenv("GRADIO_SERVER_PORT", "7860"))
+TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100"))
+LOCALHOST_NAME = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
+GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"
+GRADIO_SHARE_SERVER_ADDRESS = os.getenv("GRADIO_SHARE_SERVER_ADDRESS")
+
+should_watch = bool(os.getenv("GRADIO_WATCH_DIRS", False))
+GRADIO_WATCH_DIRS = (
+ os.getenv("GRADIO_WATCH_DIRS", "").split(",") if should_watch else []
+)
+GRADIO_WATCH_MODULE_NAME = os.getenv("GRADIO_WATCH_MODULE_NAME", "app")
+GRADIO_WATCH_DEMO_NAME = os.getenv("GRADIO_WATCH_DEMO_NAME", "demo")
+
+
+class Server(uvicorn.Server):
+ def __init__(
+ self, config: Config, reloader: SourceFileReloader | None = None
+ ) -> None:
+ self.running_app = config.app
+ super().__init__(config)
+ self.reloader = reloader
+ if self.reloader:
+ self.event = threading.Event()
+ self.watch = partial(watchfn, self.reloader)
+
+ def install_signal_handlers(self):
+ pass
+
+ def run_in_thread(self):
+ self.thread = threading.Thread(target=self.run, daemon=True)
+ if self.reloader:
+ self.watch_thread = threading.Thread(target=self.watch, daemon=True)
+ self.watch_thread.start()
+ self.thread.start()
+ start = time.time()
+ while not self.started:
+ time.sleep(1e-3)
+ if time.time() - start > 5:
+ raise ServerFailedToStartError(
+ "Server failed to start. Please check that the port is available."
+ )
+
+ def close(self):
+ self.should_exit = True
+ if self.reloader:
+ self.reloader.stop()
+ self.watch_thread.join()
+ self.thread.join()
+
+
+def get_first_available_port(initial: int, final: int) -> int:
+ """
+ Gets the first open port in a specified range of port numbers
+ Parameters:
+ initial: the initial value in the range of port numbers
+ final: final (exclusive) value in the range of port numbers, should be greater than `initial`
+ Returns:
+ port: the first open port in the range
+ """
+ for port in range(initial, final):
+ try:
+ s = socket.socket() # create a socket object
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind((LOCALHOST_NAME, port)) # Bind to the port
+ s.close()
+ return port
+ except OSError:
+ pass
+ raise OSError(
+ f"All ports from {initial} to {final - 1} are in use. Please close a port."
+ )
+
+
+def configure_app(app: App, blocks: Blocks) -> App:
+ auth = blocks.auth
+ if auth is not None:
+ if not callable(auth):
+ app.auth = {account[0]: account[1] for account in auth}
+ else:
+ app.auth = auth
+ else:
+ app.auth = None
+ app.blocks = blocks
+ app.cwd = os.getcwd()
+ app.favicon_path = blocks.favicon_path
+ app.tokens = {}
+ return app
+
+
+def start_server(
+ blocks: Blocks,
+ server_name: str | None = None,
+ server_port: int | None = None,
+ ssl_keyfile: str | None = None,
+ ssl_certfile: str | None = None,
+ ssl_keyfile_password: str | None = None,
+ app_kwargs: dict | None = None,
+) -> tuple[str, int, str, App, Server]:
+ """Launches a local server running the provided Interface
+ Parameters:
+ blocks: The Blocks object to run on the server
+ server_name: to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME.
+ server_port: will start gradio app on this port (if available). Can be set by environment variable GRADIO_SERVER_PORT.
+ auth: If provided, username and password (or list of username-password tuples) required to access the Blocks. Can also provide function that takes username and password and returns True if valid login.
+ ssl_keyfile: If a path to a file is provided, will use this as the private key file to create a local server running on https.
+ ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
+ ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
+ app_kwargs: Additional keyword arguments to pass to the gradio.routes.App constructor.
+
+ Returns:
+ port: the port number the server is running on
+ path_to_local_server: the complete address that the local server can be accessed at
+ app: the FastAPI app object
+ server: the server object that is a subclass of uvicorn.Server (used to close the server)
+ """
+ if ssl_keyfile is not None and ssl_certfile is None:
+ raise ValueError("ssl_certfile must be provided if ssl_keyfile is provided.")
+
+ server_name = server_name or LOCALHOST_NAME
+ url_host_name = "localhost" if server_name == "0.0.0.0" else server_name
+
+ # Strip IPv6 brackets from the address if they exist.
+ # This is needed as http://[::1]:port/ is a valid browser address,
+ # but not a valid IPv6 address, so asyncio will throw an exception.
+ if server_name.startswith("[") and server_name.endswith("]"):
+ host = server_name[1:-1]
+ else:
+ host = server_name
+
+ app = App.create_app(blocks, app_kwargs=app_kwargs)
+
+ server_ports = (
+ [server_port]
+ if server_port is not None
+ else range(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS)
+ )
+
+ for port in server_ports:
+ try:
+ # The fastest way to check if a port is available is to try to bind to it with socket.
+ # If the port is not available, socket will throw an OSError.
+ s = socket.socket()
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ # Really, we should be checking if (server_name, server_port) is available, but
+ # socket.bind() doesn't seem to throw an OSError with ipv6 addresses, based on my testing.
+ # Instead, we just check if the port is available on localhost.
+ s.bind((LOCALHOST_NAME, port))
+ s.close()
+
+ # To avoid race conditions, so we also check if the port by trying to start the uvicorn server.
+ # If the port is not available, this will throw a ServerFailedToStartError.
+ config = uvicorn.Config(
+ app=app,
+ port=port,
+ host=host,
+ log_level="warning",
+ ssl_keyfile=ssl_keyfile,
+ ssl_certfile=ssl_certfile,
+ ssl_keyfile_password=ssl_keyfile_password,
+ )
+ reloader = None
+ if GRADIO_WATCH_DIRS:
+ change_event = threading.Event()
+ app.change_event = change_event
+ reloader = SourceFileReloader(
+ app=app,
+ watch_dirs=GRADIO_WATCH_DIRS,
+ watch_module_name=GRADIO_WATCH_MODULE_NAME,
+ demo_name=GRADIO_WATCH_DEMO_NAME,
+ stop_event=threading.Event(),
+ change_event=change_event,
+ )
+ server = Server(config=config, reloader=reloader)
+ server.run_in_thread()
+ break
+ except (OSError, ServerFailedToStartError):
+ pass
+ else:
+ raise OSError(
+ f"Cannot find empty port in range: {min(server_ports)}-{max(server_ports)}. You can specify a different port by setting the GRADIO_SERVER_PORT environment variable or passing the `server_port` parameter to `launch()`."
+ )
+
+ if ssl_keyfile is not None:
+ path_to_local_server = f"https://{url_host_name}:{port}/"
+ else:
+ path_to_local_server = f"http://{url_host_name}:{port}/"
+
+ return server_name, port, path_to_local_server, app, server
+
+
+def setup_tunnel(
+ local_host: str, local_port: int, share_token: str, share_server_address: str | None
+) -> str:
+ share_server_address = (
+ GRADIO_SHARE_SERVER_ADDRESS
+ if share_server_address is None
+ else share_server_address
+ )
+ if share_server_address is None:
+ try:
+ response = httpx.get(GRADIO_API_SERVER, timeout=30)
+ payload = response.json()[0]
+ remote_host, remote_port = payload["host"], int(payload["port"])
+ except Exception as e:
+ raise RuntimeError(
+ "Could not get share link from Gradio API Server."
+ ) from e
+ else:
+ remote_host, remote_port = share_server_address.split(":")
+ remote_port = int(remote_port)
+ try:
+ tunnel = Tunnel(remote_host, remote_port, local_host, local_port, share_token)
+ address = tunnel.start_tunnel()
+ return address
+ except Exception as e:
+ raise RuntimeError(str(e)) from e
+
+
+def url_ok(url: str) -> bool:
+ try:
+ for _ in range(5):
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore")
+ r = httpx.head(url, timeout=3, verify=False)
+ if r.status_code in (200, 401, 302): # 401 or 302 if auth is set
+ return True
+ time.sleep(0.500)
+ except (ConnectionError, httpx.ConnectError):
+ return False
+ return False
diff --git a/gradio/oauth.py b/gradio/oauth.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d757fbd79e7fe26f8ea18dfc20c666a45a4f18b
--- /dev/null
+++ b/gradio/oauth.py
@@ -0,0 +1,293 @@
+from __future__ import annotations
+
+import hashlib
+import os
+import typing
+import urllib.parse
+import warnings
+from dataclasses import dataclass, field
+
+import fastapi
+from fastapi.responses import RedirectResponse
+from huggingface_hub import HfFolder, whoami
+
+from .utils import get_space
+
+OAUTH_CLIENT_ID = os.environ.get("OAUTH_CLIENT_ID")
+OAUTH_CLIENT_SECRET = os.environ.get("OAUTH_CLIENT_SECRET")
+OAUTH_SCOPES = os.environ.get("OAUTH_SCOPES")
+OPENID_PROVIDER_URL = os.environ.get("OPENID_PROVIDER_URL")
+
+
+def attach_oauth(app: fastapi.FastAPI):
+ try:
+ from starlette.middleware.sessions import SessionMiddleware
+ except ImportError as e:
+ raise ImportError(
+ "Cannot initialize OAuth to due a missing library. Please run `pip install gradio[oauth]` or add "
+ "`gradio[oauth]` to your requirements.txt file in order to install the required dependencies."
+ ) from e
+
+ # Add `/login/huggingface`, `/login/callback` and `/logout` routes to enable OAuth in the Gradio app.
+ # If the app is running in a Space, OAuth is enabled normally. Otherwise, we mock the "real" routes to make the
+ # user log in with a fake user profile - without any calls to hf.co.
+ if get_space() is not None:
+ _add_oauth_routes(app)
+ else:
+ _add_mocked_oauth_routes(app)
+
+ # Session Middleware requires a secret key to sign the cookies. Let's use a hash
+ # of the OAuth secret key to make it unique to the Space + updated in case OAuth
+ # config gets updated.
+ session_secret = (OAUTH_CLIENT_SECRET or "") + "-v2"
+ # ^ if we change the session cookie format in the future, we can bump the version of the session secret to make
+ # sure cookies are invalidated. Otherwise some users with an old cookie format might get a HTTP 500 error.
+ app.add_middleware(
+ SessionMiddleware,
+ secret_key=hashlib.sha256(session_secret.encode()).hexdigest(),
+ same_site="none",
+ https_only=True,
+ )
+
+
+def _add_oauth_routes(app: fastapi.FastAPI) -> None:
+ """Add OAuth routes to the FastAPI app (login, callback handler and logout)."""
+ try:
+ from authlib.integrations.starlette_client import OAuth
+ except ImportError as e:
+ raise ImportError(
+ "Cannot initialize OAuth to due a missing library. Please run `pip install gradio[oauth]` or add "
+ "`gradio[oauth]` to your requirements.txt file in order to install the required dependencies."
+ ) from e
+
+ # Check environment variables
+ msg = (
+ "OAuth is required but {} environment variable is not set. Make sure you've enabled OAuth in your Space by"
+ " setting `hf_oauth: true` in the Space metadata."
+ )
+ if OAUTH_CLIENT_ID is None:
+ raise ValueError(msg.format("OAUTH_CLIENT_ID"))
+ if OAUTH_CLIENT_SECRET is None:
+ raise ValueError(msg.format("OAUTH_CLIENT_SECRET"))
+ if OAUTH_SCOPES is None:
+ raise ValueError(msg.format("OAUTH_SCOPES"))
+ if OPENID_PROVIDER_URL is None:
+ raise ValueError(msg.format("OPENID_PROVIDER_URL"))
+
+ # Register OAuth server
+ oauth = OAuth()
+ oauth.register(
+ name="huggingface",
+ client_id=OAUTH_CLIENT_ID,
+ client_secret=OAUTH_CLIENT_SECRET,
+ client_kwargs={"scope": OAUTH_SCOPES},
+ server_metadata_url=OPENID_PROVIDER_URL + "/.well-known/openid-configuration",
+ )
+
+ # Define OAuth routes
+ @app.get("/login/huggingface")
+ async def oauth_login(request: fastapi.Request):
+ """Endpoint that redirects to HF OAuth page."""
+ # Define target (where to redirect after login)
+ redirect_uri = _generate_redirect_uri(request)
+ return await oauth.huggingface.authorize_redirect(request, redirect_uri) # type: ignore
+
+ @app.get("/login/callback")
+ async def oauth_redirect_callback(request: fastapi.Request) -> RedirectResponse:
+ """Endpoint that handles the OAuth callback."""
+ oauth_info = await oauth.huggingface.authorize_access_token(request) # type: ignore
+ request.session["oauth_info"] = oauth_info
+ return _redirect_to_target(request)
+
+ @app.get("/logout")
+ async def oauth_logout(request: fastapi.Request) -> RedirectResponse:
+ """Endpoint that logs out the user (e.g. delete cookie session)."""
+ request.session.pop("oauth_info", None)
+ return _redirect_to_target(request)
+
+
+def _add_mocked_oauth_routes(app: fastapi.FastAPI) -> None:
+ """Add fake oauth routes if Gradio is run locally and OAuth is enabled.
+
+ Clicking on a gr.LoginButton will have the same behavior as in a Space (i.e. gets redirected in a new tab) but
+ instead of authenticating with HF, a mocked user profile is added to the session.
+ """
+ warnings.warn(
+ "Gradio does not support OAuth features outside of a Space environment. To help"
+ " you debug your app locally, the login and logout buttons are mocked with your"
+ " profile. To make it work, your machine must be logged in to Huggingface."
+ )
+ mocked_oauth_info = _get_mocked_oauth_info()
+
+ # Define OAuth routes
+ @app.get("/login/huggingface")
+ async def oauth_login(request: fastapi.Request):
+ """Fake endpoint that redirects to HF OAuth page."""
+ # Define target (where to redirect after login)
+ redirect_uri = _generate_redirect_uri(request)
+ return RedirectResponse(
+ "/login/callback?" + urllib.parse.urlencode({"_target_url": redirect_uri})
+ )
+
+ @app.get("/login/callback")
+ async def oauth_redirect_callback(request: fastapi.Request) -> RedirectResponse:
+ """Endpoint that handles the OAuth callback."""
+ request.session["oauth_info"] = mocked_oauth_info
+ return _redirect_to_target(request)
+
+ @app.get("/logout")
+ async def oauth_logout(request: fastapi.Request) -> RedirectResponse:
+ """Endpoint that logs out the user (e.g. delete cookie session)."""
+ request.session.pop("oauth_info", None)
+ logout_url = str(request.url).replace("/logout", "/") # preserve query params
+ return RedirectResponse(url=logout_url)
+
+
+def _generate_redirect_uri(request: fastapi.Request) -> str:
+ if "_target_url" in request.query_params:
+ # if `_target_url` already in query params => respect it
+ target = request.query_params["_target_url"]
+ else:
+ # otherwise => keep query params
+ target = "/?" + urllib.parse.urlencode(request.query_params)
+
+ redirect_uri = request.url_for("oauth_redirect_callback").include_query_params(
+ _target_url=target
+ )
+ redirect_uri_as_str = str(redirect_uri)
+ if redirect_uri.netloc.endswith(".hf.space"):
+ # In Space, FastAPI redirect as http but we want https
+ redirect_uri_as_str = redirect_uri_as_str.replace("http://", "https://")
+ return redirect_uri_as_str
+
+
+def _redirect_to_target(
+ request: fastapi.Request, default_target: str = "/"
+) -> RedirectResponse:
+ target = request.query_params.get("_target_url", default_target)
+ return RedirectResponse(target)
+
+
+@dataclass
+class OAuthProfile(typing.Dict): # inherit from Dict for backward compatibility
+ """
+ A Gradio OAuthProfile object that can be used to inject the profile of a user in a
+ function. If a function expects `OAuthProfile` or `Optional[OAuthProfile]` as input,
+ the value will be injected from the FastAPI session if the user is logged in. If the
+ user is not logged in and the function expects `OAuthProfile`, an error will be
+ raised.
+
+ Attributes:
+ name (str): The name of the user (e.g. 'Abubakar Abid').
+ username (str): The username of the user (e.g. 'abidlabs')
+ profile (str): The profile URL of the user (e.g. 'https://huggingface.co/abidlabs').
+ picture (str): The profile picture URL of the user.
+
+ Example:
+ import gradio as gr
+ from typing import Optional
+
+
+ def hello(profile: Optional[gr.OAuthProfile]) -> str:
+ if profile is None:
+ return "I don't know you."
+ return f"Hello {profile.name}"
+
+
+ with gr.Blocks() as demo:
+ gr.LoginButton()
+ gr.LogoutButton()
+ gr.Markdown().attach_load_event(hello, None)
+ """
+
+ name: str = field(init=False)
+ username: str = field(init=False)
+ profile: str = field(init=False)
+ picture: str = field(init=False)
+
+ def __init__(self, data: dict): # hack to make OAuthProfile backward compatible
+ self.update(data)
+ self.name = self["name"]
+ self.username = self["preferred_username"]
+ self.profile = self["profile"]
+ self.picture = self["picture"]
+
+
+@dataclass
+class OAuthToken:
+ """
+ A Gradio OAuthToken object that can be used to inject the access token of a user in a
+ function. If a function expects `OAuthToken` or `Optional[OAuthToken]` as input,
+ the value will be injected from the FastAPI session if the user is logged in. If the
+ user is not logged in and the function expects `OAuthToken`, an error will be
+ raised.
+
+ Attributes:
+ token (str): The access token of the user.
+ scope (str): The scope of the access token.
+ expires_at (int): The expiration timestamp of the access token.
+
+ Example:
+ import gradio as gr
+ from typing import Optional
+ from huggingface_hub import whoami
+
+
+ def list_organizations(oauth_token: Optional[gr.OAuthToken]) -> str:
+ if oauth_token is None:
+ return "Please log in to list organizations."
+ org_names = [org["name"] for org in whoami(oauth_token.token)["orgs"]]
+ return f"You belong to {', '.join(org_names)}."
+
+
+ with gr.Blocks() as demo:
+ gr.LoginButton()
+ gr.LogoutButton()
+ gr.Markdown().attach_load_event(list_organizations, None)
+ """
+
+ token: str
+ scope: str
+ expires_at: int
+
+
+def _get_mocked_oauth_info() -> typing.Dict:
+ token = HfFolder.get_token()
+ if token is None:
+ raise ValueError(
+ "Your machine must be logged in to HF to debug a Gradio app locally. Please"
+ " run `huggingface-cli login` or set `HF_TOKEN` as environment variable "
+ "with one of your access token. You can generate a new token in your "
+ "settings page (https://huggingface.co/settings/tokens)."
+ )
+
+ user = whoami()
+ if user["type"] != "user":
+ raise ValueError(
+ "Your machine is not logged in with a personal account. Please use a "
+ "personal access token. You can generate a new token in your settings page"
+ " (https://huggingface.co/settings/tokens)."
+ )
+
+ return {
+ "access_token": token,
+ "token_type": "bearer",
+ "expires_in": 3600,
+ "id_token": "AAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "scope": "openid profile",
+ "expires_at": 1691676444,
+ "userinfo": {
+ "sub": "11111111111111111111111",
+ "name": user["fullname"],
+ "preferred_username": user["name"],
+ "profile": f"https://huggingface.co/{user['name']}",
+ "picture": user["avatarUrl"],
+ "website": "",
+ "aud": "00000000-0000-0000-0000-000000000000",
+ "auth_time": 1691672844,
+ "nonce": "aaaaaaaaaaaaaaaaaaa",
+ "iat": 1691672844,
+ "exp": 1691676444,
+ "iss": "https://huggingface.co",
+ },
+ }
diff --git a/gradio/package.json b/gradio/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..378ff4c52753b49e614ddfa26200f711237b248b
--- /dev/null
+++ b/gradio/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "gradio",
+ "version": "4.16.0",
+ "description": "",
+ "python": "true"
+}
diff --git a/gradio/pipelines.py b/gradio/pipelines.py
new file mode 100644
index 0000000000000000000000000000000000000000..875a5b011de770160962e998626fd4b1132a6118
--- /dev/null
+++ b/gradio/pipelines.py
@@ -0,0 +1,270 @@
+"""This module should not be used directly as its API is subject to change. Instead,
+please use the `gr.Interface.from_pipeline()` function."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from gradio import components
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from transformers import pipelines
+
+
+def load_from_pipeline(pipeline: pipelines.base.Pipeline) -> dict:
+ """
+ Gets the appropriate Interface kwargs for a given Hugging Face transformers.Pipeline.
+ pipeline (transformers.Pipeline): the transformers.Pipeline from which to create an interface
+ Returns:
+ (dict): a dictionary of kwargs that can be used to construct an Interface object
+ """
+ try:
+ import transformers
+ from transformers import pipelines
+ except ImportError as ie:
+ raise ImportError(
+ "transformers not installed. Please try `pip install transformers`"
+ ) from ie
+ if not isinstance(pipeline, pipelines.base.Pipeline):
+ raise ValueError("pipeline must be a transformers.Pipeline")
+
+ # Handle the different pipelines. The has_attr() checks to make sure the pipeline exists in the
+ # version of the transformers library that the user has installed.
+ if hasattr(transformers, "AudioClassificationPipeline") and isinstance(
+ pipeline, pipelines.audio_classification.AudioClassificationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Audio(
+ sources=["microphone"],
+ type="filepath",
+ label="Input",
+ render=False,
+ ),
+ "outputs": components.Label(label="Class", render=False),
+ "preprocess": lambda i: {"inputs": i},
+ "postprocess": lambda r: {i["label"].split(", ")[0]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "AutomaticSpeechRecognitionPipeline") and isinstance(
+ pipeline,
+ pipelines.automatic_speech_recognition.AutomaticSpeechRecognitionPipeline,
+ ):
+ pipeline_info = {
+ "inputs": components.Audio(
+ sources=["microphone"], type="filepath", label="Input", render=False
+ ),
+ "outputs": components.Textbox(label="Output", render=False),
+ "preprocess": lambda i: {"inputs": i},
+ "postprocess": lambda r: r["text"],
+ }
+ elif hasattr(transformers, "FeatureExtractionPipeline") and isinstance(
+ pipeline, pipelines.feature_extraction.FeatureExtractionPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Dataframe(label="Output", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r[0],
+ }
+ elif hasattr(transformers, "FillMaskPipeline") and isinstance(
+ pipeline, pipelines.fill_mask.FillMaskPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: {i["token_str"]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "ImageClassificationPipeline") and isinstance(
+ pipeline, pipelines.image_classification.ImageClassificationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Image(
+ type="filepath", label="Input Image", render=False
+ ),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda i: {"images": i},
+ "postprocess": lambda r: {i["label"].split(", ")[0]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "QuestionAnsweringPipeline") and isinstance(
+ pipeline, pipelines.question_answering.QuestionAnsweringPipeline
+ ):
+ pipeline_info = {
+ "inputs": [
+ components.Textbox(lines=7, label="Context", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": [
+ components.Textbox(label="Answer", render=False),
+ components.Label(label="Score", render=False),
+ ],
+ "preprocess": lambda c, q: {"context": c, "question": q},
+ "postprocess": lambda r: (r["answer"], r["score"]),
+ }
+ elif hasattr(transformers, "SummarizationPipeline") and isinstance(
+ pipeline, pipelines.text2text_generation.SummarizationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(lines=7, label="Input", render=False),
+ "outputs": components.Textbox(label="Summary", render=False),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r[0]["summary_text"],
+ }
+ elif hasattr(transformers, "TextClassificationPipeline") and isinstance(
+ pipeline, pipelines.text_classification.TextClassificationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda x: [x],
+ "postprocess": lambda r: {i["label"].split(", ")[0]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "TextGenerationPipeline") and isinstance(
+ pipeline, pipelines.text_generation.TextGenerationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Output", render=False),
+ "preprocess": lambda x: {"text_inputs": x},
+ "postprocess": lambda r: r[0]["generated_text"],
+ }
+ elif hasattr(transformers, "TranslationPipeline") and isinstance(
+ pipeline, pipelines.text2text_generation.TranslationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Translation", render=False),
+ "preprocess": lambda x: [x],
+ "postprocess": lambda r: r[0]["translation_text"],
+ }
+ elif hasattr(transformers, "Text2TextGenerationPipeline") and isinstance(
+ pipeline, pipelines.text2text_generation.Text2TextGenerationPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Textbox(label="Input", render=False),
+ "outputs": components.Textbox(label="Generated Text", render=False),
+ "preprocess": lambda x: [x],
+ "postprocess": lambda r: r[0]["generated_text"],
+ }
+ elif hasattr(transformers, "ZeroShotClassificationPipeline") and isinstance(
+ pipeline, pipelines.zero_shot_classification.ZeroShotClassificationPipeline
+ ):
+ pipeline_info = {
+ "inputs": [
+ components.Textbox(label="Input", render=False),
+ components.Textbox(
+ label="Possible class names (" "comma-separated)", render=False
+ ),
+ components.Checkbox(label="Allow multiple true classes", render=False),
+ ],
+ "outputs": components.Label(label="Classification", render=False),
+ "preprocess": lambda i, c, m: {
+ "sequences": i,
+ "candidate_labels": c,
+ "multi_label": m,
+ },
+ "postprocess": lambda r: {
+ r["labels"][i]: r["scores"][i] for i in range(len(r["labels"]))
+ },
+ }
+ elif hasattr(transformers, "DocumentQuestionAnsweringPipeline") and isinstance(
+ pipeline,
+ pipelines.document_question_answering.DocumentQuestionAnsweringPipeline, # type: ignore
+ ):
+ pipeline_info = {
+ "inputs": [
+ components.Image(type="filepath", label="Input Document", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": components.Label(label="Label", render=False),
+ "preprocess": lambda img, q: {"image": img, "question": q},
+ "postprocess": lambda r: {i["answer"]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "VisualQuestionAnsweringPipeline") and isinstance(
+ pipeline, pipelines.visual_question_answering.VisualQuestionAnsweringPipeline
+ ):
+ pipeline_info = {
+ "inputs": [
+ components.Image(type="filepath", label="Input Image", render=False),
+ components.Textbox(label="Question", render=False),
+ ],
+ "outputs": components.Label(label="Score", render=False),
+ "preprocess": lambda img, q: {"image": img, "question": q},
+ "postprocess": lambda r: {i["answer"]: i["score"] for i in r},
+ }
+ elif hasattr(transformers, "ImageToTextPipeline") and isinstance(
+ pipeline,
+ pipelines.image_to_text.ImageToTextPipeline, # type: ignore
+ ):
+ pipeline_info = {
+ "inputs": components.Image(
+ type="filepath", label="Input Image", render=False
+ ),
+ "outputs": components.Textbox(label="Text", render=False),
+ "preprocess": lambda i: {"images": i},
+ "postprocess": lambda r: r[0]["generated_text"],
+ }
+ elif hasattr(transformers, "ObjectDetectionPipeline") and isinstance(
+ pipeline, pipelines.object_detection.ObjectDetectionPipeline
+ ):
+ pipeline_info = {
+ "inputs": components.Image(
+ type="filepath", label="Input Image", render=False
+ ),
+ "outputs": components.AnnotatedImage(
+ label="Objects Detected", render=False
+ ),
+ "preprocess": lambda i: {"inputs": i},
+ "postprocess": lambda r, img: (
+ img,
+ [
+ (
+ (
+ i["box"]["xmin"],
+ i["box"]["ymin"],
+ i["box"]["xmax"],
+ i["box"]["ymax"],
+ ),
+ i["label"],
+ )
+ for i in r
+ ],
+ ),
+ }
+ else:
+ raise ValueError(f"Unsupported pipeline type: {type(pipeline)}")
+
+ # define the function that will be called by the Interface
+ def fn(*params):
+ data = pipeline_info["preprocess"](*params)
+ # special cases that needs to be handled differently
+ if isinstance(
+ pipeline,
+ (
+ pipelines.text_classification.TextClassificationPipeline,
+ pipelines.text2text_generation.Text2TextGenerationPipeline,
+ pipelines.text2text_generation.TranslationPipeline,
+ ),
+ ):
+ data = pipeline(*data)
+ else:
+ data = pipeline(**data)
+ # special case for object-detection
+ # original input image sent to postprocess function
+ if isinstance(
+ pipeline,
+ pipelines.object_detection.ObjectDetectionPipeline,
+ ):
+ output = pipeline_info["postprocess"](data, params[0])
+ else:
+ output = pipeline_info["postprocess"](data)
+ return output
+
+ interface_info = pipeline_info.copy()
+ interface_info["fn"] = fn
+ del interface_info["preprocess"]
+ del interface_info["postprocess"]
+
+ # define the title/description of the Interface
+ interface_info["title"] = pipeline.model.__class__.__name__
+
+ return interface_info
diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6d6f2c3c7c23f881f0cb6093c5ec75b67f3a209
--- /dev/null
+++ b/gradio/processing_utils.py
@@ -0,0 +1,739 @@
+from __future__ import annotations
+
+import base64
+import hashlib
+import json
+import logging
+import os
+import shutil
+import subprocess
+import tempfile
+import warnings
+from io import BytesIO
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, Literal
+
+import httpx
+import numpy as np
+from gradio_client import utils as client_utils
+from PIL import Image, ImageOps, PngImagePlugin
+
+from gradio import wasm_utils
+from gradio.data_classes import FileData, GradioModel, GradioRootModel
+from gradio.utils import abspath
+
+with warnings.catch_warnings():
+ warnings.simplefilter("ignore") # Ignore pydub warning if ffmpeg is not installed
+ from pydub import AudioSegment
+
+log = logging.getLogger(__name__)
+
+if TYPE_CHECKING:
+ from gradio.components.base import Component
+
+#########################
+# GENERAL
+#########################
+
+
+def to_binary(x: str | dict) -> bytes:
+ """Converts a base64 string or dictionary to a binary string that can be sent in a POST."""
+ if isinstance(x, dict):
+ if x.get("data"):
+ base64str = x["data"]
+ else:
+ base64str = client_utils.encode_url_or_file_to_base64(x["path"])
+ else:
+ base64str = x
+ return base64.b64decode(extract_base64_data(base64str))
+
+
+def extract_base64_data(x: str) -> str:
+ """Just extracts the base64 data from a general base64 string."""
+ return x.rsplit(",", 1)[-1]
+
+
+#########################
+# IMAGE PRE-PROCESSING
+#########################
+
+
+def encode_plot_to_base64(plt):
+ with BytesIO() as output_bytes:
+ plt.savefig(output_bytes, format="png")
+ bytes_data = output_bytes.getvalue()
+ base64_str = str(base64.b64encode(bytes_data), "utf-8")
+ return "data:image/png;base64," + base64_str
+
+
+def get_pil_metadata(pil_image):
+ # Copy any text-only metadata
+ metadata = PngImagePlugin.PngInfo()
+ for key, value in pil_image.info.items():
+ if isinstance(key, str) and isinstance(value, str):
+ metadata.add_text(key, value)
+
+ return metadata
+
+
+def encode_pil_to_bytes(pil_image, format="png"):
+ with BytesIO() as output_bytes:
+ pil_image.save(output_bytes, format, pnginfo=get_pil_metadata(pil_image))
+ return output_bytes.getvalue()
+
+
+def encode_pil_to_base64(pil_image):
+ bytes_data = encode_pil_to_bytes(pil_image)
+ base64_str = str(base64.b64encode(bytes_data), "utf-8")
+ return "data:image/png;base64," + base64_str
+
+
+def encode_array_to_base64(image_array):
+ with BytesIO() as output_bytes:
+ pil_image = Image.fromarray(_convert(image_array, np.uint8, force_copy=False))
+ pil_image.save(output_bytes, "PNG")
+ bytes_data = output_bytes.getvalue()
+ base64_str = str(base64.b64encode(bytes_data), "utf-8")
+ return "data:image/png;base64," + base64_str
+
+
+def hash_file(file_path: str | Path, chunk_num_blocks: int = 128) -> str:
+ sha1 = hashlib.sha1()
+ with open(file_path, "rb") as f:
+ for chunk in iter(lambda: f.read(chunk_num_blocks * sha1.block_size), b""):
+ sha1.update(chunk)
+ return sha1.hexdigest()
+
+
+def hash_url(url: str) -> str:
+ sha1 = hashlib.sha1()
+ sha1.update(url.encode("utf-8"))
+ return sha1.hexdigest()
+
+
+def hash_bytes(bytes: bytes):
+ sha1 = hashlib.sha1()
+ sha1.update(bytes)
+ return sha1.hexdigest()
+
+
+def hash_base64(base64_encoding: str, chunk_num_blocks: int = 128) -> str:
+ sha1 = hashlib.sha1()
+ for i in range(0, len(base64_encoding), chunk_num_blocks * sha1.block_size):
+ data = base64_encoding[i : i + chunk_num_blocks * sha1.block_size]
+ sha1.update(data.encode("utf-8"))
+ return sha1.hexdigest()
+
+
+def save_pil_to_cache(
+ img: Image.Image,
+ cache_dir: str,
+ name: str = "image",
+ format: Literal["png", "jpeg"] = "png",
+) -> str:
+ bytes_data = encode_pil_to_bytes(img, format)
+ temp_dir = Path(cache_dir) / hash_bytes(bytes_data)
+ temp_dir.mkdir(exist_ok=True, parents=True)
+ filename = str((temp_dir / f"{name}.{format}").resolve())
+ img.save(filename, pnginfo=get_pil_metadata(img))
+ return filename
+
+
+def save_img_array_to_cache(
+ arr: np.ndarray, cache_dir: str, format: Literal["png", "jpeg"] = "png"
+) -> str:
+ pil_image = Image.fromarray(_convert(arr, np.uint8, force_copy=False))
+ return save_pil_to_cache(pil_image, cache_dir, format=format)
+
+
+def save_audio_to_cache(
+ data: np.ndarray, sample_rate: int, format: str, cache_dir: str
+) -> str:
+ temp_dir = Path(cache_dir) / hash_bytes(data.tobytes())
+ temp_dir.mkdir(exist_ok=True, parents=True)
+ filename = str((temp_dir / f"audio.{format}").resolve())
+ audio_to_file(sample_rate, data, filename, format=format)
+ return filename
+
+
+def save_bytes_to_cache(data: bytes, file_name: str, cache_dir: str) -> str:
+ path = Path(cache_dir) / hash_bytes(data)
+ path.mkdir(exist_ok=True, parents=True)
+ path = path / Path(file_name).name
+ path.write_bytes(data)
+ return str(path.resolve())
+
+
+def save_file_to_cache(file_path: str | Path, cache_dir: str) -> str:
+ """Returns a temporary file path for a copy of the given file path if it does
+ not already exist. Otherwise returns the path to the existing temp file."""
+ temp_dir = hash_file(file_path)
+ temp_dir = Path(cache_dir) / temp_dir
+ temp_dir.mkdir(exist_ok=True, parents=True)
+
+ name = client_utils.strip_invalid_filename_characters(Path(file_path).name)
+ full_temp_file_path = str(abspath(temp_dir / name))
+
+ if not Path(full_temp_file_path).exists():
+ shutil.copy2(file_path, full_temp_file_path)
+
+ return full_temp_file_path
+
+
+def save_url_to_cache(url: str, cache_dir: str) -> str:
+ """Downloads a file and makes a temporary file path for a copy if does not already
+ exist. Otherwise returns the path to the existing temp file."""
+ temp_dir = hash_url(url)
+ temp_dir = Path(cache_dir) / temp_dir
+ temp_dir.mkdir(exist_ok=True, parents=True)
+ name = client_utils.strip_invalid_filename_characters(Path(url).name)
+ full_temp_file_path = str(abspath(temp_dir / name))
+
+ if not Path(full_temp_file_path).exists():
+ with httpx.stream("GET", url) as r, open(full_temp_file_path, "wb") as f:
+ for chunk in r.iter_raw():
+ f.write(chunk)
+
+ return full_temp_file_path
+
+
+def save_base64_to_cache(
+ base64_encoding: str, cache_dir: str, file_name: str | None = None
+) -> str:
+ """Converts a base64 encoding to a file and returns the path to the file if
+ the file doesn't already exist. Otherwise returns the path to the existing file.
+ """
+ temp_dir = hash_base64(base64_encoding)
+ temp_dir = Path(cache_dir) / temp_dir
+ temp_dir.mkdir(exist_ok=True, parents=True)
+
+ guess_extension = client_utils.get_extension(base64_encoding)
+ if file_name:
+ file_name = client_utils.strip_invalid_filename_characters(file_name)
+ elif guess_extension:
+ file_name = f"file.{guess_extension}"
+ else:
+ file_name = "file"
+
+ full_temp_file_path = str(abspath(temp_dir / file_name)) # type: ignore
+
+ if not Path(full_temp_file_path).exists():
+ data, _ = client_utils.decode_base64_to_binary(base64_encoding)
+ with open(full_temp_file_path, "wb") as fb:
+ fb.write(data)
+
+ return full_temp_file_path
+
+
+def move_resource_to_block_cache(
+ url_or_file_path: str | Path | None, block: Component
+) -> str | None:
+ """This method has been replaced by Block.move_resource_to_block_cache(), but is
+ left here for backwards compatibility for any custom components created in Gradio 4.2.0 or earlier.
+ """
+ return block.move_resource_to_block_cache(url_or_file_path)
+
+
+def move_files_to_cache(data: Any, block: Component, postprocess: bool = False):
+ """Move files to cache and replace the file path with the cache path.
+
+ Runs after .postprocess(), after .process_example(), and before .preprocess().
+
+ Args:
+ data: The input or output data for a component. Can be a dictionary or a dataclass
+ block: The component
+ postprocess: Whether its running from postprocessing
+ """
+
+ def _move_to_cache(d: dict):
+ payload = FileData(**d)
+ # If the gradio app developer is returning a URL from
+ # postprocess, it means the component can display a URL
+ # without it being served from the gradio server
+ # This makes it so that the URL is not downloaded and speeds up event processing
+ if payload.url and postprocess:
+ temp_file_path = payload.url
+ else:
+ temp_file_path = move_resource_to_block_cache(payload.path, block)
+ assert temp_file_path is not None
+ payload.path = temp_file_path
+ return payload.model_dump()
+
+ if isinstance(data, (GradioRootModel, GradioModel)):
+ data = data.model_dump()
+
+ return client_utils.traverse(data, _move_to_cache, client_utils.is_file_obj)
+
+
+def resize_and_crop(img, size, crop_type="center"):
+ """
+ Resize and crop an image to fit the specified size.
+ args:
+ size: `(width, height)` tuple. Pass `None` for either width or height
+ to only crop and resize the other.
+ crop_type: can be 'top', 'middle' or 'bottom', depending on this
+ value, the image will cropped getting the 'top/left', 'middle' or
+ 'bottom/right' of the image to fit the size.
+ raises:
+ ValueError: if an invalid `crop_type` is provided.
+ """
+ if crop_type == "top":
+ center = (0, 0)
+ elif crop_type == "center":
+ center = (0.5, 0.5)
+ else:
+ raise ValueError
+
+ resize = list(size)
+ if size[0] is None:
+ resize[0] = img.size[0]
+ if size[1] is None:
+ resize[1] = img.size[1]
+ return ImageOps.fit(img, resize, centering=center) # type: ignore
+
+
+##################
+# Audio
+##################
+
+
+def audio_from_file(filename, crop_min=0, crop_max=100):
+ try:
+ audio = AudioSegment.from_file(filename)
+ except FileNotFoundError as e:
+ isfile = Path(filename).is_file()
+ msg = (
+ f"Cannot load audio from file: `{'ffprobe' if isfile else filename}` not found."
+ + " Please install `ffmpeg` in your system to use non-WAV audio file formats"
+ " and make sure `ffprobe` is in your PATH."
+ if isfile
+ else ""
+ )
+ raise RuntimeError(msg) from e
+ if crop_min != 0 or crop_max != 100:
+ audio_start = len(audio) * crop_min / 100
+ audio_end = len(audio) * crop_max / 100
+ audio = audio[audio_start:audio_end]
+ data = np.array(audio.get_array_of_samples())
+ if audio.channels > 1:
+ data = data.reshape(-1, audio.channels)
+ return audio.frame_rate, data
+
+
+def audio_to_file(sample_rate, data, filename, format="wav"):
+ if format == "wav":
+ data = convert_to_16_bit_wav(data)
+ audio = AudioSegment(
+ data.tobytes(),
+ frame_rate=sample_rate,
+ sample_width=data.dtype.itemsize,
+ channels=(1 if len(data.shape) == 1 else data.shape[1]),
+ )
+ file = audio.export(filename, format=format)
+ file.close() # type: ignore
+
+
+def convert_to_16_bit_wav(data):
+ # Based on: https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.write.html
+ warning = "Trying to convert audio automatically from {} to 16-bit int format."
+ if data.dtype in [np.float64, np.float32, np.float16]:
+ warnings.warn(warning.format(data.dtype))
+ data = data / np.abs(data).max()
+ data = data * 32767
+ data = data.astype(np.int16)
+ elif data.dtype == np.int32:
+ warnings.warn(warning.format(data.dtype))
+ data = data / 65536
+ data = data.astype(np.int16)
+ elif data.dtype == np.int16:
+ pass
+ elif data.dtype == np.uint16:
+ warnings.warn(warning.format(data.dtype))
+ data = data - 32768
+ data = data.astype(np.int16)
+ elif data.dtype == np.uint8:
+ warnings.warn(warning.format(data.dtype))
+ data = data * 257 - 32768
+ data = data.astype(np.int16)
+ elif data.dtype == np.int8:
+ warnings.warn(warning.format(data.dtype))
+ data = data * 256
+ data = data.astype(np.int16)
+ else:
+ raise ValueError(
+ "Audio data cannot be converted automatically from "
+ f"{data.dtype} to 16-bit int format."
+ )
+ return data
+
+
+##################
+# OUTPUT
+##################
+
+
+def _convert(image, dtype, force_copy=False, uniform=False):
+ """
+ Adapted from: https://github.com/scikit-image/scikit-image/blob/main/skimage/util/dtype.py#L510-L531
+
+ Convert an image to the requested data-type.
+ Warnings are issued in case of precision loss, or when negative values
+ are clipped during conversion to unsigned integer types (sign loss).
+ Floating point values are expected to be normalized and will be clipped
+ to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or
+ signed integers respectively.
+ Numbers are not shifted to the negative side when converting from
+ unsigned to signed integer types. Negative values will be clipped when
+ converting to unsigned integers.
+ Parameters
+ ----------
+ image : ndarray
+ Input image.
+ dtype : dtype
+ Target data-type.
+ force_copy : bool, optional
+ Force a copy of the data, irrespective of its current dtype.
+ uniform : bool, optional
+ Uniformly quantize the floating point range to the integer range.
+ By default (uniform=False) floating point values are scaled and
+ rounded to the nearest integers, which minimizes back and forth
+ conversion errors.
+ .. versionchanged :: 0.15
+ ``_convert`` no longer warns about possible precision or sign
+ information loss. See discussions on these warnings at:
+ https://github.com/scikit-image/scikit-image/issues/2602
+ https://github.com/scikit-image/scikit-image/issues/543#issuecomment-208202228
+ https://github.com/scikit-image/scikit-image/pull/3575
+ References
+ ----------
+ .. [1] DirectX data conversion rules.
+ https://msdn.microsoft.com/en-us/library/windows/desktop/dd607323%28v=vs.85%29.aspx
+ .. [2] Data Conversions. In "OpenGL ES 2.0 Specification v2.0.25",
+ pp 7-8. Khronos Group, 2010.
+ .. [3] Proper treatment of pixels as integers. A.W. Paeth.
+ In "Graphics Gems I", pp 249-256. Morgan Kaufmann, 1990.
+ .. [4] Dirty Pixels. J. Blinn. In "Jim Blinn's corner: Dirty Pixels",
+ pp 47-57. Morgan Kaufmann, 1998.
+ """
+ dtype_range = {
+ bool: (False, True),
+ np.bool_: (False, True),
+ np.bool8: (False, True), # type: ignore
+ float: (-1, 1),
+ np.float_: (-1, 1),
+ np.float16: (-1, 1),
+ np.float32: (-1, 1),
+ np.float64: (-1, 1),
+ }
+
+ def _dtype_itemsize(itemsize, *dtypes):
+ """Return first of `dtypes` with itemsize greater than `itemsize`
+ Parameters
+ ----------
+ itemsize: int
+ The data type object element size.
+ Other Parameters
+ ----------------
+ *dtypes:
+ Any Object accepted by `np.dtype` to be converted to a data
+ type object
+ Returns
+ -------
+ dtype: data type object
+ First of `dtypes` with itemsize greater than `itemsize`.
+ """
+ return next(dt for dt in dtypes if np.dtype(dt).itemsize >= itemsize)
+
+ def _dtype_bits(kind, bits, itemsize=1):
+ """Return dtype of `kind` that can store a `bits` wide unsigned int
+ Parameters:
+ kind: str
+ Data type kind.
+ bits: int
+ Desired number of bits.
+ itemsize: int
+ The data type object element size.
+ Returns
+ -------
+ dtype: data type object
+ Data type of `kind` that can store a `bits` wide unsigned int
+ """
+
+ s = next(
+ i
+ for i in (itemsize,) + (2, 4, 8)
+ if bits < (i * 8) or (bits == (i * 8) and kind == "u")
+ )
+
+ return np.dtype(kind + str(s))
+
+ def _scale(a, n, m, copy=True):
+ """Scale an array of unsigned/positive integers from `n` to `m` bits.
+ Numbers can be represented exactly only if `m` is a multiple of `n`.
+ Parameters
+ ----------
+ a : ndarray
+ Input image array.
+ n : int
+ Number of bits currently used to encode the values in `a`.
+ m : int
+ Desired number of bits to encode the values in `out`.
+ copy : bool, optional
+ If True, allocates and returns new array. Otherwise, modifies
+ `a` in place.
+ Returns
+ -------
+ out : array
+ Output image array. Has the same kind as `a`.
+ """
+ kind = a.dtype.kind
+ if n > m and a.max() < 2**m:
+ return a.astype(_dtype_bits(kind, m))
+ elif n == m:
+ return a.copy() if copy else a
+ elif n > m:
+ # downscale with precision loss
+ if copy:
+ b = np.empty(a.shape, _dtype_bits(kind, m))
+ np.floor_divide(a, 2 ** (n - m), out=b, dtype=a.dtype, casting="unsafe")
+ return b
+ else:
+ a //= 2 ** (n - m)
+ return a
+ elif m % n == 0:
+ # exact upscale to a multiple of `n` bits
+ if copy:
+ b = np.empty(a.shape, _dtype_bits(kind, m))
+ np.multiply(a, (2**m - 1) // (2**n - 1), out=b, dtype=b.dtype)
+ return b
+ else:
+ a = a.astype(_dtype_bits(kind, m, a.dtype.itemsize), copy=False)
+ a *= (2**m - 1) // (2**n - 1)
+ return a
+ else:
+ # upscale to a multiple of `n` bits,
+ # then downscale with precision loss
+ o = (m // n + 1) * n
+ if copy:
+ b = np.empty(a.shape, _dtype_bits(kind, o))
+ np.multiply(a, (2**o - 1) // (2**n - 1), out=b, dtype=b.dtype)
+ b //= 2 ** (o - m)
+ return b
+ else:
+ a = a.astype(_dtype_bits(kind, o, a.dtype.itemsize), copy=False)
+ a *= (2**o - 1) // (2**n - 1)
+ a //= 2 ** (o - m)
+ return a
+
+ image = np.asarray(image)
+ dtypeobj_in = image.dtype
+ dtypeobj_out = np.dtype("float64") if dtype is np.floating else np.dtype(dtype)
+ dtype_in = dtypeobj_in.type
+ dtype_out = dtypeobj_out.type
+ kind_in = dtypeobj_in.kind
+ kind_out = dtypeobj_out.kind
+ itemsize_in = dtypeobj_in.itemsize
+ itemsize_out = dtypeobj_out.itemsize
+
+ # Below, we do an `issubdtype` check. Its purpose is to find out
+ # whether we can get away without doing any image conversion. This happens
+ # when:
+ #
+ # - the output and input dtypes are the same or
+ # - when the output is specified as a type, and the input dtype
+ # is a subclass of that type (e.g. `np.floating` will allow
+ # `float32` and `float64` arrays through)
+
+ if np.issubdtype(dtype_in, np.obj2sctype(dtype)):
+ if force_copy:
+ image = image.copy()
+ return image
+
+ if kind_in in "ui":
+ imin_in = np.iinfo(dtype_in).min
+ imax_in = np.iinfo(dtype_in).max
+ if kind_out in "ui":
+ imin_out = np.iinfo(dtype_out).min # type: ignore
+ imax_out = np.iinfo(dtype_out).max # type: ignore
+
+ # any -> binary
+ if kind_out == "b":
+ return image > dtype_in(dtype_range[dtype_in][1] / 2)
+
+ # binary -> any
+ if kind_in == "b":
+ result = image.astype(dtype_out)
+ if kind_out != "f":
+ result *= dtype_out(dtype_range[dtype_out][1])
+ return result
+
+ # float -> any
+ if kind_in == "f":
+ if kind_out == "f":
+ # float -> float
+ return image.astype(dtype_out)
+
+ if np.min(image) < -1.0 or np.max(image) > 1.0:
+ raise ValueError("Images of type float must be between -1 and 1.")
+ # floating point -> integer
+ # use float type that can represent output integer type
+ computation_type = _dtype_itemsize(
+ itemsize_out, dtype_in, np.float32, np.float64
+ )
+
+ if not uniform:
+ if kind_out == "u":
+ image_out = np.multiply(image, imax_out, dtype=computation_type) # type: ignore
+ else:
+ image_out = np.multiply(
+ image,
+ (imax_out - imin_out) / 2, # type: ignore
+ dtype=computation_type,
+ )
+ image_out -= 1.0 / 2.0
+ np.rint(image_out, out=image_out)
+ np.clip(image_out, imin_out, imax_out, out=image_out) # type: ignore
+ elif kind_out == "u":
+ image_out = np.multiply(image, imax_out + 1, dtype=computation_type) # type: ignore
+ np.clip(image_out, 0, imax_out, out=image_out) # type: ignore
+ else:
+ image_out = np.multiply(
+ image,
+ (imax_out - imin_out + 1.0) / 2.0, # type: ignore
+ dtype=computation_type,
+ )
+ np.floor(image_out, out=image_out)
+ np.clip(image_out, imin_out, imax_out, out=image_out) # type: ignore
+ return image_out.astype(dtype_out)
+
+ # signed/unsigned int -> float
+ if kind_out == "f":
+ # use float type that can exactly represent input integers
+ computation_type = _dtype_itemsize(
+ itemsize_in, dtype_out, np.float32, np.float64
+ )
+
+ if kind_in == "u":
+ # using np.divide or np.multiply doesn't copy the data
+ # until the computation time
+ image = np.multiply(image, 1.0 / imax_in, dtype=computation_type) # type: ignore
+ # DirectX uses this conversion also for signed ints
+ # if imin_in:
+ # np.maximum(image, -1.0, out=image)
+ else:
+ image = np.add(image, 0.5, dtype=computation_type)
+ image *= 2 / (imax_in - imin_in) # type: ignore
+
+ return np.asarray(image, dtype_out)
+
+ # unsigned int -> signed/unsigned int
+ if kind_in == "u":
+ if kind_out == "i":
+ # unsigned int -> signed int
+ image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1)
+ return image.view(dtype_out)
+ else:
+ # unsigned int -> unsigned int
+ return _scale(image, 8 * itemsize_in, 8 * itemsize_out)
+
+ # signed int -> unsigned int
+ if kind_out == "u":
+ image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out)
+ result = np.empty(image.shape, dtype_out)
+ np.maximum(image, 0, out=result, dtype=image.dtype, casting="unsafe")
+ return result
+
+ # signed int -> signed int
+ if itemsize_in > itemsize_out:
+ return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1)
+
+ image = image.astype(_dtype_bits("i", itemsize_out * 8))
+ image -= imin_in # type: ignore
+ image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
+ image += imin_out # type: ignore
+ return image.astype(dtype_out)
+
+
+def ffmpeg_installed() -> bool:
+ if wasm_utils.IS_WASM:
+ # TODO: Support ffmpeg in WASM
+ return False
+
+ return shutil.which("ffmpeg") is not None
+
+
+def video_is_playable(video_filepath: str) -> bool:
+ """Determines if a video is playable in the browser.
+
+ A video is playable if it has a playable container and codec.
+ .mp4 -> h264
+ .webm -> vp9
+ .ogg -> theora
+ """
+ from ffmpy import FFprobe, FFRuntimeError
+
+ try:
+ container = Path(video_filepath).suffix.lower()
+ probe = FFprobe(
+ global_options="-show_format -show_streams -select_streams v -print_format json",
+ inputs={video_filepath: None},
+ )
+ output = probe.run(stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ output = json.loads(output[0])
+ video_codec = output["streams"][0]["codec_name"]
+ return (container, video_codec) in [
+ (".mp4", "h264"),
+ (".ogg", "theora"),
+ (".webm", "vp9"),
+ ]
+ # If anything goes wrong, assume the video can be played to not convert downstream
+ except (FFRuntimeError, IndexError, KeyError):
+ return True
+
+
+def convert_video_to_playable_mp4(video_path: str) -> str:
+ """Convert the video to mp4. If something goes wrong return the original video."""
+ from ffmpy import FFmpeg, FFRuntimeError
+
+ try:
+ with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
+ output_path = Path(video_path).with_suffix(".mp4")
+ shutil.copy2(video_path, tmp_file.name)
+ # ffmpeg will automatically use h264 codec (playable in browser) when converting to mp4
+ ff = FFmpeg(
+ inputs={str(tmp_file.name): None},
+ outputs={str(output_path): None},
+ global_options="-y -loglevel quiet",
+ )
+ ff.run()
+ except FFRuntimeError as e:
+ print(f"Error converting video to browser-playable format {str(e)}")
+ output_path = video_path
+ finally:
+ # Remove temp file
+ os.remove(tmp_file.name) # type: ignore
+ return str(output_path)
+
+
+def get_video_length(video_path: str | Path):
+ if wasm_utils.IS_WASM:
+ raise wasm_utils.WasmUnsupportedError(
+ "Video duration is not supported in the Wasm mode."
+ )
+ duration = subprocess.check_output(
+ [
+ "ffprobe",
+ "-i",
+ str(video_path),
+ "-show_entries",
+ "format=duration",
+ "-v",
+ "quiet",
+ "-of",
+ "csv={}".format("p=0"),
+ ]
+ )
+ duration_str = duration.decode("utf-8").strip()
+ duration_float = float(duration_str)
+
+ return duration_float
diff --git a/gradio/queueing.py b/gradio/queueing.py
new file mode 100644
index 0000000000000000000000000000000000000000..c871d7989ec8f6287a67eb46730439340e53222d
--- /dev/null
+++ b/gradio/queueing.py
@@ -0,0 +1,654 @@
+from __future__ import annotations
+
+import asyncio
+import copy
+import json
+import os
+import random
+import time
+import traceback
+import uuid
+from collections import defaultdict
+from queue import Queue as ThreadQueue
+from typing import TYPE_CHECKING
+
+import fastapi
+from gradio_client.utils import ServerMessage
+from typing_extensions import Literal
+
+from gradio import route_utils, routes
+from gradio.data_classes import (
+ Estimation,
+ LogMessage,
+ PredictBody,
+ Progress,
+ ProgressUnit,
+)
+from gradio.exceptions import Error
+from gradio.helpers import TrackedIterable
+from gradio.utils import LRUCache, run_coro_in_background, safe_get_lock, set_task_name
+
+if TYPE_CHECKING:
+ from gradio.blocks import BlockFunction
+
+
+class Event:
+ def __init__(
+ self,
+ session_hash: str,
+ fn_index: int,
+ request: fastapi.Request,
+ username: str | None,
+ concurrency_id: str,
+ ):
+ self.session_hash = session_hash
+ self.fn_index = fn_index
+ self.request = request
+ self.username = username
+ self.concurrency_id = concurrency_id
+ self._id = uuid.uuid4().hex
+ self.data: PredictBody | None = None
+ self.progress: Progress | None = None
+ self.progress_pending: bool = False
+ self.alive = True
+
+
+class EventQueue:
+ def __init__(self, concurrency_id: str, concurrency_limit: int | None):
+ self.queue: list[Event] = []
+ self.concurrency_id = concurrency_id
+ self.concurrency_limit = concurrency_limit
+ self.current_concurrency = 0
+ self.start_times_per_fn_index: defaultdict[int, set[float]] = defaultdict(set)
+
+
+class ProcessTime:
+ def __init__(self):
+ self.process_time = 0
+ self.count = 0
+ self.avg_time = 0
+
+ def add(self, time: float):
+ self.process_time += time
+ self.count += 1
+ self.avg_time = self.process_time / self.count
+
+
+class Queue:
+ def __init__(
+ self,
+ live_updates: bool,
+ concurrency_count: int,
+ update_intervals: float,
+ max_size: int | None,
+ block_fns: list[BlockFunction],
+ default_concurrency_limit: int | None | Literal["not_set"] = "not_set",
+ ):
+ self.pending_messages_per_session: LRUCache[str, ThreadQueue] = LRUCache(2000)
+ self.pending_event_ids_session: dict[str, set[str]] = {}
+ self.pending_message_lock = safe_get_lock()
+ self.event_queue_per_concurrency_id: dict[str, EventQueue] = {}
+ self.stopped = False
+ self.max_thread_count = concurrency_count
+ self.update_intervals = update_intervals
+ self.active_jobs: list[None | list[Event]] = []
+ self.delete_lock = safe_get_lock()
+ self.server_app = None
+ self.process_time_per_fn_index: defaultdict[int, ProcessTime] = defaultdict(
+ ProcessTime
+ )
+ self.live_updates = live_updates
+ self.sleep_when_free = 0.05
+ self.progress_update_sleep_when_free = 0.1
+ self.max_size = max_size
+ self.block_fns = block_fns
+ self.continuous_tasks: list[Event] = []
+ self._asyncio_tasks: list[asyncio.Task] = []
+ self.default_concurrency_limit = self._resolve_concurrency_limit(
+ default_concurrency_limit
+ )
+
+ def start(self):
+ self.active_jobs = [None] * self.max_thread_count
+ self.set_event_queue_per_concurrency_id()
+
+ run_coro_in_background(self.start_processing)
+ run_coro_in_background(self.start_progress_updates)
+ if not self.live_updates:
+ run_coro_in_background(self.notify_clients)
+
+ def set_event_queue_per_concurrency_id(self):
+ for block_fn in self.block_fns:
+ concurrency_id = block_fn.concurrency_id
+ concurrency_limit: int | None
+ if block_fn.concurrency_limit == "default":
+ concurrency_limit = self.default_concurrency_limit
+ else:
+ concurrency_limit = block_fn.concurrency_limit
+ if concurrency_id not in self.event_queue_per_concurrency_id:
+ self.event_queue_per_concurrency_id[concurrency_id] = EventQueue(
+ concurrency_id, concurrency_limit
+ )
+ elif (
+ concurrency_limit is not None
+ ): # Update concurrency limit if it is lower than existing limit
+ existing_event_queue = self.event_queue_per_concurrency_id[
+ concurrency_id
+ ]
+ if (
+ existing_event_queue.concurrency_limit is None
+ or concurrency_limit < existing_event_queue.concurrency_limit
+ ):
+ existing_event_queue.concurrency_limit = concurrency_limit
+
+ def reload(self):
+ self.set_event_queue_per_concurrency_id()
+
+ def close(self):
+ self.stopped = True
+
+ def send_message(
+ self,
+ event: Event,
+ message_type: str,
+ data: dict | None = None,
+ ):
+ if not event.alive:
+ return
+ data = {} if data is None else data
+ messages = self.pending_messages_per_session[event.session_hash]
+ messages.put_nowait({"msg": message_type, "event_id": event._id, **data})
+
+ def _resolve_concurrency_limit(
+ self, default_concurrency_limit: int | None | Literal["not_set"]
+ ) -> int | None:
+ """
+ Handles the logic of resolving the default_concurrency_limit as this can be specified via a combination
+ of the `default_concurrency_limit` parameter of the `Blocks.queue()` or the `GRADIO_DEFAULT_CONCURRENCY_LIMIT`
+ environment variable. The parameter in `Blocks.queue()` takes precedence over the environment variable.
+ Parameters:
+ default_concurrency_limit: The default concurrency limit, as specified by a user in `Blocks.queu()`.
+ """
+ if default_concurrency_limit != "not_set":
+ return default_concurrency_limit
+ if default_concurrency_limit_env := os.environ.get(
+ "GRADIO_DEFAULT_CONCURRENCY_LIMIT"
+ ):
+ if default_concurrency_limit_env.lower() == "none":
+ return None
+ else:
+ return int(default_concurrency_limit_env)
+ else:
+ return 1
+
+ def __len__(self):
+ total_len = 0
+ for event_queue in self.event_queue_per_concurrency_id.values():
+ total_len += len(event_queue.queue)
+ return total_len
+
+ async def push(
+ self, body: PredictBody, request: fastapi.Request, username: str | None
+ ) -> tuple[bool, str]:
+ if body.session_hash is None:
+ return False, "No session hash provided."
+ if body.fn_index is None:
+ return False, "No function index provided."
+ if self.max_size is not None and len(self) >= self.max_size:
+ return (
+ False,
+ f"Queue is full. Max size is {self.max_size} and size is {len(self)}.",
+ )
+
+ event = Event(
+ body.session_hash,
+ body.fn_index,
+ request,
+ username,
+ self.block_fns[body.fn_index].concurrency_id,
+ )
+ event.data = body
+ async with self.pending_message_lock:
+ if body.session_hash not in self.pending_messages_per_session:
+ self.pending_messages_per_session[body.session_hash] = ThreadQueue()
+ if body.session_hash not in self.pending_event_ids_session:
+ self.pending_event_ids_session[body.session_hash] = set()
+ self.pending_event_ids_session[body.session_hash].add(event._id)
+ event_queue = self.event_queue_per_concurrency_id[event.concurrency_id]
+ event_queue.queue.append(event)
+
+ self.broadcast_estimations(event.concurrency_id, len(event_queue.queue) - 1)
+
+ return True, event._id
+
+ def _cancel_asyncio_tasks(self):
+ for task in self._asyncio_tasks:
+ task.cancel()
+ self._asyncio_tasks = []
+
+ def set_server_app(self, app: routes.App):
+ self.server_app = app
+
+ def get_active_worker_count(self) -> int:
+ count = 0
+ for worker in self.active_jobs:
+ if worker is not None:
+ count += 1
+ return count
+
+ def get_events(self) -> tuple[list[Event], bool, str] | None:
+ concurrency_ids = list(self.event_queue_per_concurrency_id.keys())
+ random.shuffle(concurrency_ids)
+ for concurrency_id in concurrency_ids:
+ event_queue = self.event_queue_per_concurrency_id[concurrency_id]
+ if len(event_queue.queue) and (
+ event_queue.concurrency_limit is None
+ or event_queue.current_concurrency < event_queue.concurrency_limit
+ ):
+ first_event = event_queue.queue[0]
+ block_fn = self.block_fns[first_event.fn_index]
+ events = [first_event]
+ batch = block_fn.batch
+ if batch:
+ events += [
+ event
+ for event in event_queue.queue[1:]
+ if event.fn_index == first_event.fn_index
+ ][: block_fn.max_batch_size - 1]
+
+ for event in events:
+ event_queue.queue.remove(event)
+
+ return events, batch, concurrency_id
+
+ async def start_processing(self) -> None:
+ try:
+ while not self.stopped:
+ if len(self) == 0:
+ await asyncio.sleep(self.sleep_when_free)
+ continue
+
+ if None not in self.active_jobs:
+ await asyncio.sleep(self.sleep_when_free)
+ continue
+
+ # Using mutex to avoid editing a list in use
+ async with self.delete_lock:
+ event_batch = self.get_events()
+
+ if event_batch:
+ events, batch, concurrency_id = event_batch
+ self.active_jobs[self.active_jobs.index(None)] = events
+ event_queue = self.event_queue_per_concurrency_id[concurrency_id]
+ event_queue.current_concurrency += 1
+ start_time = time.time()
+ event_queue.start_times_per_fn_index[events[0].fn_index].add(
+ start_time
+ )
+ process_event_task = run_coro_in_background(
+ self.process_events, events, batch, start_time
+ )
+ set_task_name(
+ process_event_task,
+ events[0].session_hash,
+ events[0].fn_index,
+ batch,
+ )
+
+ self._asyncio_tasks.append(process_event_task)
+ if self.live_updates:
+ self.broadcast_estimations(concurrency_id)
+ else:
+ await asyncio.sleep(self.sleep_when_free)
+ finally:
+ self.stopped = True
+ self._cancel_asyncio_tasks()
+
+ async def start_progress_updates(self) -> None:
+ """
+ Because progress updates can be very frequent, we do not necessarily want to send a message per update.
+ Rather, we check for progress updates at regular intervals, and send a message if there is a pending update.
+ Consecutive progress updates between sends will overwrite each other so only the most recent update will be sent.
+ """
+ while not self.stopped:
+ events = [
+ evt for job in self.active_jobs if job is not None for evt in job
+ ] + self.continuous_tasks
+
+ if len(events) == 0:
+ await asyncio.sleep(self.progress_update_sleep_when_free)
+ continue
+
+ for event in events:
+ if event.progress_pending and event.progress:
+ event.progress_pending = False
+ self.send_message(
+ event, ServerMessage.progress, event.progress.model_dump()
+ )
+
+ await asyncio.sleep(self.progress_update_sleep_when_free)
+
+ def set_progress(
+ self,
+ event_id: str,
+ iterables: list[TrackedIterable] | None,
+ ):
+ if iterables is None:
+ return
+ for job in self.active_jobs:
+ if job is None:
+ continue
+ for evt in job:
+ if evt._id == event_id:
+ progress_data: list[ProgressUnit] = []
+ for iterable in iterables:
+ progress_unit = ProgressUnit(
+ index=iterable.index,
+ length=iterable.length,
+ unit=iterable.unit,
+ progress=iterable.progress,
+ desc=iterable.desc,
+ )
+ progress_data.append(progress_unit)
+ evt.progress = Progress(progress_data=progress_data)
+ evt.progress_pending = True
+
+ def log_message(
+ self,
+ event_id: str,
+ log: str,
+ level: Literal["info", "warning"],
+ ):
+ events = [
+ evt for job in self.active_jobs if job is not None for evt in job
+ ] + self.continuous_tasks
+ for event in events:
+ if event._id == event_id:
+ log_message = LogMessage(
+ log=log,
+ level=level,
+ )
+ self.send_message(event, ServerMessage.log, log_message.model_dump())
+
+ async def clean_events(
+ self, *, session_hash: str | None = None, event_id: str | None = None
+ ) -> None:
+ for job_set in self.active_jobs:
+ if job_set:
+ for job in job_set:
+ if job.session_hash == session_hash or job._id == event_id:
+ job.alive = False
+
+ async with self.delete_lock:
+ events_to_remove: list[Event] = []
+ for event_queue in self.event_queue_per_concurrency_id.values():
+ for event in event_queue.queue:
+ if event.session_hash == session_hash or event._id == event_id:
+ events_to_remove.append(event)
+
+ for event in events_to_remove:
+ self.event_queue_per_concurrency_id[event.concurrency_id].queue.remove(
+ event
+ )
+
+ async def notify_clients(self) -> None:
+ """
+ Notify clients about events statuses in the queue periodically.
+ """
+ while not self.stopped:
+ await asyncio.sleep(self.update_intervals)
+ if len(self) > 0:
+ for concurrency_id in self.event_queue_per_concurrency_id:
+ self.broadcast_estimations(concurrency_id)
+
+ def broadcast_estimations(
+ self, concurrency_id: str, after: int | None = None
+ ) -> None:
+ wait_so_far = 0
+ event_queue = self.event_queue_per_concurrency_id[concurrency_id]
+ time_till_available_worker: int | None = 0
+
+ if event_queue.current_concurrency == event_queue.concurrency_limit:
+ expected_end_times = []
+ for fn_index, start_times in event_queue.start_times_per_fn_index.items():
+ if fn_index not in self.process_time_per_fn_index:
+ time_till_available_worker = None
+ break
+ process_time = self.process_time_per_fn_index[fn_index].avg_time
+ expected_end_times += [
+ start_time + process_time for start_time in start_times
+ ]
+ if time_till_available_worker is not None and len(expected_end_times) > 0:
+ time_of_first_completion = min(expected_end_times)
+ time_till_available_worker = max(
+ time_of_first_completion - time.time(), 0
+ )
+
+ for rank, event in enumerate(event_queue.queue):
+ process_time_for_fn = (
+ self.process_time_per_fn_index[event.fn_index].avg_time
+ if event.fn_index in self.process_time_per_fn_index
+ else None
+ )
+ rank_eta = (
+ process_time_for_fn + wait_so_far + time_till_available_worker
+ if process_time_for_fn is not None
+ and wait_so_far is not None
+ and time_till_available_worker is not None
+ else None
+ )
+
+ if after is None or rank >= after:
+ self.send_message(
+ event,
+ ServerMessage.estimation,
+ Estimation(
+ rank=rank, rank_eta=rank_eta, queue_size=len(event_queue.queue)
+ ).model_dump(),
+ )
+ if event_queue.concurrency_limit is None:
+ wait_so_far = 0
+ elif wait_so_far is not None and process_time_for_fn is not None:
+ wait_so_far += process_time_for_fn / event_queue.concurrency_limit
+ else:
+ wait_so_far = None
+
+ def get_status(self) -> Estimation:
+ return Estimation(
+ queue_size=len(self),
+ )
+
+ async def call_prediction(self, events: list[Event], batch: bool):
+ body = events[0].data
+ if body is None:
+ raise ValueError("No event data")
+ username = events[0].username
+ body.event_id = events[0]._id if not batch else None
+ try:
+ body.request = events[0].request
+ except ValueError:
+ pass
+
+ if batch:
+ body.data = list(zip(*[event.data.data for event in events if event.data]))
+ body.request = events[0].request
+ body.batched = True
+
+ app = self.server_app
+ if app is None:
+ raise Exception("Server app has not been set.")
+ api_name = "predict"
+
+ fn_index_inferred = route_utils.infer_fn_index(
+ app=app, api_name=api_name, body=body
+ )
+
+ gr_request = route_utils.compile_gr_request(
+ app=app,
+ body=body,
+ fn_index_inferred=fn_index_inferred,
+ username=username,
+ request=None,
+ )
+
+ try:
+ output = await route_utils.call_process_api(
+ app=app,
+ body=body,
+ gr_request=gr_request,
+ fn_index_inferred=fn_index_inferred,
+ )
+ except Exception as error:
+ show_error = app.get_blocks().show_error or isinstance(error, Error)
+ traceback.print_exc()
+ raise Exception(str(error) if show_error else None) from error
+
+ # To emulate the HTTP response from the predict API,
+ # convert the output to a JSON response string.
+ # This is done by FastAPI automatically in the HTTP endpoint handlers,
+ # but we need to do it manually here.
+ response_class = app.router.default_response_class
+ if isinstance(response_class, fastapi.datastructures.DefaultPlaceholder):
+ actual_response_class = response_class.value
+ else:
+ actual_response_class = response_class
+ http_response = actual_response_class(
+ output
+ ) # Do the same as https://github.com/tiangolo/fastapi/blob/0.87.0/fastapi/routing.py#L264
+ # Also, decode the JSON string to a Python object, emulating the HTTP client behavior e.g. the `json()` method of `httpx`.
+ response_json = json.loads(http_response.body.decode())
+
+ return response_json
+
+ async def process_events(
+ self, events: list[Event], batch: bool, begin_time: float
+ ) -> None:
+ awake_events: list[Event] = []
+ fn_index = events[0].fn_index
+ try:
+ for event in events:
+ if event.alive:
+ self.send_message(
+ event,
+ ServerMessage.process_starts,
+ {
+ "eta": self.process_time_per_fn_index[fn_index].avg_time
+ if fn_index in self.process_time_per_fn_index
+ else None
+ },
+ )
+ awake_events.append(event)
+ if not awake_events:
+ return
+ try:
+ response = await self.call_prediction(awake_events, batch)
+ err = None
+ except Exception as e:
+ response = None
+ err = e
+ for event in awake_events:
+ self.send_message(
+ event,
+ ServerMessage.process_completed,
+ {
+ "output": {
+ "error": None
+ if len(e.args) and e.args[0] is None
+ else str(e)
+ },
+ "success": False,
+ },
+ )
+ if response and response.get("is_generating", False):
+ old_response = response
+ old_err = err
+ while response and response.get("is_generating", False):
+ old_response = response
+ old_err = err
+ for event in awake_events:
+ self.send_message(
+ event,
+ ServerMessage.process_generating,
+ {
+ "output": old_response,
+ "success": old_response is not None,
+ },
+ )
+ awake_events = [event for event in awake_events if event.alive]
+ if not awake_events:
+ return
+ try:
+ response = await self.call_prediction(awake_events, batch)
+ err = None
+ except Exception as e:
+ response = None
+ err = e
+ for event in awake_events:
+ if response is None:
+ relevant_response = err
+ else:
+ relevant_response = old_response or old_err
+ self.send_message(
+ event,
+ ServerMessage.process_completed,
+ {
+ "output": {"error": str(relevant_response)}
+ if isinstance(relevant_response, Exception)
+ else relevant_response,
+ "success": relevant_response
+ and not isinstance(relevant_response, Exception),
+ },
+ )
+ elif response:
+ output = copy.deepcopy(response)
+ for e, event in enumerate(awake_events):
+ if batch and "data" in output:
+ output["data"] = list(zip(*response.get("data")))[e]
+ self.send_message(
+ event,
+ ServerMessage.process_completed,
+ {
+ "output": output,
+ "success": response is not None,
+ },
+ )
+ end_time = time.time()
+ if response is not None:
+ self.process_time_per_fn_index[events[0].fn_index].add(
+ end_time - begin_time
+ )
+ except Exception as e:
+ traceback.print_exc()
+ finally:
+ event_queue = self.event_queue_per_concurrency_id[events[0].concurrency_id]
+ event_queue.current_concurrency -= 1
+ start_times = event_queue.start_times_per_fn_index[fn_index]
+ if begin_time in start_times:
+ start_times.remove(begin_time)
+ try:
+ self.active_jobs[self.active_jobs.index(events)] = None
+ except ValueError:
+ # `events` can be absent from `self.active_jobs`
+ # when this coroutine is called from the `join_queue` endpoint handler in `routes.py`
+ # without putting the `events` into `self.active_jobs`.
+ # https://github.com/gradio-app/gradio/blob/f09aea34d6bd18c1e2fef80c86ab2476a6d1dd83/gradio/routes.py#L594-L596
+ pass
+ for event in events:
+ # Always reset the state of the iterator
+ # If the job finished successfully, this has no effect
+ # If the job is cancelled, this will enable future runs
+ # to start "from scratch"
+ await self.reset_iterators(event._id)
+
+ async def reset_iterators(self, event_id: str):
+ # Do the same thing as the /reset route
+ app = self.server_app
+ if app is None:
+ raise Exception("Server app has not been set.")
+ if event_id not in app.iterators:
+ # Failure, but don't raise an error
+ return
+ async with app.lock:
+ del app.iterators[event_id]
+ app.iterators_to_reset.add(event_id)
+ return
diff --git a/gradio/ranged_response.py b/gradio/ranged_response.py
new file mode 100644
index 0000000000000000000000000000000000000000..f488776e6c7f3a58ce95375e043680b6c17257da
--- /dev/null
+++ b/gradio/ranged_response.py
@@ -0,0 +1,188 @@
+# Taken from https://gist.github.com/kevinastone/a6a62db57577b3f24e8a6865ed311463
+# Context: https://github.com/encode/starlette/pull/1090
+from __future__ import annotations
+
+import os
+import re
+import stat
+from typing import NamedTuple
+from urllib.parse import quote
+
+import aiofiles
+from aiofiles.os import stat as aio_stat
+from starlette.datastructures import Headers
+from starlette.exceptions import HTTPException
+from starlette.responses import Response, guess_type
+from starlette.staticfiles import StaticFiles
+from starlette.types import Receive, Scope, Send
+
+RANGE_REGEX = re.compile(r"^bytes=(?P
\d+)-(?P\d*)$")
+
+
+class ClosedRange(NamedTuple):
+ start: int
+ end: int
+
+ def __len__(self) -> int:
+ return self.end - self.start + 1
+
+ def __bool__(self) -> bool:
+ return len(self) > 0
+
+
+class OpenRange(NamedTuple):
+ start: int
+ end: int | None = None
+
+ def clamp(self, start: int, end: int) -> ClosedRange:
+ begin = max(self.start, start)
+ end = min(x for x in (self.end, end) if x)
+
+ begin = min(begin, end)
+ end = max(begin, end)
+
+ return ClosedRange(begin, end)
+
+
+class RangedFileResponse(Response):
+ chunk_size = 4096
+
+ def __init__(
+ self,
+ path: str | os.PathLike,
+ range: OpenRange,
+ headers: dict[str, str] | None = None,
+ media_type: str | None = None,
+ filename: str | None = None,
+ stat_result: os.stat_result | None = None,
+ method: str | None = None,
+ ) -> None:
+ if aiofiles is None:
+ raise ModuleNotFoundError(
+ "'aiofiles' must be installed to use FileResponse"
+ )
+ self.path = path
+ self.range = range
+ self.filename = filename
+ self.background = None
+ self.send_header_only = method is not None and method.upper() == "HEAD"
+ if media_type is None:
+ media_type = guess_type(filename or path)[0] or "text/plain"
+ self.media_type = media_type
+ self.init_headers(headers or {})
+ if self.filename is not None:
+ content_disposition_filename = quote(self.filename)
+ if content_disposition_filename != self.filename:
+ content_disposition = (
+ f"attachment; filename*=utf-8''{content_disposition_filename}"
+ )
+ else:
+ content_disposition = f'attachment; filename="{self.filename}"'
+ self.headers.setdefault("content-disposition", content_disposition)
+ self.stat_result = stat_result
+
+ def set_range_headers(self, range: ClosedRange) -> None:
+ assert self.stat_result
+ total_length = self.stat_result.st_size
+ content_length = len(range)
+ self.headers[
+ "content-range"
+ ] = f"bytes {range.start}-{range.end}/{total_length}"
+ self.headers["content-length"] = str(content_length)
+ pass
+
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
+ if self.stat_result is None:
+ try:
+ stat_result = await aio_stat(self.path)
+ self.stat_result = stat_result
+ except FileNotFoundError as fnfe:
+ raise RuntimeError(
+ f"File at path {self.path} does not exist."
+ ) from fnfe
+ else:
+ mode = stat_result.st_mode
+ if not stat.S_ISREG(mode):
+ raise RuntimeError(f"File at path {self.path} is not a file.")
+
+ byte_range = self.range.clamp(0, self.stat_result.st_size)
+ self.set_range_headers(byte_range)
+
+ async with aiofiles.open(self.path, mode="rb") as file:
+ await file.seek(byte_range.start)
+ await send(
+ {
+ "type": "http.response.start",
+ "status": 206,
+ "headers": self.raw_headers,
+ }
+ )
+ if self.send_header_only:
+ await send(
+ {"type": "http.response.body", "body": b"", "more_body": False}
+ )
+ else:
+ remaining_bytes = len(byte_range)
+
+ if not byte_range:
+ await send(
+ {"type": "http.response.body", "body": b"", "more_body": False}
+ )
+ return
+
+ while remaining_bytes > 0:
+ chunk_size = min(self.chunk_size, remaining_bytes)
+ chunk = await file.read(chunk_size)
+ remaining_bytes -= len(chunk)
+ await send(
+ {
+ "type": "http.response.body",
+ "body": chunk,
+ "more_body": remaining_bytes > 0,
+ }
+ )
+
+
+class RangedStaticFiles(StaticFiles):
+ def file_response(
+ self,
+ full_path: str | os.PathLike,
+ stat_result: os.stat_result,
+ scope: Scope,
+ status_code: int = 200,
+ ) -> Response:
+ request_headers = Headers(scope=scope)
+
+ if request_headers.get("range"):
+ response = self.ranged_file_response(
+ full_path, stat_result=stat_result, scope=scope
+ )
+ else:
+ response = super().file_response(
+ full_path, stat_result=stat_result, scope=scope, status_code=status_code
+ )
+ response.headers["accept-ranges"] = "bytes"
+ return response
+
+ def ranged_file_response(
+ self,
+ full_path: str | os.PathLike,
+ stat_result: os.stat_result,
+ scope: Scope,
+ ) -> Response:
+ method = scope["method"]
+ request_headers = Headers(scope=scope)
+
+ range_header = request_headers["range"]
+
+ match = RANGE_REGEX.search(range_header)
+ if not match:
+ raise HTTPException(400)
+
+ start, end = match.group("start"), match.group("end")
+
+ range = OpenRange(int(start), int(end) if end else None)
+
+ return RangedFileResponse(
+ full_path, range, stat_result=stat_result, method=method
+ )
diff --git a/gradio/route_utils.py b/gradio/route_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..7f4746f1d06a484b03cf3d0fe855b129d10a05e8
--- /dev/null
+++ b/gradio/route_utils.py
@@ -0,0 +1,549 @@
+from __future__ import annotations
+
+import hashlib
+import json
+from collections import deque
+from dataclasses import dataclass as python_dataclass
+from tempfile import NamedTemporaryFile, _TemporaryFileWrapper
+from typing import TYPE_CHECKING, AsyncGenerator, BinaryIO, List, Optional, Tuple, Union
+
+import fastapi
+import httpx
+import multipart
+from gradio_client.documentation import document, set_documentation_group
+from multipart.multipart import parse_options_header
+from starlette.datastructures import FormData, Headers, UploadFile
+from starlette.formparsers import MultiPartException, MultipartPart
+
+from gradio import utils
+from gradio.data_classes import PredictBody
+from gradio.exceptions import Error
+from gradio.helpers import EventData
+from gradio.state_holder import SessionState
+
+if TYPE_CHECKING:
+ from gradio.blocks import Blocks
+ from gradio.routes import App
+
+set_documentation_group("routes")
+
+
+class Obj:
+ """
+ Using a class to convert dictionaries into objects. Used by the `Request` class.
+ Credit: https://www.geeksforgeeks.org/convert-nested-python-dictionary-to-object/
+ """
+
+ def __init__(self, dict_):
+ self.__dict__.update(dict_)
+ for key, value in dict_.items():
+ if isinstance(value, (dict, list)):
+ value = Obj(value)
+ setattr(self, key, value)
+
+ def __getitem__(self, item):
+ return self.__dict__[item]
+
+ def __setitem__(self, item, value):
+ self.__dict__[item] = value
+
+ def __iter__(self):
+ for key, value in self.__dict__.items():
+ if isinstance(value, Obj):
+ yield (key, dict(value))
+ else:
+ yield (key, value)
+
+ def __contains__(self, item) -> bool:
+ if item in self.__dict__:
+ return True
+ for value in self.__dict__.values():
+ if isinstance(value, Obj) and item in value:
+ return True
+ return False
+
+ def keys(self):
+ return self.__dict__.keys()
+
+ def values(self):
+ return self.__dict__.values()
+
+ def items(self):
+ return self.__dict__.items()
+
+ def __str__(self) -> str:
+ return str(self.__dict__)
+
+ def __repr__(self) -> str:
+ return str(self.__dict__)
+
+
+@document()
+class Request:
+ """
+ A Gradio request object that can be used to access the request headers, cookies,
+ query parameters and other information about the request from within the prediction
+ function. The class is a thin wrapper around the fastapi.Request class. Attributes
+ of this class include: `headers`, `client`, `query_params`, and `path_params`. If
+ auth is enabled, the `username` attribute can be used to get the logged in user.
+ Example:
+ import gradio as gr
+ def echo(text, request: gr.Request):
+ if request:
+ print("Request headers dictionary:", request.headers)
+ print("IP address:", request.client.host)
+ print("Query parameters:", dict(request.query_params))
+ return text
+ io = gr.Interface(echo, "textbox", "textbox").launch()
+ Demos: request_ip_headers
+ """
+
+ def __init__(
+ self,
+ request: fastapi.Request | None = None,
+ username: str | None = None,
+ **kwargs,
+ ):
+ """
+ Can be instantiated with either a fastapi.Request or by manually passing in
+ attributes (needed for queueing).
+ Parameters:
+ request: A fastapi.Request
+ """
+ self.request = request
+ self.username = username
+ self.kwargs: dict = kwargs
+
+ def dict_to_obj(self, d):
+ if isinstance(d, dict):
+ return json.loads(json.dumps(d), object_hook=Obj)
+ else:
+ return d
+
+ def __getattr__(self, name):
+ if self.request:
+ return self.dict_to_obj(getattr(self.request, name))
+ else:
+ try:
+ obj = self.kwargs[name]
+ except KeyError as ke:
+ raise AttributeError(
+ f"'Request' object has no attribute '{name}'"
+ ) from ke
+ return self.dict_to_obj(obj)
+
+
+class FnIndexInferError(Exception):
+ pass
+
+
+def infer_fn_index(app: App, api_name: str, body: PredictBody) -> int:
+ if body.fn_index is None:
+ for i, fn in enumerate(app.get_blocks().dependencies):
+ if fn["api_name"] == api_name:
+ return i
+
+ raise FnIndexInferError(f"Could not infer fn_index for api_name {api_name}.")
+ else:
+ return body.fn_index
+
+
+def compile_gr_request(
+ app: App,
+ body: PredictBody,
+ fn_index_inferred: int,
+ username: Optional[str],
+ request: Optional[fastapi.Request],
+):
+ # If this fn_index cancels jobs, then the only input we need is the
+ # current session hash
+ if app.get_blocks().dependencies[fn_index_inferred]["cancels"]:
+ body.data = [body.session_hash]
+ if body.request:
+ if body.batched:
+ gr_request = [Request(username=username, request=request)]
+ else:
+ gr_request = Request(username=username, request=body.request)
+ else:
+ if request is None:
+ raise ValueError("request must be provided if body.request is None")
+ gr_request = Request(username=username, request=request)
+
+ return gr_request
+
+
+def restore_session_state(app: App, body: PredictBody):
+ event_id = body.event_id
+ session_hash = getattr(body, "session_hash", None)
+ if session_hash is not None:
+ session_state = app.state_holder[session_hash]
+ # The should_reset set keeps track of the fn_indices
+ # that have been cancelled. When a job is cancelled,
+ # the /reset route will mark the jobs as having been reset.
+ # That way if the cancel job finishes BEFORE the job being cancelled
+ # the job being cancelled will not overwrite the state of the iterator.
+ if event_id is None:
+ iterator = None
+ elif event_id in app.iterators_to_reset:
+ iterator = None
+ app.iterators_to_reset.remove(event_id)
+ else:
+ iterator = app.iterators.get(event_id)
+ else:
+ session_state = SessionState(app.get_blocks())
+ iterator = None
+
+ return session_state, iterator
+
+
+def prepare_event_data(
+ blocks: Blocks,
+ body: PredictBody,
+) -> EventData:
+ target = body.trigger_id
+ event_data = EventData(
+ blocks.blocks.get(target) if target else None,
+ body.event_data,
+ )
+ return event_data
+
+
+async def call_process_api(
+ app: App,
+ body: PredictBody,
+ gr_request: Union[Request, list[Request]],
+ fn_index_inferred: int,
+):
+ session_state, iterator = restore_session_state(app=app, body=body)
+
+ dependency = app.get_blocks().dependencies[fn_index_inferred]
+ event_data = prepare_event_data(app.get_blocks(), body)
+ event_id = body.event_id
+
+ session_hash = getattr(body, "session_hash", None)
+ inputs = body.data
+
+ batch_in_single_out = not body.batched and dependency["batch"]
+ if batch_in_single_out:
+ inputs = [inputs]
+
+ try:
+ with utils.MatplotlibBackendMananger():
+ output = await app.get_blocks().process_api(
+ fn_index=fn_index_inferred,
+ inputs=inputs,
+ request=gr_request,
+ state=session_state,
+ iterator=iterator,
+ session_hash=session_hash,
+ event_id=event_id,
+ event_data=event_data,
+ in_event_listener=True,
+ )
+ iterator = output.pop("iterator", None)
+ if event_id is not None:
+ app.iterators[event_id] = iterator # type: ignore
+ if isinstance(output, Error):
+ raise output
+ except BaseException:
+ iterator = app.iterators.get(event_id) if event_id is not None else None
+ if iterator is not None: # close off any streams that are still open
+ run_id = id(iterator)
+ pending_streams: dict[int, list] = (
+ app.get_blocks().pending_streams[session_hash].get(run_id, {})
+ )
+ for stream in pending_streams.values():
+ stream.append(None)
+ raise
+
+ if batch_in_single_out:
+ output["data"] = output["data"][0]
+
+ return output
+
+
+def strip_url(orig_url: str) -> str:
+ """
+ Strips the query parameters and trailing slash from a URL.
+ """
+ parsed_url = httpx.URL(orig_url)
+ stripped_url = parsed_url.copy_with(query=None)
+ stripped_url = str(stripped_url)
+ return stripped_url.rstrip("/")
+
+
+def _user_safe_decode(src: bytes, codec: str) -> str:
+ try:
+ return src.decode(codec)
+ except (UnicodeDecodeError, LookupError):
+ return src.decode("latin-1")
+
+
+class GradioUploadFile(UploadFile):
+ """UploadFile with a sha attribute."""
+
+ def __init__(
+ self,
+ file: BinaryIO,
+ *,
+ size: int | None = None,
+ filename: str | None = None,
+ headers: Headers | None = None,
+ ) -> None:
+ super().__init__(file, size=size, filename=filename, headers=headers)
+ self.sha = hashlib.sha1()
+
+
+@python_dataclass(frozen=True)
+class FileUploadProgressUnit:
+ filename: str
+ chunk_size: int
+
+
+@python_dataclass
+class FileUploadProgressTracker:
+ deque: deque[FileUploadProgressUnit]
+ is_done: bool
+
+
+class FileUploadProgressNotTrackedError(Exception):
+ pass
+
+
+class FileUploadProgressNotQueuedError(Exception):
+ pass
+
+
+class FileUploadProgress:
+ def __init__(self) -> None:
+ self._statuses: dict[str, FileUploadProgressTracker] = {}
+
+ def track(self, upload_id: str):
+ if upload_id not in self._statuses:
+ self._statuses[upload_id] = FileUploadProgressTracker(deque(), False)
+
+ def append(self, upload_id: str, filename: str, message_bytes: bytes):
+ if upload_id not in self._statuses:
+ self.track(upload_id)
+ queue = self._statuses[upload_id].deque
+
+ if len(queue) == 0:
+ queue.append(FileUploadProgressUnit(filename, len(message_bytes)))
+ else:
+ last_unit = queue.popleft()
+ if last_unit.filename != filename:
+ queue.append(FileUploadProgressUnit(filename, len(message_bytes)))
+ else:
+ queue.append(
+ FileUploadProgressUnit(
+ filename,
+ last_unit.chunk_size + len(message_bytes),
+ )
+ )
+
+ def set_done(self, upload_id: str):
+ if upload_id not in self._statuses:
+ self.track(upload_id)
+ self._statuses[upload_id].is_done = True
+
+ def is_done(self, upload_id: str):
+ if upload_id not in self._statuses:
+ raise FileUploadProgressNotTrackedError()
+ return self._statuses[upload_id].is_done
+
+ def stop_tracking(self, upload_id: str):
+ if upload_id in self._statuses:
+ del self._statuses[upload_id]
+
+ def pop(self, upload_id: str) -> FileUploadProgressUnit:
+ if upload_id not in self._statuses:
+ raise FileUploadProgressNotTrackedError()
+ try:
+ return self._statuses[upload_id].deque.pop()
+ except IndexError as e:
+ raise FileUploadProgressNotQueuedError() from e
+
+
+class GradioMultiPartParser:
+ """Vendored from starlette.MultipartParser.
+
+ Thanks starlette!
+
+ Made the following modifications
+ - Use GradioUploadFile instead of UploadFile
+ - Use NamedTemporaryFile instead of SpooledTemporaryFile
+ - Compute hash of data as the request is streamed
+
+ """
+
+ max_file_size = 1024 * 1024
+
+ def __init__(
+ self,
+ headers: Headers,
+ stream: AsyncGenerator[bytes, None],
+ *,
+ max_files: Union[int, float] = 1000,
+ max_fields: Union[int, float] = 1000,
+ upload_id: str | None = None,
+ upload_progress: FileUploadProgress | None = None,
+ ) -> None:
+ assert (
+ multipart is not None
+ ), "The `python-multipart` library must be installed to use form parsing."
+ self.headers = headers
+ self.stream = stream
+ self.max_files = max_files
+ self.max_fields = max_fields
+ self.items: List[Tuple[str, Union[str, UploadFile]]] = []
+ self.upload_id = upload_id
+ self.upload_progress = upload_progress
+ self._current_files = 0
+ self._current_fields = 0
+ self._current_partial_header_name: bytes = b""
+ self._current_partial_header_value: bytes = b""
+ self._current_part = MultipartPart()
+ self._charset = ""
+ self._file_parts_to_write: List[Tuple[MultipartPart, bytes]] = []
+ self._file_parts_to_finish: List[MultipartPart] = []
+ self._files_to_close_on_error: List[_TemporaryFileWrapper] = []
+
+ def on_part_begin(self) -> None:
+ self._current_part = MultipartPart()
+
+ def on_part_data(self, data: bytes, start: int, end: int) -> None:
+ message_bytes = data[start:end]
+ if self.upload_progress is not None:
+ self.upload_progress.append(
+ self.upload_id, # type: ignore
+ self._current_part.file.filename, # type: ignore
+ message_bytes,
+ )
+ if self._current_part.file is None:
+ self._current_part.data += message_bytes
+ else:
+ self._file_parts_to_write.append((self._current_part, message_bytes))
+
+ def on_part_end(self) -> None:
+ if self._current_part.file is None:
+ self.items.append(
+ (
+ self._current_part.field_name,
+ _user_safe_decode(self._current_part.data, self._charset),
+ )
+ )
+ else:
+ self._file_parts_to_finish.append(self._current_part)
+ # The file can be added to the items right now even though it's not
+ # finished yet, because it will be finished in the `parse()` method, before
+ # self.items is used in the return value.
+ self.items.append((self._current_part.field_name, self._current_part.file))
+
+ def on_header_field(self, data: bytes, start: int, end: int) -> None:
+ self._current_partial_header_name += data[start:end]
+
+ def on_header_value(self, data: bytes, start: int, end: int) -> None:
+ self._current_partial_header_value += data[start:end]
+
+ def on_header_end(self) -> None:
+ field = self._current_partial_header_name.lower()
+ if field == b"content-disposition":
+ self._current_part.content_disposition = self._current_partial_header_value
+ self._current_part.item_headers.append(
+ (field, self._current_partial_header_value)
+ )
+ self._current_partial_header_name = b""
+ self._current_partial_header_value = b""
+
+ def on_headers_finished(self) -> None:
+ disposition, options = parse_options_header(
+ self._current_part.content_disposition
+ )
+ try:
+ self._current_part.field_name = _user_safe_decode(
+ options[b"name"], self._charset
+ )
+ except KeyError as e:
+ raise MultiPartException(
+ 'The Content-Disposition header field "name" must be ' "provided."
+ ) from e
+ if b"filename" in options:
+ self._current_files += 1
+ if self._current_files > self.max_files:
+ raise MultiPartException(
+ f"Too many files. Maximum number of files is {self.max_files}."
+ )
+ filename = _user_safe_decode(options[b"filename"], self._charset)
+ tempfile = NamedTemporaryFile(delete=False)
+ self._files_to_close_on_error.append(tempfile)
+ self._current_part.file = GradioUploadFile(
+ file=tempfile, # type: ignore[arg-type]
+ size=0,
+ filename=filename,
+ headers=Headers(raw=self._current_part.item_headers),
+ )
+ else:
+ self._current_fields += 1
+ if self._current_fields > self.max_fields:
+ raise MultiPartException(
+ f"Too many fields. Maximum number of fields is {self.max_fields}."
+ )
+ self._current_part.file = None
+
+ def on_end(self) -> None:
+ pass
+
+ async def parse(self) -> FormData:
+ # Parse the Content-Type header to get the multipart boundary.
+ _, params = parse_options_header(self.headers["Content-Type"])
+ charset = params.get(b"charset", "utf-8")
+ if isinstance(charset, bytes):
+ charset = charset.decode("latin-1")
+ self._charset = charset
+ try:
+ boundary = params[b"boundary"]
+ except KeyError as e:
+ raise MultiPartException("Missing boundary in multipart.") from e
+
+ # Callbacks dictionary.
+ callbacks = {
+ "on_part_begin": self.on_part_begin,
+ "on_part_data": self.on_part_data,
+ "on_part_end": self.on_part_end,
+ "on_header_field": self.on_header_field,
+ "on_header_value": self.on_header_value,
+ "on_header_end": self.on_header_end,
+ "on_headers_finished": self.on_headers_finished,
+ "on_end": self.on_end,
+ }
+
+ # Create the parser.
+ parser = multipart.MultipartParser(boundary, callbacks)
+ try:
+ # Feed the parser with data from the request.
+ async for chunk in self.stream:
+ parser.write(chunk)
+ # Write file data, it needs to use await with the UploadFile methods
+ # that call the corresponding file methods *in a threadpool*,
+ # otherwise, if they were called directly in the callback methods above
+ # (regular, non-async functions), that would block the event loop in
+ # the main thread.
+ for part, data in self._file_parts_to_write:
+ assert part.file # for type checkers
+ await part.file.write(data)
+ part.file.sha.update(data) # type: ignore
+ for part in self._file_parts_to_finish:
+ assert part.file # for type checkers
+ await part.file.seek(0)
+ self._file_parts_to_write.clear()
+ self._file_parts_to_finish.clear()
+ except MultiPartException as exc:
+ # Close all the files if there was an error.
+ for file in self._files_to_close_on_error:
+ file.close()
+ raise exc
+
+ parser.finalize()
+ if self.upload_progress is not None:
+ self.upload_progress.set_done(self.upload_id) # type: ignore
+ return FormData(self.items)
diff --git a/gradio/routes.py b/gradio/routes.py
new file mode 100644
index 0000000000000000000000000000000000000000..0391f0f72ff390633ce3f46dcd04a0fb2c2673b4
--- /dev/null
+++ b/gradio/routes.py
@@ -0,0 +1,935 @@
+"""Implements a FastAPI server to run the gradio interface. Note that some types in this
+module use the Optional/Union notation so that they work correctly with pydantic."""
+
+from __future__ import annotations
+
+import asyncio
+import contextlib
+import sys
+
+if sys.version_info >= (3, 9):
+ from importlib.resources import files
+else:
+ from importlib_resources import files
+import inspect
+import json
+import mimetypes
+import os
+import posixpath
+import secrets
+import shutil
+import tempfile
+import threading
+import time
+import traceback
+from pathlib import Path
+from queue import Empty as EmptyQueue
+from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, List, Optional, Type
+
+import fastapi
+import httpx
+import markupsafe
+import orjson
+from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, status
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import (
+ FileResponse,
+ HTMLResponse,
+ JSONResponse,
+ PlainTextResponse,
+)
+from fastapi.security import OAuth2PasswordRequestForm
+from fastapi.templating import Jinja2Templates
+from gradio_client import utils as client_utils
+from gradio_client.documentation import document, set_documentation_group
+from gradio_client.utils import ServerMessage
+from jinja2.exceptions import TemplateNotFound
+from multipart.multipart import parse_options_header
+from starlette.background import BackgroundTask
+from starlette.responses import RedirectResponse, StreamingResponse
+
+import gradio
+import gradio.ranged_response as ranged_response
+from gradio import route_utils, utils, wasm_utils
+from gradio.context import Context
+from gradio.data_classes import ComponentServerBody, PredictBody, ResetBody
+from gradio.exceptions import Error
+from gradio.oauth import attach_oauth
+from gradio.queueing import Estimation
+from gradio.route_utils import ( # noqa: F401
+ FileUploadProgress,
+ FileUploadProgressNotQueuedError,
+ FileUploadProgressNotTrackedError,
+ GradioMultiPartParser,
+ GradioUploadFile,
+ MultiPartException,
+ Request,
+)
+from gradio.state_holder import StateHolder
+from gradio.utils import (
+ get_package_version,
+)
+
+if TYPE_CHECKING:
+ from gradio.blocks import Block
+
+
+mimetypes.init()
+
+STATIC_TEMPLATE_LIB = files("gradio").joinpath("templates").as_posix() # type: ignore
+STATIC_PATH_LIB = files("gradio").joinpath("templates", "frontend", "static").as_posix() # type: ignore
+BUILD_PATH_LIB = files("gradio").joinpath("templates", "frontend", "assets").as_posix() # type: ignore
+VERSION = get_package_version()
+
+
+class ORJSONResponse(JSONResponse):
+ media_type = "application/json"
+
+ @staticmethod
+ def _render(content: Any) -> bytes:
+ return orjson.dumps(
+ content,
+ option=orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_PASSTHROUGH_DATETIME,
+ default=str,
+ )
+
+ def render(self, content: Any) -> bytes:
+ return ORJSONResponse._render(content)
+
+ @staticmethod
+ def _render_str(content: Any) -> str:
+ return ORJSONResponse._render(content).decode("utf-8")
+
+
+def toorjson(value):
+ return markupsafe.Markup(
+ ORJSONResponse._render_str(value)
+ .replace("<", "\\u003c")
+ .replace(">", "\\u003e")
+ .replace("&", "\\u0026")
+ .replace("'", "\\u0027")
+ )
+
+
+templates = Jinja2Templates(directory=STATIC_TEMPLATE_LIB)
+templates.env.filters["toorjson"] = toorjson
+
+client = httpx.AsyncClient()
+
+
+def move_uploaded_files_to_cache(files: list[str], destinations: list[str]) -> None:
+ for file, dest in zip(files, destinations):
+ shutil.move(file, dest)
+
+
+file_upload_statuses = FileUploadProgress()
+
+
+class App(FastAPI):
+ """
+ FastAPI App Wrapper
+ """
+
+ def __init__(self, **kwargs):
+ self.tokens = {}
+ self.auth = None
+ self.blocks: gradio.Blocks | None = None
+ self.state_holder = StateHolder()
+ self.iterators: dict[str, AsyncIterator] = {}
+ self.iterators_to_reset: set[str] = set()
+ self.lock = utils.safe_get_lock()
+ self.cookie_id = secrets.token_urlsafe(32)
+ self.queue_token = secrets.token_urlsafe(32)
+ self.startup_events_triggered = False
+ self.uploaded_file_dir = os.environ.get("GRADIO_TEMP_DIR") or str(
+ (Path(tempfile.gettempdir()) / "gradio").resolve()
+ )
+ self.change_event: None | threading.Event = None
+ self._asyncio_tasks: list[asyncio.Task] = []
+ # Allow user to manually set `docs_url` and `redoc_url`
+ # when instantiating an App; when they're not set, disable docs and redoc.
+ kwargs.setdefault("docs_url", None)
+ kwargs.setdefault("redoc_url", None)
+ super().__init__(**kwargs)
+
+ def configure_app(self, blocks: gradio.Blocks) -> None:
+ auth = blocks.auth
+ if auth is not None:
+ if not callable(auth):
+ self.auth = {account[0]: account[1] for account in auth}
+ else:
+ self.auth = auth
+ else:
+ self.auth = None
+
+ self.blocks = blocks
+ self.cwd = os.getcwd()
+ self.favicon_path = blocks.favicon_path
+ self.tokens = {}
+ self.root_path = blocks.root_path
+ self.state_holder.set_blocks(blocks)
+
+ def get_blocks(self) -> gradio.Blocks:
+ if self.blocks is None:
+ raise ValueError("No Blocks has been configured for this app.")
+ return self.blocks
+
+ def build_proxy_request(self, url_path):
+ url = httpx.URL(url_path)
+ assert self.blocks
+ # Don't proxy a URL unless it's a URL specifically loaded by the user using
+ # gr.load() to prevent SSRF or harvesting of HF tokens by malicious Spaces.
+ is_safe_url = any(
+ url.host == httpx.URL(root).host for root in self.blocks.proxy_urls
+ )
+ if not is_safe_url:
+ raise PermissionError("This URL cannot be proxied.")
+ is_hf_url = url.host.endswith(".hf.space")
+ headers = {}
+ if Context.hf_token is not None and is_hf_url:
+ headers["Authorization"] = f"Bearer {Context.hf_token}"
+ rp_req = client.build_request("GET", url, headers=headers)
+ return rp_req
+
+ def _cancel_asyncio_tasks(self):
+ for task in self._asyncio_tasks:
+ task.cancel()
+ self._asyncio_tasks = []
+
+ @staticmethod
+ def create_app(
+ blocks: gradio.Blocks, app_kwargs: Dict[str, Any] | None = None
+ ) -> App:
+ app_kwargs = app_kwargs or {}
+ app_kwargs.setdefault("default_response_class", ORJSONResponse)
+ app = App(**app_kwargs)
+ app.configure_app(blocks)
+
+ if not wasm_utils.IS_WASM:
+ app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_methods=["*"],
+ allow_headers=["*"],
+ )
+
+ @app.get("/user")
+ @app.get("/user/")
+ def get_current_user(request: fastapi.Request) -> Optional[str]:
+ token = request.cookies.get(
+ f"access-token-{app.cookie_id}"
+ ) or request.cookies.get(f"access-token-unsecure-{app.cookie_id}")
+ return app.tokens.get(token)
+
+ @app.get("/login_check")
+ @app.get("/login_check/")
+ def login_check(user: str = Depends(get_current_user)):
+ if app.auth is None or user is not None:
+ return
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated"
+ )
+
+ @app.get("/token")
+ @app.get("/token/")
+ def get_token(request: fastapi.Request) -> dict:
+ token = request.cookies.get(f"access-token-{app.cookie_id}")
+ return {"token": token, "user": app.tokens.get(token)}
+
+ @app.get("/app_id")
+ @app.get("/app_id/")
+ def app_id(request: fastapi.Request) -> dict:
+ return {"app_id": app.get_blocks().app_id}
+
+ @app.get("/dev/reload", dependencies=[Depends(login_check)])
+ async def notify_changes(
+ request: fastapi.Request,
+ ):
+ async def reload_checker(request: fastapi.Request):
+ heartbeat_rate = 15
+ check_rate = 0.05
+ last_heartbeat = time.perf_counter()
+
+ while True:
+ if await request.is_disconnected():
+ return
+
+ if app.change_event and app.change_event.is_set():
+ app.change_event.clear()
+ yield """data: CHANGE\n\n"""
+
+ await asyncio.sleep(check_rate)
+ if time.perf_counter() - last_heartbeat > heartbeat_rate:
+ yield """data: HEARTBEAT\n\n"""
+ last_heartbeat = time.time()
+
+ return StreamingResponse(
+ reload_checker(request),
+ media_type="text/event-stream",
+ )
+
+ @app.post("/login")
+ @app.post("/login/")
+ def login(form_data: OAuth2PasswordRequestForm = Depends()):
+ username, password = form_data.username.strip(), form_data.password
+ if app.auth is None:
+ return RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
+ if (
+ not callable(app.auth)
+ and username in app.auth
+ and app.auth[username] == password
+ ) or (callable(app.auth) and app.auth.__call__(username, password)):
+ token = secrets.token_urlsafe(16)
+ app.tokens[token] = username
+ response = JSONResponse(content={"success": True})
+ response.set_cookie(
+ key=f"access-token-{app.cookie_id}",
+ value=token,
+ httponly=True,
+ samesite="none",
+ secure=True,
+ )
+ response.set_cookie(
+ key=f"access-token-unsecure-{app.cookie_id}",
+ value=token,
+ httponly=True,
+ )
+ return response
+ else:
+ raise HTTPException(status_code=400, detail="Incorrect credentials.")
+
+ ###############
+ # OAuth Routes
+ ###############
+
+ # Define OAuth routes if the app expects it (i.e. a LoginButton is defined).
+ # It allows users to "Sign in with HuggingFace".
+ if app.blocks is not None and app.blocks.expects_oauth:
+ attach_oauth(app)
+
+ ###############
+ # Main Routes
+ ###############
+
+ @app.head("/", response_class=HTMLResponse)
+ @app.get("/", response_class=HTMLResponse)
+ def main(request: fastapi.Request, user: str = Depends(get_current_user)):
+ mimetypes.add_type("application/javascript", ".js")
+ blocks = app.get_blocks()
+ root_path = (
+ request.scope.get("root_path")
+ or request.headers.get("X-Direct-Url")
+ or ""
+ )
+ if app.auth is None or user is not None:
+ config = app.get_blocks().config
+ config["root"] = route_utils.strip_url(root_path)
+ else:
+ config = {
+ "auth_required": True,
+ "auth_message": blocks.auth_message,
+ "space_id": app.get_blocks().space_id,
+ "root": route_utils.strip_url(root_path),
+ }
+
+ try:
+ template = (
+ "frontend/share.html" if blocks.share else "frontend/index.html"
+ )
+ return templates.TemplateResponse(
+ template,
+ {"request": request, "config": config},
+ )
+ except TemplateNotFound as err:
+ if blocks.share:
+ raise ValueError(
+ "Did you install Gradio from source files? Share mode only "
+ "works when Gradio is installed through the pip package."
+ ) from err
+ else:
+ raise ValueError(
+ "Did you install Gradio from source files? You need to build "
+ "the frontend by running /scripts/build_frontend.sh"
+ ) from err
+
+ @app.get("/info/", dependencies=[Depends(login_check)])
+ @app.get("/info", dependencies=[Depends(login_check)])
+ def api_info(serialize: bool = True):
+ # config = app.get_blocks().get_api_info()
+ return app.get_blocks().get_api_info() # type: ignore
+
+ @app.get("/config/", dependencies=[Depends(login_check)])
+ @app.get("/config", dependencies=[Depends(login_check)])
+ def get_config(request: fastapi.Request):
+ root_path = (
+ request.scope.get("root_path")
+ or request.headers.get("X-Direct-Url")
+ or ""
+ )
+ config = app.get_blocks().config
+ config["root"] = route_utils.strip_url(root_path)
+ return config
+
+ @app.get("/static/{path:path}")
+ def static_resource(path: str):
+ static_file = safe_join(STATIC_PATH_LIB, path)
+ return FileResponse(static_file)
+
+ @app.get("/custom_component/{id}/{type}/{file_name}")
+ def custom_component_path(id: str, type: str, file_name: str):
+ config = app.get_blocks().config
+ components = config["components"]
+ location = next(
+ (item for item in components if item["component_class_id"] == id), None
+ )
+
+ if location is None:
+ raise HTTPException(status_code=404, detail="Component not found.")
+
+ component_instance = app.get_blocks().get_component(location["id"])
+
+ module_name = component_instance.__class__.__module__
+ module_path = sys.modules[module_name].__file__
+
+ if module_path is None or component_instance is None:
+ raise HTTPException(status_code=404, detail="Component not found.")
+
+ return FileResponse(
+ safe_join(
+ str(Path(module_path).parent),
+ f"{component_instance.__class__.TEMPLATE_DIR}/{type}/{file_name}",
+ )
+ )
+
+ @app.get("/assets/{path:path}")
+ def build_resource(path: str):
+ build_file = safe_join(BUILD_PATH_LIB, path)
+ return FileResponse(build_file)
+
+ @app.get("/favicon.ico")
+ async def favicon():
+ blocks = app.get_blocks()
+ if blocks.favicon_path is None:
+ return static_resource("img/logo.svg")
+ else:
+ return FileResponse(blocks.favicon_path)
+
+ @app.head("/proxy={url_path:path}", dependencies=[Depends(login_check)])
+ @app.get("/proxy={url_path:path}", dependencies=[Depends(login_check)])
+ async def reverse_proxy(url_path: str):
+ # Adapted from: https://github.com/tiangolo/fastapi/issues/1788
+ try:
+ rp_req = app.build_proxy_request(url_path)
+ except PermissionError as err:
+ raise HTTPException(status_code=400, detail=str(err)) from err
+ rp_resp = await client.send(rp_req, stream=True)
+ return StreamingResponse(
+ rp_resp.aiter_raw(),
+ status_code=rp_resp.status_code,
+ headers=rp_resp.headers, # type: ignore
+ background=BackgroundTask(rp_resp.aclose),
+ )
+
+ @app.head("/file={path_or_url:path}", dependencies=[Depends(login_check)])
+ @app.get("/file={path_or_url:path}", dependencies=[Depends(login_check)])
+ async def file(path_or_url: str, request: fastapi.Request):
+ blocks = app.get_blocks()
+ if client_utils.is_http_url_like(path_or_url):
+ return RedirectResponse(
+ url=path_or_url, status_code=status.HTTP_302_FOUND
+ )
+ abs_path = utils.abspath(path_or_url)
+
+ in_blocklist = any(
+ utils.is_in_or_equal(abs_path, blocked_path)
+ for blocked_path in blocks.blocked_paths
+ )
+ is_dir = abs_path.is_dir()
+
+ if in_blocklist or is_dir:
+ raise HTTPException(403, f"File not allowed: {path_or_url}.")
+
+ created_by_app = str(abs_path) in set().union(*blocks.temp_file_sets)
+ in_allowlist = any(
+ utils.is_in_or_equal(abs_path, allowed_path)
+ for allowed_path in blocks.allowed_paths
+ )
+ was_uploaded = utils.is_in_or_equal(abs_path, app.uploaded_file_dir)
+ is_cached_example = utils.is_in_or_equal(
+ abs_path, utils.abspath(utils.get_cache_folder())
+ )
+
+ if not (
+ created_by_app or in_allowlist or was_uploaded or is_cached_example
+ ):
+ raise HTTPException(403, f"File not allowed: {path_or_url}.")
+
+ if not abs_path.exists():
+ raise HTTPException(404, f"File not found: {path_or_url}.")
+
+ range_val = request.headers.get("Range", "").strip()
+ if range_val.startswith("bytes=") and "-" in range_val:
+ range_val = range_val[6:]
+ start, end = range_val.split("-")
+ if start.isnumeric() and end.isnumeric():
+ start = int(start)
+ end = int(end)
+ response = ranged_response.RangedFileResponse(
+ abs_path,
+ ranged_response.OpenRange(start, end),
+ dict(request.headers),
+ stat_result=os.stat(abs_path),
+ )
+ return response
+
+ return FileResponse(abs_path, headers={"Accept-Ranges": "bytes"})
+
+ @app.get(
+ "/stream/{session_hash}/{run}/{component_id}",
+ dependencies=[Depends(login_check)],
+ )
+ async def stream(
+ session_hash: str, run: int, component_id: int, request: fastapi.Request
+ ):
+ stream: list = (
+ app.get_blocks()
+ .pending_streams[session_hash]
+ .get(run, {})
+ .get(component_id, None)
+ )
+ if stream is None:
+ raise HTTPException(404, "Stream not found.")
+
+ def stream_wrapper():
+ check_stream_rate = 0.01
+ max_wait_time = 120 # maximum wait between yields - assume generator thread has crashed otherwise.
+ wait_time = 0
+ while True:
+ if len(stream) == 0:
+ if wait_time > max_wait_time:
+ return
+ wait_time += check_stream_rate
+ time.sleep(check_stream_rate)
+ continue
+ wait_time = 0
+ next_stream = stream.pop(0)
+ if next_stream is None:
+ return
+ yield next_stream
+
+ return StreamingResponse(stream_wrapper())
+
+ @app.get("/file/{path:path}", dependencies=[Depends(login_check)])
+ async def file_deprecated(path: str, request: fastapi.Request):
+ return await file(path, request)
+
+ @app.post("/reset/")
+ @app.post("/reset")
+ async def reset_iterator(body: ResetBody):
+ if body.event_id not in app.iterators:
+ return {"success": False}
+ async with app.lock:
+ del app.iterators[body.event_id]
+ app.iterators_to_reset.add(body.event_id)
+ await app.get_blocks()._queue.clean_events(event_id=body.event_id)
+ return {"success": True}
+
+ # had to use '/run' endpoint for Colab compatibility, '/api' supported for backwards compatibility
+ @app.post("/run/{api_name}", dependencies=[Depends(login_check)])
+ @app.post("/run/{api_name}/", dependencies=[Depends(login_check)])
+ @app.post("/api/{api_name}", dependencies=[Depends(login_check)])
+ @app.post("/api/{api_name}/", dependencies=[Depends(login_check)])
+ async def predict(
+ api_name: str,
+ body: PredictBody,
+ request: fastapi.Request,
+ username: str = Depends(get_current_user),
+ ):
+ fn_index_inferred = route_utils.infer_fn_index(
+ app=app, api_name=api_name, body=body
+ )
+
+ if not app.get_blocks().api_open and app.get_blocks().queue_enabled_for_fn(
+ fn_index_inferred
+ ):
+ raise HTTPException(
+ detail="This API endpoint does not accept direct HTTP POST requests. Please join the queue to use this API.",
+ status_code=status.HTTP_404_NOT_FOUND,
+ )
+
+ gr_request = route_utils.compile_gr_request(
+ app,
+ body,
+ fn_index_inferred=fn_index_inferred,
+ username=username,
+ request=request,
+ )
+
+ try:
+ output = await route_utils.call_process_api(
+ app=app,
+ body=body,
+ gr_request=gr_request,
+ fn_index_inferred=fn_index_inferred,
+ )
+ except BaseException as error:
+ show_error = app.get_blocks().show_error or isinstance(error, Error)
+ traceback.print_exc()
+ return JSONResponse(
+ content={"error": str(error) if show_error else None},
+ status_code=500,
+ )
+ return output
+
+ @app.get("/queue/data", dependencies=[Depends(login_check)])
+ async def queue_data(
+ request: fastapi.Request,
+ session_hash: str,
+ ):
+ blocks = app.get_blocks()
+
+ async def sse_stream(request: fastapi.Request):
+ try:
+ last_heartbeat = time.perf_counter()
+ while True:
+ if await request.is_disconnected():
+ await blocks._queue.clean_events(session_hash=session_hash)
+ return
+
+ if (
+ session_hash
+ not in blocks._queue.pending_messages_per_session
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Session not found.",
+ )
+
+ heartbeat_rate = 15
+ check_rate = 0.05
+ message = None
+ try:
+ messages = blocks._queue.pending_messages_per_session[
+ session_hash
+ ]
+ message = messages.get_nowait()
+ except EmptyQueue:
+ await asyncio.sleep(check_rate)
+ if time.perf_counter() - last_heartbeat > heartbeat_rate:
+ # Fix this
+ message = {
+ "msg": ServerMessage.heartbeat,
+ }
+ # Need to reset last_heartbeat with perf_counter
+ # otherwise only a single hearbeat msg will be sent
+ # and then the stream will retry leading to infinite queue 😬
+ last_heartbeat = time.perf_counter()
+
+ if blocks._queue.stopped:
+ message = {
+ "msg": "unexpected_error",
+ "message": "Server stopped unexpectedly.",
+ "success": False,
+ }
+ if message:
+ yield f"data: {json.dumps(message)}\n\n"
+ if message["msg"] == ServerMessage.process_completed:
+ blocks._queue.pending_event_ids_session[
+ session_hash
+ ].remove(message["event_id"])
+ if message["msg"] == ServerMessage.server_stopped or (
+ message["msg"] == ServerMessage.process_completed
+ and (
+ len(
+ blocks._queue.pending_event_ids_session[
+ session_hash
+ ]
+ )
+ == 0
+ )
+ ):
+ return
+ except BaseException as e:
+ message = {
+ "msg": "unexpected_error",
+ "success": False,
+ "message": str(e),
+ }
+ yield f"data: {json.dumps(message)}\n\n"
+ if isinstance(e, asyncio.CancelledError):
+ del blocks._queue.pending_messages_per_session[session_hash]
+ await blocks._queue.clean_events(session_hash=session_hash)
+ raise e
+
+ return StreamingResponse(
+ sse_stream(request),
+ media_type="text/event-stream",
+ )
+
+ @app.post("/queue/join", dependencies=[Depends(login_check)])
+ async def queue_join(
+ body: PredictBody,
+ request: fastapi.Request,
+ username: str = Depends(get_current_user),
+ ):
+ blocks = app.get_blocks()
+
+ if blocks._queue.server_app is None:
+ blocks._queue.set_server_app(app)
+
+ if blocks._queue.stopped:
+ raise HTTPException(
+ status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
+ detail="Queue is stopped.",
+ )
+
+ success, event_id = await blocks._queue.push(body, request, username)
+ if not success:
+ status_code = (
+ status.HTTP_503_SERVICE_UNAVAILABLE
+ if "Queue is full." in event_id
+ else status.HTTP_400_BAD_REQUEST
+ )
+ raise HTTPException(status_code=status_code, detail=event_id)
+ return {"event_id": event_id}
+
+ @app.post("/component_server", dependencies=[Depends(login_check)])
+ @app.post("/component_server/", dependencies=[Depends(login_check)])
+ def component_server(body: ComponentServerBody):
+ state = app.state_holder[body.session_hash]
+ component_id = body.component_id
+ block: Block
+ if component_id in state:
+ block = state[component_id]
+ else:
+ block = app.get_blocks().blocks[component_id]
+ fn = getattr(block, body.fn_name, None)
+ if fn is None or not getattr(fn, "_is_server_fn", False):
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Function not found.",
+ )
+ return fn(body.data)
+
+ @app.get(
+ "/queue/status",
+ dependencies=[Depends(login_check)],
+ response_model=Estimation,
+ )
+ async def get_queue_status():
+ return app.get_blocks()._queue.get_status()
+
+ @app.get("/upload_progress")
+ def get_upload_progress(upload_id: str, request: fastapi.Request):
+ async def sse_stream(request: fastapi.Request):
+ last_heartbeat = time.perf_counter()
+ is_done = False
+ while True:
+ if await request.is_disconnected():
+ file_upload_statuses.stop_tracking(upload_id)
+ return
+ if is_done:
+ file_upload_statuses.stop_tracking(upload_id)
+ return
+
+ heartbeat_rate = 15
+ check_rate = 0.05
+ try:
+ if file_upload_statuses.is_done(upload_id):
+ message = {"msg": "done"}
+ is_done = True
+ else:
+ update = file_upload_statuses.pop(upload_id)
+ message = {
+ "msg": "update",
+ "orig_name": update.filename,
+ "chunk_size": update.chunk_size,
+ }
+ yield f"data: {json.dumps(message)}\n\n"
+ except FileUploadProgressNotTrackedError:
+ return
+ except FileUploadProgressNotQueuedError:
+ await asyncio.sleep(check_rate)
+ if time.perf_counter() - last_heartbeat > heartbeat_rate:
+ message = {"msg": "heartbeat"}
+ yield f"data: {json.dumps(message)}\n\n"
+ last_heartbeat = time.perf_counter()
+
+ return StreamingResponse(
+ sse_stream(request),
+ media_type="text/event-stream",
+ )
+
+ @app.post("/upload", dependencies=[Depends(login_check)])
+ async def upload_file(
+ request: fastapi.Request,
+ bg_tasks: BackgroundTasks,
+ upload_id: Optional[str] = None,
+ ):
+ content_type_header = request.headers.get("Content-Type")
+ content_type: bytes
+ content_type, _ = parse_options_header(content_type_header)
+ if content_type != b"multipart/form-data":
+ raise HTTPException(status_code=400, detail="Invalid content type.")
+
+ try:
+ if upload_id:
+ file_upload_statuses.track(upload_id)
+ multipart_parser = GradioMultiPartParser(
+ request.headers,
+ request.stream(),
+ max_files=1000,
+ max_fields=1000,
+ upload_id=upload_id if upload_id else None,
+ upload_progress=file_upload_statuses if upload_id else None,
+ )
+ form = await multipart_parser.parse()
+ except MultiPartException as exc:
+ raise HTTPException(status_code=400, detail=exc.message) from exc
+
+ output_files = []
+ files_to_copy = []
+ locations: list[str] = []
+ for temp_file in form.getlist("files"):
+ assert isinstance(temp_file, GradioUploadFile)
+ if temp_file.filename:
+ file_name = Path(temp_file.filename).name
+ name = client_utils.strip_invalid_filename_characters(file_name)
+ else:
+ name = f"tmp{secrets.token_hex(5)}"
+ directory = Path(app.uploaded_file_dir) / temp_file.sha.hexdigest()
+ directory.mkdir(exist_ok=True, parents=True)
+ dest = (directory / name).resolve()
+ temp_file.file.close()
+ # we need to move the temp file to the cache directory
+ # but that's possibly blocking and we're in an async function
+ # so we try to rename (this is what shutil.move tries first)
+ # which should be super fast.
+ # if that fails, we move in the background.
+ try:
+ os.rename(temp_file.file.name, dest)
+ except OSError:
+ files_to_copy.append(temp_file.file.name)
+ locations.append(str(dest))
+ output_files.append(dest)
+ if files_to_copy:
+ bg_tasks.add_task(
+ move_uploaded_files_to_cache, files_to_copy, locations
+ )
+ return output_files
+
+ @app.on_event("startup")
+ @app.get("/startup-events")
+ async def startup_events():
+ if not app.startup_events_triggered:
+ app.get_blocks().startup_events()
+ app.startup_events_triggered = True
+ return True
+ return False
+
+ @app.get("/theme.css", response_class=PlainTextResponse)
+ def theme_css():
+ return PlainTextResponse(app.get_blocks().theme_css, media_type="text/css")
+
+ @app.get("/robots.txt", response_class=PlainTextResponse)
+ def robots_txt():
+ if app.get_blocks().share:
+ return "User-agent: *\nDisallow: /"
+ else:
+ return "User-agent: *\nDisallow: "
+
+ return app
+
+
+########
+# Helper functions
+########
+
+
+def safe_join(directory: str, path: str) -> str:
+ """Safely path to a base directory to avoid escaping the base directory.
+ Borrowed from: werkzeug.security.safe_join"""
+ _os_alt_seps: List[str] = [
+ sep for sep in [os.path.sep, os.path.altsep] if sep is not None and sep != "/"
+ ]
+
+ if path == "":
+ raise HTTPException(400)
+
+ filename = posixpath.normpath(path)
+ fullpath = os.path.join(directory, filename)
+ if (
+ any(sep in filename for sep in _os_alt_seps)
+ or os.path.isabs(filename)
+ or filename == ".."
+ or filename.startswith("../")
+ or os.path.isdir(fullpath)
+ ):
+ raise HTTPException(403)
+
+ if not os.path.exists(fullpath):
+ raise HTTPException(404, "File not found")
+
+ return fullpath
+
+
+def get_types(cls_set: List[Type]):
+ docset = []
+ types = []
+ for cls in cls_set:
+ doc = inspect.getdoc(cls) or ""
+ doc_lines = doc.split("\n")
+ for line in doc_lines:
+ if "value (" in line:
+ types.append(line.split("value (")[1].split(")")[0])
+ docset.append(doc_lines[1].split(":")[-1])
+ return docset, types
+
+
+set_documentation_group("routes")
+
+
+@document()
+def mount_gradio_app(
+ app: fastapi.FastAPI,
+ blocks: gradio.Blocks,
+ path: str,
+ app_kwargs: dict[str, Any] | None = None,
+) -> fastapi.FastAPI:
+ """Mount a gradio.Blocks to an existing FastAPI application.
+
+ Parameters:
+ app: The parent FastAPI application.
+ blocks: The blocks object we want to mount to the parent app.
+ path: The path at which the gradio application will be mounted.
+ app_kwargs: Additional keyword arguments to pass to the underlying FastAPI app as a dictionary of parameter keys and argument values. For example, `{"docs_url": "/docs"}`
+ Example:
+ from fastapi import FastAPI
+ import gradio as gr
+ app = FastAPI()
+ @app.get("/")
+ def read_main():
+ return {"message": "This is your main app"}
+ io = gr.Interface(lambda x: "Hello, " + x + "!", "textbox", "textbox")
+ app = gr.mount_gradio_app(app, io, path="/gradio")
+ # Then run `uvicorn run:app` from the terminal and navigate to http://localhost:8000/gradio.
+ """
+ blocks.dev_mode = False
+ blocks.config = blocks.get_config_file()
+ blocks.validate_queue_settings()
+ gradio_app = App.create_app(blocks, app_kwargs=app_kwargs)
+
+ old_lifespan = app.router.lifespan_context
+
+ @contextlib.asynccontextmanager
+ async def new_lifespan(app: FastAPI):
+ async with old_lifespan(
+ app
+ ): # Instert the startup events inside the FastAPI context manager
+ gradio_app.get_blocks().startup_events()
+ yield
+
+ app.router.lifespan_context = new_lifespan
+
+ app.mount(path, gradio_app)
+ return app
diff --git a/gradio/state_holder.py b/gradio/state_holder.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0c4a95dfce2ca22336cd457b1f0d35418a60673
--- /dev/null
+++ b/gradio/state_holder.py
@@ -0,0 +1,57 @@
+from __future__ import annotations
+
+import threading
+from collections import OrderedDict
+from copy import deepcopy
+from typing import TYPE_CHECKING, Any
+
+if TYPE_CHECKING:
+ from gradio.blocks import Blocks
+
+
+class StateHolder:
+ def __init__(self):
+ self.capacity = 10000
+ self.session_data = OrderedDict()
+ self.lock = threading.Lock()
+
+ def set_blocks(self, blocks: Blocks):
+ self.blocks = blocks
+ self.capacity = blocks.state_session_capacity
+
+ def __getitem__(self, session_id: str) -> SessionState:
+ if session_id not in self.session_data:
+ self.session_data[session_id] = SessionState(self.blocks)
+ self.update(session_id)
+ return self.session_data[session_id]
+
+ def __contains__(self, session_id: str):
+ return session_id in self.session_data
+
+ def update(self, session_id: str):
+ with self.lock:
+ if session_id in self.session_data:
+ self.session_data.move_to_end(session_id)
+ if len(self.session_data) > self.capacity:
+ self.session_data.popitem(last=False)
+
+
+class SessionState:
+ def __init__(self, blocks: Blocks):
+ self.blocks = blocks
+ self._data = {}
+
+ def __getitem__(self, key: int) -> Any:
+ if key not in self._data:
+ block = self.blocks.blocks[key]
+ if getattr(block, "stateful", False):
+ self._data[key] = deepcopy(getattr(block, "value", None))
+ else:
+ self._data[key] = None
+ return self._data[key]
+
+ def __setitem__(self, key: int, value: Any):
+ self._data[key] = value
+
+ def __contains__(self, key: int):
+ return key in self._data
diff --git a/gradio/strings.py b/gradio/strings.py
new file mode 100644
index 0000000000000000000000000000000000000000..f2e0a08409ce6b34e4c8c5cbadd7b56dda2cf2ad
--- /dev/null
+++ b/gradio/strings.py
@@ -0,0 +1,40 @@
+import os
+import threading
+from typing import Dict
+
+import httpx
+
+from gradio import wasm_utils
+
+MESSAGING_API_ENDPOINT = "https://api.gradio.app/gradio-messaging/en"
+
+en = {
+ "RUNNING_LOCALLY": "Running on local URL: {}",
+ "RUNNING_LOCALLY_SEPARATED": "Running on local URL: {}://{}:{}",
+ "SHARE_LINK_DISPLAY": "Running on public URL: {}",
+ "COULD_NOT_GET_SHARE_LINK": "\nCould not create share link. Please check your internet connection or our status page: https://status.gradio.app.",
+ "COULD_NOT_GET_SHARE_LINK_MISSING_FILE": "\nCould not create share link. Missing file: {}. \n\nPlease check your internet connection. This can happen if your antivirus software blocks the download of this file. You can install manually by following these steps: \n\n1. Download this file: {}\n2. Rename the downloaded file to: {}\n3. Move the file to this location: {}",
+ "COLAB_NO_LOCAL": "Cannot display local interface on google colab, public link created.",
+ "PUBLIC_SHARE_TRUE": "\nTo create a public link, set `share=True` in `launch()`.",
+ "MODEL_PUBLICLY_AVAILABLE_URL": "Model available publicly at: {} (may take up to a minute for link to be usable)",
+ "GENERATING_PUBLIC_LINK": "Generating public link (may take a few seconds...):",
+ "BETA_INVITE": "\nThanks for being a Gradio user! If you have questions or feedback, please join our Discord server and chat with us: https://discord.gg/feTf9x3ZSB",
+ "COLAB_DEBUG_TRUE": "Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. "
+ "To turn off, set debug=False in launch().",
+ "COLAB_DEBUG_FALSE": "Colab notebook detected. To show errors in colab notebook, set debug=True in launch()",
+ "COLAB_WARNING": "Note: opening Chrome Inspector may crash demo inside Colab notebooks.",
+ "SHARE_LINK_MESSAGE": "\nThis share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)",
+ "INLINE_DISPLAY_BELOW": "Interface loading below...",
+}
+
+
+def get_updated_messaging(en: Dict):
+ try:
+ updated_messaging = httpx.get(MESSAGING_API_ENDPOINT, timeout=3).json()
+ en.update(updated_messaging)
+ except Exception: # Use default messaging
+ pass
+
+
+if os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True" and not wasm_utils.IS_WASM:
+ threading.Thread(target=get_updated_messaging, args=(en,)).start()
diff --git a/gradio/templates.py b/gradio/templates.py
new file mode 100644
index 0000000000000000000000000000000000000000..94d62358f6a4adc8bbac0c2fe1a2ad8959536b4e
--- /dev/null
+++ b/gradio/templates.py
@@ -0,0 +1,628 @@
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any, Callable, Iterable, Literal
+
+import numpy as np
+from PIL import Image as _Image # using _ to minimize namespace pollution
+
+from gradio import components
+from gradio.components.audio import WaveformOptions
+from gradio.components.image_editor import Brush, Eraser
+
+
+class TextArea(components.Textbox):
+ """
+ Sets: lines=7
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | Callable | None = "",
+ *,
+ lines: int = 7,
+ max_lines: int = 20,
+ placeholder: str | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ autofocus: bool = False,
+ autoscroll: bool = True,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ type: Literal["text", "password", "email"] = "text",
+ text_align: Literal["left", "right"] | None = None,
+ rtl: bool = False,
+ show_copy_button: bool = False,
+ ):
+ super().__init__(
+ value=value,
+ lines=lines,
+ max_lines=max_lines,
+ placeholder=placeholder,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ autofocus=autofocus,
+ autoscroll=autoscroll,
+ elem_classes=elem_classes,
+ render=render,
+ type=type,
+ text_align=text_align,
+ rtl=rtl,
+ show_copy_button=show_copy_button,
+ )
+
+
+class Sketchpad(components.ImageEditor):
+ """
+ Sets: sources=(), brush=Brush(colors=["#000000"], color_mode="fixed")
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | _Image.Image | np.ndarray | None = None,
+ *,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ image_mode: Literal[
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
+ ] = "RGBA",
+ sources: Iterable[Literal["upload", "webcam", "clipboard"]] = (),
+ type: Literal["numpy", "pil", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ show_download_button: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ show_share_button: bool | None = None,
+ _selectable: bool = False,
+ crop_size: tuple[int | float, int | float] | str | None = None,
+ transforms: Iterable[Literal["crop"]] = ("crop",),
+ eraser: Eraser | None = None,
+ brush: Brush | None = None,
+ ):
+ if not brush:
+ brush = Brush(colors=["#000000"], color_mode="fixed")
+ super().__init__(
+ value=value,
+ height=height,
+ width=width,
+ image_mode=image_mode,
+ sources=sources,
+ type=type,
+ label=label,
+ every=every,
+ show_label=show_label,
+ show_download_button=show_download_button,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ mirror_webcam=mirror_webcam,
+ show_share_button=show_share_button,
+ _selectable=_selectable,
+ crop_size=crop_size,
+ transforms=transforms,
+ eraser=eraser,
+ brush=brush,
+ )
+
+
+class Paint(components.ImageEditor):
+ """
+ Sets: sources=()
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | _Image.Image | np.ndarray | None = None,
+ *,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ image_mode: Literal[
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
+ ] = "RGBA",
+ sources: Iterable[Literal["upload", "webcam", "clipboard"]] = (),
+ type: Literal["numpy", "pil", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ show_download_button: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ show_share_button: bool | None = None,
+ _selectable: bool = False,
+ crop_size: tuple[int | float, int | float] | str | None = None,
+ transforms: Iterable[Literal["crop"]] = ("crop",),
+ eraser: Eraser | None = None,
+ brush: Brush | None = None,
+ ):
+ super().__init__(
+ value=value,
+ height=height,
+ width=width,
+ image_mode=image_mode,
+ sources=sources,
+ type=type,
+ label=label,
+ every=every,
+ show_label=show_label,
+ show_download_button=show_download_button,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ mirror_webcam=mirror_webcam,
+ show_share_button=show_share_button,
+ _selectable=_selectable,
+ crop_size=crop_size,
+ transforms=transforms,
+ eraser=eraser,
+ brush=brush,
+ )
+
+
+class ImageMask(components.ImageEditor):
+ """
+ Sets: brush=Brush(colors=["#000000"], color_mode="fixed")
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | _Image.Image | np.ndarray | None = None,
+ *,
+ height: int | None = None,
+ width: int | str | None = None,
+ image_mode: Literal[
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
+ ] = "RGBA",
+ sources: Iterable[Literal["upload", "webcam", "clipboard"]] = (
+ "upload",
+ "webcam",
+ "clipboard",
+ ),
+ type: Literal["numpy", "pil", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ show_download_button: bool = True,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ show_share_button: bool | None = None,
+ _selectable: bool = False,
+ crop_size: tuple[int | float, int | float] | str | None = None,
+ transforms: Iterable[Literal["crop"]] = ("crop",),
+ eraser: Eraser | None = None,
+ brush: Brush | None = None,
+ ):
+ if not brush:
+ brush = Brush(colors=["#000000"], color_mode="fixed")
+ super().__init__(
+ value=value,
+ height=height,
+ width=width,
+ image_mode=image_mode,
+ sources=sources,
+ type=type,
+ label=label,
+ every=every,
+ show_label=show_label,
+ show_download_button=show_download_button,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ mirror_webcam=mirror_webcam,
+ show_share_button=show_share_button,
+ _selectable=_selectable,
+ crop_size=crop_size,
+ transforms=transforms,
+ eraser=eraser,
+ brush=brush,
+ )
+
+
+class PlayableVideo(components.Video):
+ """
+ Sets: format="mp4"
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str
+ | Path
+ | tuple[str | Path, str | Path | None]
+ | Callable
+ | None = None,
+ *,
+ format: Literal["mp4"] = "mp4",
+ sources: list[Literal["upload", "webcam"]] | None = None,
+ height: int | str | None = None,
+ width: int | str | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ mirror_webcam: bool = True,
+ include_audio: bool | None = None,
+ autoplay: bool = False,
+ show_share_button: bool | None = None,
+ show_download_button: bool | None = None,
+ min_length: int | None = None,
+ max_length: int | None = None,
+ ):
+ sources = ["upload"]
+ super().__init__(
+ value=value,
+ format=format,
+ sources=sources, # type: ignore
+ height=height,
+ width=width,
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ mirror_webcam=mirror_webcam,
+ include_audio=include_audio,
+ autoplay=autoplay,
+ show_share_button=show_share_button,
+ show_download_button=show_download_button,
+ min_length=min_length,
+ max_length=max_length,
+ )
+
+
+class Microphone(components.Audio):
+ """
+ Sets: sources=["microphone"]
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | Path | tuple[int, np.ndarray] | Callable | None = None,
+ *,
+ sources: list[Literal["upload", "microphone"]] | None = None,
+ type: Literal["numpy", "filepath"] = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ streaming: bool = False,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ format: Literal["wav", "mp3"] = "wav",
+ autoplay: bool = False,
+ show_download_button: bool | None = None,
+ show_share_button: bool | None = None,
+ editable: bool = True,
+ min_length: int | None = None,
+ max_length: int | None = None,
+ waveform_options: WaveformOptions | dict | None = None,
+ ):
+ sources = ["microphone"]
+ super().__init__(
+ value,
+ sources=sources,
+ type=type,
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ interactive=interactive,
+ visible=visible,
+ streaming=streaming,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ format=format,
+ autoplay=autoplay,
+ show_download_button=show_download_button,
+ show_share_button=show_share_button,
+ editable=editable,
+ min_length=min_length,
+ max_length=max_length,
+ waveform_options=waveform_options,
+ )
+
+
+class Files(components.File):
+ """
+ Sets: file_count="multiple"
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: str | list[str] | Callable | None = None,
+ *,
+ file_count: Literal["multiple"] = "multiple",
+ file_types: list[str] | None = None,
+ type: Literal["filepath", "binary"] = "filepath",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int = 160,
+ height: int | float | None = None,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ ):
+ super().__init__(
+ value,
+ file_count=file_count,
+ file_types=file_types,
+ type=type,
+ label=label,
+ every=every,
+ show_label=show_label,
+ container=container,
+ scale=scale,
+ min_width=min_width,
+ height=height,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ render=render,
+ )
+
+
+class Numpy(components.Dataframe):
+ """
+ Sets: type="numpy"
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: list[list[Any]] | Callable | None = None,
+ *,
+ headers: list[str] | None = None,
+ row_count: int | tuple[int, str] = (1, "dynamic"),
+ col_count: int | tuple[int, str] | None = None,
+ datatype: str | list[str] = "str",
+ type: Literal["numpy"] = "numpy",
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ every: float | None = None,
+ height: int = 500,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ wrap: bool = False,
+ line_breaks: bool = True,
+ column_widths: list[str | int] | None = None,
+ ):
+ super().__init__(
+ value=value,
+ headers=headers,
+ row_count=row_count,
+ col_count=col_count,
+ datatype=datatype,
+ type=type,
+ label=label,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ wrap=wrap,
+ elem_classes=elem_classes,
+ render=render,
+ line_breaks=line_breaks,
+ column_widths=column_widths,
+ every=every,
+ height=height,
+ scale=scale,
+ latex_delimiters=latex_delimiters,
+ min_width=min_width,
+ )
+
+
+class Matrix(components.Dataframe):
+ """
+ Sets: type="array"
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: list[list[Any]] | Callable | None = None,
+ *,
+ headers: list[str] | None = None,
+ row_count: int | tuple[int, str] = (1, "dynamic"),
+ col_count: int | tuple[int, str] | None = None,
+ datatype: str | list[str] = "str",
+ type: Literal["array"] = "array",
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ every: float | None = None,
+ height: int = 500,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ wrap: bool = False,
+ line_breaks: bool = True,
+ column_widths: list[str | int] | None = None,
+ ):
+ super().__init__(
+ value=value,
+ headers=headers,
+ row_count=row_count,
+ col_count=col_count,
+ datatype=datatype,
+ type=type,
+ label=label,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ wrap=wrap,
+ elem_classes=elem_classes,
+ render=render,
+ line_breaks=line_breaks,
+ column_widths=column_widths,
+ every=every,
+ height=height,
+ scale=scale,
+ latex_delimiters=latex_delimiters,
+ min_width=min_width,
+ )
+
+
+class List(components.Dataframe):
+ """
+ Sets: type="array", col_count=1
+ """
+
+ is_template = True
+
+ def __init__(
+ self,
+ value: list[list[Any]] | Callable | None = None,
+ *,
+ headers: list[str] | None = None,
+ row_count: int | tuple[int, str] = (1, "dynamic"),
+ col_count: Literal[1] = 1,
+ datatype: str | list[str] = "str",
+ type: Literal["array"] = "array",
+ latex_delimiters: list[dict[str, str | bool]] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ every: float | None = None,
+ height: int = 500,
+ scale: int | None = None,
+ min_width: int = 160,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ wrap: bool = False,
+ line_breaks: bool = True,
+ column_widths: list[str | int] | None = None,
+ ):
+ super().__init__(
+ value=value,
+ headers=headers,
+ row_count=row_count,
+ col_count=col_count,
+ datatype=datatype,
+ type=type,
+ label=label,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ wrap=wrap,
+ elem_classes=elem_classes,
+ render=render,
+ line_breaks=line_breaks,
+ column_widths=column_widths,
+ every=every,
+ height=height,
+ scale=scale,
+ latex_delimiters=latex_delimiters,
+ min_width=min_width,
+ )
+
+
+Mic = Microphone
diff --git a/gradio/test_data/__init__.py b/gradio/test_data/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gradio/test_data/blocks_configs.py b/gradio/test_data/blocks_configs.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd235a360628b4db0c432d9b205b7cf7eb3d2582
--- /dev/null
+++ b/gradio/test_data/blocks_configs.py
@@ -0,0 +1,910 @@
+XRAY_CONFIG = {
+ "version": "3.40.1",
+ "mode": "blocks",
+ "dev_mode": True,
+ "analytics_enabled": False,
+ "components": [
+ {
+ "id": 31,
+ "type": "markdown",
+ "props": {
+ "value": "Detect Disease From Scan \nWith this model you can lorem ipsum
\n\n",
+ "visible": True,
+ "rtl": False,
+ "name": "markdown",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 32,
+ "type": "checkboxgroup",
+ "props": {
+ "choices": [
+ ("Covid", "Covid"),
+ ("Malaria", "Malaria"),
+ ("Lung Cancer", "Lung Cancer"),
+ ],
+ "value": [],
+ "type": "value",
+ "label": "Disease to Scan For",
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "checkboxgroup",
+ "_selectable": False,
+ },
+ "serializer": "ListStringSerializable",
+ "api_info": {
+ "info": {"type": "array", "items": {"type": "string"}},
+ "serialized_info": False,
+ },
+ "example_inputs": {"raw": ["Covid"], "serialized": ["Covid"]},
+ },
+ {
+ "id": 33,
+ "type": "tabs",
+ "props": {"visible": True, "name": "tabs", "_selectable": False},
+ },
+ {
+ "id": 34,
+ "type": "tabitem",
+ "props": {"label": "X-ray", "name": "tabitem", "_selectable": False},
+ },
+ {
+ "id": 35,
+ "type": "row",
+ "props": {
+ "variant": "default",
+ "visible": True,
+ "equal_height": True,
+ "name": "row",
+ },
+ },
+ {
+ "id": 36,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "invert_colors": False,
+ "source": "upload",
+ "tool": "editor",
+ "type": "numpy",
+ "show_label": True,
+ "show_download_button": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "streaming": False,
+ "mirror_webcam": True,
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "show_share_button": False,
+ "name": "image",
+ "_selectable": False,
+ },
+ "serializer": "ImgSerializable",
+ "api_info": {
+ "info": {
+ "type": "string",
+ "description": "base64 representation of an image",
+ },
+ "serialized_info": True,
+ },
+ "example_inputs": {
+ "raw": "data:image/png;base64,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",
+ "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ },
+ },
+ {
+ "id": 37,
+ "type": "json",
+ "props": {
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "json",
+ },
+ "serializer": "JSONSerializable",
+ "api_info": {
+ "info": {"type": {}, "description": "any valid json"},
+ "serialized_info": True,
+ },
+ "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None},
+ },
+ {
+ "id": 38,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "variant": "secondary",
+ "visible": True,
+ "interactive": True,
+ "name": "button",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 39,
+ "type": "tabitem",
+ "props": {"label": "CT Scan", "name": "tabitem", "_selectable": False},
+ },
+ {
+ "id": 40,
+ "type": "row",
+ "props": {
+ "variant": "default",
+ "visible": True,
+ "equal_height": True,
+ "name": "row",
+ },
+ },
+ {
+ "id": 41,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "invert_colors": False,
+ "source": "upload",
+ "tool": "editor",
+ "type": "numpy",
+ "show_label": True,
+ "show_download_button": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "streaming": False,
+ "mirror_webcam": True,
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "show_share_button": False,
+ "name": "image",
+ "_selectable": False,
+ },
+ "serializer": "ImgSerializable",
+ "api_info": {
+ "info": {
+ "type": "string",
+ "description": "base64 representation of an image",
+ },
+ "serialized_info": True,
+ },
+ "example_inputs": {
+ "raw": "data:image/png;base64,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",
+ "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ },
+ },
+ {
+ "id": 42,
+ "type": "json",
+ "props": {
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "json",
+ },
+ "serializer": "JSONSerializable",
+ "api_info": {
+ "info": {"type": {}, "description": "any valid json"},
+ "serialized_info": True,
+ },
+ "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None},
+ },
+ {
+ "id": 43,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "variant": "secondary",
+ "visible": True,
+ "interactive": True,
+ "name": "button",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 44,
+ "type": "textbox",
+ "props": {
+ "value": "",
+ "lines": 1,
+ "max_lines": 20,
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "autofocus": False,
+ "type": "text",
+ "rtl": False,
+ "show_copy_button": False,
+ "name": "textbox",
+ "_selectable": False,
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 45,
+ "type": "form",
+ "props": {"scale": 0, "min_width": 0, "name": "form"},
+ },
+ {
+ "id": 46,
+ "type": "form",
+ "props": {"scale": 0, "min_width": 0, "name": "form"},
+ },
+ ],
+ "css": None,
+ "title": "Gradio",
+ "space_id": None,
+ "enable_queue": None,
+ "show_error": True,
+ "show_api": True,
+ "is_colab": False,
+ "stylesheets": [
+ "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap",
+ "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap",
+ ],
+ "theme": "default",
+ "layout": {
+ "id": 30,
+ "children": [
+ {"id": 31},
+ {"id": 45, "children": [{"id": 32}]},
+ {
+ "id": 33,
+ "children": [
+ {
+ "id": 34,
+ "children": [
+ {"id": 35, "children": [{"id": 36}, {"id": 37}]},
+ {"id": 38},
+ ],
+ },
+ {
+ "id": 39,
+ "children": [
+ {"id": 40, "children": [{"id": 41}, {"id": 42}]},
+ {"id": 43},
+ ],
+ },
+ ],
+ },
+ {"id": 46, "children": [{"id": 44}]},
+ ],
+ },
+ "dependencies": [
+ {
+ "targets": [38],
+ "trigger": "click",
+ "inputs": [32, 36],
+ "outputs": [37],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ {
+ "targets": [43],
+ "trigger": "click",
+ "inputs": [32, 41],
+ "outputs": [42],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ {
+ "targets": [],
+ "trigger": "load",
+ "inputs": [],
+ "outputs": [44],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ ],
+}
+
+XRAY_CONFIG_DIFF_IDS = {
+ "version": "3.32.0\n",
+ "mode": "blocks",
+ "dev_mode": True,
+ "analytics_enabled": False,
+ "components": [
+ {
+ "id": 1,
+ "type": "markdown",
+ "props": {
+ "value": "Detect Disease From Scan \nWith this model you can lorem ipsum
\n\n",
+ "visible": True,
+ "rtl": False,
+ "name": "markdown",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 2,
+ "type": "checkboxgroup",
+ "props": {
+ "choices": [
+ ("Covid", "Covid"),
+ ("Malaria", "Malaria"),
+ ("Lung Cancer", "Lung Cancer"),
+ ],
+ "value": [],
+ "type": "value",
+ "label": "Disease to Scan For",
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "checkboxgroup",
+ "_selectable": False,
+ },
+ "serializer": "ListStringSerializable",
+ "api_info": {
+ "info": {"type": "array", "items": {"type": "string"}},
+ "serialized_info": False,
+ },
+ "example_inputs": {"raw": ["Covid"], "serialized": ["Covid"]},
+ },
+ {
+ "id": 3,
+ "type": "tabs",
+ "props": {"visible": True, "name": "tabs", "_selectable": False},
+ },
+ {
+ "id": 4,
+ "type": "tabitem",
+ "props": {"label": "X-ray", "name": "tabitem", "_selectable": False},
+ },
+ {
+ "id": 5,
+ "type": "row",
+ "props": {
+ "variant": "default",
+ "visible": True,
+ "equal_height": True,
+ "name": "row",
+ },
+ },
+ {
+ "id": 6,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "invert_colors": False,
+ "source": "upload",
+ "tool": "editor",
+ "type": "numpy",
+ "show_label": True,
+ "show_download_button": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "streaming": False,
+ "mirror_webcam": True,
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "show_share_button": False,
+ "name": "image",
+ "_selectable": False,
+ },
+ "serializer": "ImgSerializable",
+ "api_info": {
+ "info": {
+ "type": "string",
+ "description": "base64 representation of an image",
+ },
+ "serialized_info": True,
+ },
+ "example_inputs": {
+ "raw": "data:image/png;base64,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",
+ "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ },
+ },
+ {
+ "id": 7,
+ "type": "json",
+ "props": {
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "json",
+ },
+ "serializer": "JSONSerializable",
+ "api_info": {
+ "info": {"type": {}, "description": "any valid json"},
+ "serialized_info": True,
+ },
+ "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None},
+ },
+ {
+ "id": 8,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "variant": "secondary",
+ "visible": True,
+ "interactive": True,
+ "name": "button",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 9,
+ "type": "tabitem",
+ "props": {"label": "CT Scan", "name": "tabitem", "_selectable": False},
+ },
+ {
+ "id": 10,
+ "type": "row",
+ "props": {
+ "variant": "default",
+ "visible": True,
+ "equal_height": True,
+ "name": "row",
+ },
+ },
+ {
+ "id": 11,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "invert_colors": False,
+ "source": "upload",
+ "tool": "editor",
+ "type": "numpy",
+ "show_label": True,
+ "show_download_button": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "streaming": False,
+ "mirror_webcam": True,
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "show_share_button": False,
+ "name": "image",
+ "_selectable": False,
+ },
+ "serializer": "ImgSerializable",
+ "api_info": {
+ "info": {
+ "type": "string",
+ "description": "base64 representation of an image",
+ },
+ "serialized_info": True,
+ },
+ "example_inputs": {
+ "raw": "data:image/png;base64,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",
+ "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
+ },
+ },
+ {
+ "id": 12,
+ "type": "json",
+ "props": {
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "name": "json",
+ },
+ "serializer": "JSONSerializable",
+ "api_info": {
+ "info": {"type": {}, "description": "any valid json"},
+ "serialized_info": True,
+ },
+ "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None},
+ },
+ {
+ "id": 13,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "variant": "secondary",
+ "visible": True,
+ "interactive": True,
+ "name": "button",
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 14,
+ "type": "textbox",
+ "props": {
+ "value": "",
+ "lines": 1,
+ "max_lines": 20,
+ "show_label": True,
+ "container": True,
+ "min_width": 160,
+ "visible": True,
+ "autofocus": False,
+ "type": "text",
+ "rtl": False,
+ "show_copy_button": False,
+ "name": "textbox",
+ "_selectable": False,
+ },
+ "serializer": "StringSerializable",
+ "api_info": {"info": {"type": "string"}, "serialized_info": False},
+ "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"},
+ },
+ {
+ "id": 15,
+ "type": "form",
+ "props": {"scale": 0, "min_width": 0, "name": "form"},
+ },
+ {
+ "id": 16,
+ "type": "form",
+ "props": {"scale": 0, "min_width": 0, "name": "form"},
+ },
+ ],
+ "css": None,
+ "title": "Gradio",
+ "space_id": None,
+ "enable_queue": None,
+ "show_error": True,
+ "show_api": True,
+ "is_colab": False,
+ "stylesheets": [
+ "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap",
+ "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap",
+ ],
+ "theme": "default",
+ "layout": {
+ "id": 0,
+ "children": [
+ {"id": 1},
+ {"id": 15, "children": [{"id": 2}]},
+ {
+ "id": 3,
+ "children": [
+ {
+ "id": 4,
+ "children": [
+ {"id": 5, "children": [{"id": 6}, {"id": 7}]},
+ {"id": 8},
+ ],
+ },
+ {
+ "id": 9,
+ "children": [
+ {"id": 10, "children": [{"id": 11}, {"id": 12}]},
+ {"id": 13},
+ ],
+ },
+ ],
+ },
+ {"id": 16, "children": [{"id": 14}]},
+ ],
+ },
+ "dependencies": [
+ {
+ "targets": [8],
+ "trigger": "click",
+ "inputs": [2, 6],
+ "outputs": [7],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ {
+ "targets": [13],
+ "trigger": "click",
+ "inputs": [2, 11],
+ "outputs": [12],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ {
+ "targets": [],
+ "trigger": "load",
+ "inputs": [],
+ "outputs": [14],
+ "backend_fn": True,
+ "js": None,
+ "queue": None,
+ "api_name": None,
+ "scroll_to_output": False,
+ "show_progress": "full",
+ "every": None,
+ "batch": False,
+ "max_batch_size": 4,
+ "cancels": [],
+ "types": {"continuous": False, "generator": False},
+ "collects_event_data": False,
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ },
+ ],
+}
+
+
+XRAY_CONFIG_WITH_MISTAKE = {
+ "mode": "blocks",
+ "dev_mode": True,
+ "analytics_enabled": False,
+ "theme": "default",
+ "components": [
+ {
+ "id": 1,
+ "type": "markdown",
+ "props": {
+ "value": "Detect Disease From Scan \nWith this model you can lorem ipsum
\n\n",
+ "name": "markdown",
+ "rtl": False,
+ },
+ },
+ {
+ "id": 2,
+ "type": "checkboxgroup",
+ "props": {
+ "choices": [
+ ("Covid", "Covid"),
+ ("Malaria", "Malaria"),
+ ("Lung Cancer", "Lung Cancer"),
+ ],
+ "value": [],
+ "name": "checkboxgroup",
+ "_selectable": False,
+ "show_label": True,
+ "label": "Disease to Scan For",
+ "container": True,
+ "min_width": 160,
+ },
+ },
+ {
+ "id": 3,
+ "type": "tabs",
+ "props": {
+ "value": True,
+ },
+ },
+ {
+ "id": 4,
+ "type": "tabitem",
+ "props": {
+ "label": "X-ray",
+ "value": True,
+ },
+ },
+ {
+ "id": 5,
+ "type": "row",
+ "props": {
+ "type": "row",
+ "variant": "default",
+ "equal_height": True,
+ "value": True,
+ },
+ },
+ {
+ "id": 6,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "source": "upload",
+ "streaming": False,
+ "mirror_webcam": True,
+ "tool": "editor",
+ "name": "image",
+ "_selectable": False,
+ "show_share_button": False,
+ },
+ },
+ {
+ "id": 7,
+ "type": "json",
+ "props": {
+ "name": "json",
+ },
+ },
+ {
+ "id": 8,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "name": "button",
+ "interactive": True,
+ "css": {"background-color": "red", "--hover-color": "orange"},
+ "variant": "secondary",
+ },
+ },
+ {
+ "id": 9,
+ "type": "tabitem",
+ "props": {
+ "show_label": True,
+ "label": "CT Scan",
+ "value": True,
+ },
+ },
+ {
+ "id": 10,
+ "type": "row",
+ "props": {
+ "type": "row",
+ "variant": "default",
+ "equal_height": True,
+ "value": True,
+ },
+ },
+ {
+ "id": 11,
+ "type": "image",
+ "props": {
+ "image_mode": "RGB",
+ "brush_color": "#000000",
+ "mask_opacity": 0.7,
+ "source": "upload",
+ "tool": "editor",
+ "streaming": False,
+ "mirror_webcam": True,
+ "name": "image",
+ "_selectable": False,
+ "show_share_button": False,
+ },
+ },
+ {
+ "id": 12,
+ "type": "json",
+ "props": {
+ "name": "json",
+ },
+ },
+ {
+ "id": 13,
+ "type": "button",
+ "props": {
+ "value": "Run",
+ "interactive": True,
+ "name": "button",
+ "variant": "secondary",
+ },
+ },
+ {
+ "id": 14,
+ "type": "textbox",
+ "props": {
+ "lines": 1,
+ "value": "",
+ "name": "textbox",
+ "_selectable": False,
+ "show_copy_button": False,
+ "type": "text",
+ "rtl": False,
+ "autofocus": False,
+ },
+ },
+ ],
+ "layout": {
+ "id": 0,
+ "children": [
+ {"id": 1},
+ {"id": 2},
+ {
+ "id": 3,
+ "children": [
+ {
+ "id": 4,
+ "children": [
+ {"id": 5, "children": [{"id": 6}, {"id": 7}]},
+ {"id": 8},
+ ],
+ },
+ {
+ "id": 9,
+ "children": [
+ {"id": 10, "children": [{"id": 12}, {"id": 11}]},
+ {"id": 13},
+ ],
+ },
+ ],
+ },
+ {"id": 14},
+ ],
+ },
+ "dependencies": [
+ {
+ "targets": [8],
+ "trigger": "click",
+ "inputs": [2, 6],
+ "outputs": [7],
+ "api_name": None,
+ "scroll_to_output": False,
+ "cancels": [],
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ "show_progress": "full",
+ },
+ {
+ "targets": [13],
+ "trigger": "click",
+ "inputs": [2, 11],
+ "outputs": [12],
+ "api_name": None,
+ "scroll_to_output": False,
+ "cancels": [],
+ "trigger_after": None,
+ "trigger_only_on_success": False,
+ "show_progress": "full",
+ },
+ ],
+}
diff --git a/gradio/test_data/cheetah1-copy.jpg b/gradio/test_data/cheetah1-copy.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/gradio/test_data/cheetah1-copy.jpg differ
diff --git a/gradio/test_data/cheetah1.jpg b/gradio/test_data/cheetah1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c510ff30e09c1ce410afa499f0bfc3a63c751134
Binary files /dev/null and b/gradio/test_data/cheetah1.jpg differ
diff --git a/gradio/test_data/cheetah2.jpg b/gradio/test_data/cheetah2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1408ea5af612402c1a1b998ce5e76d88f1ed1de7
Binary files /dev/null and b/gradio/test_data/cheetah2.jpg differ
diff --git a/gradio/test_data/flagged_no_log/a.txt b/gradio/test_data/flagged_no_log/a.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gradio/test_data/flagged_no_log/b.txt b/gradio/test_data/flagged_no_log/b.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gradio/test_data/flagged_no_log/c.txt b/gradio/test_data/flagged_no_log/c.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gradio/test_data/flagged_with_log/log.csv b/gradio/test_data/flagged_with_log/log.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f09847b6f72b43bc6191bcb799cbb6d5df04b543
--- /dev/null
+++ b/gradio/test_data/flagged_with_log/log.csv
@@ -0,0 +1,3 @@
+input,output
+10,20
+30,60
diff --git a/gradio/test_data/lion.jpg b/gradio/test_data/lion.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e9bf9f5d0816d6201b4862088dc74476249a6a70
Binary files /dev/null and b/gradio/test_data/lion.jpg differ
diff --git a/gradio/test_data/test_audio.wav b/gradio/test_data/test_audio.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4b40a30f4b13fa75ee6dc1ddea4ff76b782670d3
Binary files /dev/null and b/gradio/test_data/test_audio.wav differ
diff --git a/gradio/test_data/test_image.png b/gradio/test_data/test_image.png
new file mode 100644
index 0000000000000000000000000000000000000000..855b4041793a49335cf6d1b66d8c1e5059daf60f
Binary files /dev/null and b/gradio/test_data/test_image.png differ
diff --git a/gradio/themes/__init__.py b/gradio/themes/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7adbe74eef8ecee7e70d00a759c0fcf807d3185
--- /dev/null
+++ b/gradio/themes/__init__.py
@@ -0,0 +1,30 @@
+from gradio.themes.base import Base, ThemeClass
+from gradio.themes.default import Default
+from gradio.themes.glass import Glass
+from gradio.themes.monochrome import Monochrome
+from gradio.themes.soft import Soft
+from gradio.themes.utils import colors, sizes
+from gradio.themes.utils.colors import Color
+from gradio.themes.utils.fonts import Font, GoogleFont
+from gradio.themes.utils.sizes import Size
+
+__all__ = [
+ "Base",
+ "Color",
+ "Default",
+ "Font",
+ "Glass",
+ "GoogleFont",
+ "Monochrome",
+ "Size",
+ "Soft",
+ "ThemeClass",
+ "colors",
+ "sizes",
+]
+
+
+def builder(*args, **kwargs):
+ from gradio.themes.builder_app import demo
+
+ return demo.launch(*args, **kwargs)
diff --git a/gradio/themes/app.py b/gradio/themes/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..78bbc62720df53eb8c38359a11b5d3ca44057397
--- /dev/null
+++ b/gradio/themes/app.py
@@ -0,0 +1,144 @@
+import time
+
+import gradio as gr
+from gradio.themes.utils.theme_dropdown import create_theme_dropdown
+
+dropdown, js = create_theme_dropdown()
+
+with gr.Blocks(theme=gr.themes.Default()) as demo:
+ with gr.Row(equal_height=True):
+ with gr.Column(scale=10):
+ gr.Markdown(
+ """
+ # Theme preview: `{THEME}`
+ To use this theme, set `theme='{AUTHOR}/{SPACE_NAME}'` in `gr.Blocks()` or `gr.Interface()`.
+ You can append an `@` and a semantic version expression, e.g. @>=1.0.0,<2.0.0 to pin to a given version
+ of this theme.
+ """
+ )
+ with gr.Column(scale=3):
+ with gr.Group():
+ dropdown.render()
+ toggle_dark = gr.Button(value="Toggle Dark")
+
+ dropdown.change(None, dropdown, None, js=js)
+ toggle_dark.click(
+ None,
+ js="""
+ () => {
+ document.body.classList.toggle('dark');
+ }
+ """,
+ )
+
+ name = gr.Textbox(
+ label="Name",
+ info="Full name, including middle name. No special characters.",
+ placeholder="John Doe",
+ value="John Doe",
+ interactive=True,
+ )
+
+ with gr.Row():
+ slider1 = gr.Slider(label="Slider 1")
+ slider2 = gr.Slider(label="Slider 2")
+ gr.CheckboxGroup(["A", "B", "C"], label="Checkbox Group")
+
+ with gr.Row():
+ with gr.Column(variant="panel", scale=1):
+ gr.Markdown("## Panel 1")
+ radio = gr.Radio(
+ ["A", "B", "C"],
+ label="Radio",
+ info="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
+ )
+ drop = gr.Dropdown(["Option 1", "Option 2", "Option 3"], show_label=False)
+ drop_2 = gr.Dropdown(
+ ["Option A", "Option B", "Option C"],
+ multiselect=True,
+ value=["Option A"],
+ label="Dropdown",
+ interactive=True,
+ )
+ check = gr.Checkbox(label="Go")
+ with gr.Column(variant="panel", scale=2):
+ img = gr.Image(
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/header-image.jpg",
+ label="Image",
+ height=320,
+ )
+ with gr.Row():
+ go_btn = gr.Button("Go", variant="primary")
+ clear_btn = gr.Button("Clear", variant="secondary")
+
+ def go(*args):
+ time.sleep(3)
+ return "https://gradio-static-files.s3.us-west-2.amazonaws.com/header-image.jpg"
+
+ go_btn.click(go, [radio, drop, drop_2, check, name], img, api_name="go")
+
+ def clear():
+ time.sleep(0.2)
+ return None
+
+ clear_btn.click(clear, None, img)
+
+ with gr.Row():
+ btn1 = gr.Button("Button 1", size="sm")
+ btn2 = gr.UploadButton(size="sm")
+ stop_btn = gr.Button("Stop", size="sm", variant="stop")
+
+ with gr.Row():
+ gr.Dataframe(value=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], label="Dataframe")
+ gr.JSON(
+ value={"a": 1, "b": 2, "c": {"test": "a", "test2": [1, 2, 3]}}, label="JSON"
+ )
+ gr.Label(value={"cat": 0.7, "dog": 0.2, "fish": 0.1})
+ gr.File()
+ with gr.Row():
+ gr.ColorPicker()
+ gr.Video("https://gradio-static-files.s3.us-west-2.amazonaws.com/world.mp4")
+ gr.Gallery(
+ [
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/lion.jpg",
+ "lion",
+ ),
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/logo.png",
+ "logo",
+ ),
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/tower.jpg",
+ "tower",
+ ),
+ ],
+ height=200,
+ )
+
+ with gr.Row():
+ with gr.Column(scale=2):
+ chatbot = gr.Chatbot([("Hello", "Hi")], label="Chatbot")
+ chat_btn = gr.Button("Add messages")
+
+ def chat(history):
+ time.sleep(2)
+ yield [["How are you?", "I am good."]]
+
+ chat_btn.click(
+ lambda history: history
+ + [["How are you?", "I am good."]]
+ + (time.sleep(2) or []),
+ chatbot,
+ chatbot,
+ )
+ with gr.Column(scale=1):
+ with gr.Accordion("Advanced Settings"):
+ gr.Markdown("Hello")
+ gr.Number(label="Chatbot control 1")
+ gr.Number(label="Chatbot control 2")
+ gr.Number(label="Chatbot control 3")
+
+
+if __name__ == "__main__":
+ demo.queue().launch()
diff --git a/gradio/themes/base.py b/gradio/themes/base.py
new file mode 100644
index 0000000000000000000000000000000000000000..f731f3d47f4d308dbdaf87e35712358cb9e17a9d
--- /dev/null
+++ b/gradio/themes/base.py
@@ -0,0 +1,1822 @@
+from __future__ import annotations
+
+import json
+import re
+import tempfile
+import textwrap
+from pathlib import Path
+from typing import Iterable
+
+import huggingface_hub
+import semantic_version as semver
+from gradio_client.documentation import document, set_documentation_group
+from huggingface_hub import CommitOperationAdd
+
+from gradio.themes.utils import (
+ colors,
+ fonts,
+ get_matching_version,
+ get_theme_assets,
+ sizes,
+)
+from gradio.themes.utils.readme_content import README_CONTENT
+
+set_documentation_group("themes")
+
+
+class ThemeClass:
+ def __init__(self):
+ self._stylesheets = []
+ self.name = None
+
+ def _get_theme_css(self):
+ css = {}
+ dark_css = {}
+
+ for attr, val in self.__dict__.items():
+ if attr.startswith("_"):
+ continue
+ if val is None:
+ if attr.endswith("_dark"):
+ dark_css[attr[:-5]] = None
+ continue
+ else:
+ raise ValueError(
+ f"Cannot set '{attr}' to None - only dark mode variables can be None."
+ )
+ val = str(val)
+ pattern = r"(\*)([\w_]+)(\b)"
+
+ def repl_func(match):
+ full_match = match.group(0)
+ if full_match.startswith("*") and full_match.endswith("_dark"):
+ raise ValueError(
+ f"Cannot refer '{attr}' to '{val}' - dark variable references are automatically used for dark mode attributes, so do not use the _dark suffix in the value."
+ )
+ if (
+ attr.endswith("_dark")
+ and full_match.startswith("*")
+ and attr[:-5] == full_match[1:]
+ ):
+ raise ValueError(
+ f"Cannot refer '{attr}' to '{val}' - if dark and light mode values are the same, set dark mode version to None."
+ )
+
+ word = match.group(2)
+ word = word.replace("_", "-")
+ return f"var(--{word})"
+
+ val = re.sub(pattern, repl_func, val)
+
+ attr = attr.replace("_", "-")
+
+ if attr.endswith("-dark"):
+ attr = attr[:-5]
+ dark_css[attr] = val
+ else:
+ css[attr] = val
+
+ for attr, val in css.items():
+ if attr not in dark_css:
+ dark_css[attr] = val
+
+ css_code = (
+ ":root {\n"
+ + "\n".join([f" --{attr}: {val};" for attr, val in css.items()])
+ + "\n}"
+ )
+ dark_css_code = (
+ ".dark {\n"
+ + "\n".join([f" --{attr}: {val};" for attr, val in dark_css.items()])
+ + "\n}"
+ )
+
+ return f"{css_code}\n{dark_css_code}"
+
+ def to_dict(self):
+ """Convert the theme into a python dictionary."""
+ schema = {"theme": {}}
+ for prop in dir(self):
+ if (
+ not prop.startswith("_")
+ or prop.startswith("_font")
+ or prop == "_stylesheets"
+ or prop == "name"
+ ) and isinstance(getattr(self, prop), (list, str)):
+ schema["theme"][prop] = getattr(self, prop)
+ return schema
+
+ @classmethod
+ def load(cls, path: str) -> ThemeClass:
+ """Load a theme from a json file.
+
+ Parameters:
+ path: The filepath to read.
+ """
+ with open(path) as fp:
+ return cls.from_dict(json.load(fp, object_hook=fonts.as_font))
+
+ @classmethod
+ def from_dict(cls, theme: dict[str, dict[str, str]]) -> ThemeClass:
+ """Create a theme instance from a dictionary representation.
+
+ Parameters:
+ theme: The dictionary representation of the theme.
+ """
+ new_theme = cls()
+ for prop, value in theme["theme"].items():
+ setattr(new_theme, prop, value)
+
+ # For backwards compatibility, load attributes in base theme not in the loaded theme from the base theme.
+ base = Base()
+ for attr in base.__dict__:
+ if not attr.startswith("_") and not hasattr(new_theme, attr):
+ setattr(new_theme, attr, getattr(base, attr))
+
+ return new_theme
+
+ def dump(self, filename: str):
+ """Write the theme to a json file.
+
+ Parameters:
+ filename: The path to write the theme too
+ """
+ Path(filename).write_text(json.dumps(self.to_dict(), cls=fonts.FontEncoder))
+
+ @classmethod
+ def from_hub(cls, repo_name: str, hf_token: str | None = None):
+ """Load a theme from the hub.
+
+ This DOES NOT require a HuggingFace account for downloading publicly available themes.
+
+ Parameters:
+ repo_name: string of the form /@. If a semantic version expression is omitted, the latest version will be fetched.
+ hf_token: HuggingFace Token. Only needed to download private themes.
+ """
+ if "@" not in repo_name:
+ name, version = repo_name, None
+ else:
+ name, version = repo_name.split("@")
+
+ api = huggingface_hub.HfApi(token=hf_token)
+
+ try:
+ space_info = api.space_info(name)
+ except huggingface_hub.utils._errors.RepositoryNotFoundError as e:
+ raise ValueError(f"The space {name} does not exist") from e
+
+ assets = get_theme_assets(space_info)
+ matching_version = get_matching_version(assets, version)
+
+ if not matching_version:
+ raise ValueError(
+ f"Cannot find a matching version for expression {version} "
+ f"from files {[f.filename for f in assets]}"
+ )
+
+ theme_file = huggingface_hub.hf_hub_download(
+ repo_id=name,
+ repo_type="space",
+ filename=f"themes/theme_schema@{matching_version.version}.json",
+ )
+ theme = cls.load(theme_file)
+ theme.name = name
+ return theme
+
+ @staticmethod
+ def _get_next_version(space_info: huggingface_hub.hf_api.SpaceInfo) -> str:
+ assets = get_theme_assets(space_info)
+ latest_version = max(assets, key=lambda asset: asset.version).version
+ return str(latest_version.next_patch())
+
+ @staticmethod
+ def _theme_version_exists(
+ space_info: huggingface_hub.hf_api.SpaceInfo, version: str
+ ) -> bool:
+ assets = get_theme_assets(space_info)
+ return any(a.version == semver.Version(version) for a in assets)
+
+ def push_to_hub(
+ self,
+ repo_name: str,
+ org_name: str | None = None,
+ version: str | None = None,
+ hf_token: str | None = None,
+ theme_name: str | None = None,
+ description: str | None = None,
+ private: bool = False,
+ ):
+ """Upload a theme to the HuggingFace hub.
+
+ This requires a HuggingFace account.
+
+ Parameters:
+ repo_name: The name of the repository to store the theme assets, e.g. 'my_theme' or 'sunset'.
+ org_name: The name of the org to save the space in. If None (the default), the username corresponding to the logged in user, or hƒ_token is used.
+ version: A semantic version tag for theme. Bumping the version tag lets you publish updates to a theme without changing the look of applications that already loaded your theme.
+ hf_token: API token for your HuggingFace account
+ theme_name: Name for the name. If None, defaults to repo_name
+ description: A long form description to your theme.
+ """
+
+ from gradio import __version__
+
+ api = huggingface_hub.HfApi()
+
+ if not hf_token:
+ try:
+ author = huggingface_hub.whoami()["name"]
+ except OSError as e:
+ raise ValueError(
+ "In order to push to hub, log in via `huggingface-cli login` "
+ "or provide a theme_token to push_to_hub. For more information "
+ "see https://huggingface.co/docs/huggingface_hub/quick-start#login"
+ ) from e
+ else:
+ author = huggingface_hub.whoami(token=hf_token)["name"]
+
+ space_id = f"{org_name or author}/{repo_name}"
+
+ try:
+ space_info = api.space_info(space_id)
+ except Exception:
+ space_info = None
+
+ space_exists = space_info is not None
+
+ # If no version, set the version to next patch release
+ if not version:
+ version = self._get_next_version(space_info) if space_exists else "0.0.1"
+ else:
+ _ = semver.Version(version)
+
+ if space_exists and self._theme_version_exists(space_info, version):
+ raise ValueError(
+ f"The space {space_id} already has a "
+ f"theme with version {version}. See: themes/theme_schema@{version}.json. "
+ "To manually override this version, use the HuggingFace hub UI."
+ )
+
+ theme_name = theme_name or repo_name
+
+ with tempfile.NamedTemporaryFile(
+ mode="w", delete=False, suffix=".json"
+ ) as css_file:
+ contents = self.to_dict()
+ contents["version"] = version
+ json.dump(contents, css_file, cls=fonts.FontEncoder)
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as readme_file:
+ readme_content = README_CONTENT.format(
+ theme_name=theme_name,
+ description=description or "Add a description of this theme here!",
+ author=author,
+ gradio_version=__version__,
+ )
+ readme_file.write(textwrap.dedent(readme_content))
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as app_file:
+ contents = (Path(__file__).parent / "app.py").read_text()
+ contents = re.sub(
+ r"theme=gr.themes.Default\(\)",
+ f"theme='{space_id}'",
+ contents,
+ )
+ contents = re.sub(r"{THEME}", theme_name or repo_name, contents)
+ contents = re.sub(r"{AUTHOR}", org_name or author, contents)
+ contents = re.sub(r"{SPACE_NAME}", repo_name, contents)
+ app_file.write(contents)
+
+ operations = [
+ CommitOperationAdd(
+ path_in_repo=f"themes/theme_schema@{version}.json",
+ path_or_fileobj=css_file.name,
+ ),
+ CommitOperationAdd(
+ path_in_repo="README.md", path_or_fileobj=readme_file.name
+ ),
+ CommitOperationAdd(path_in_repo="app.py", path_or_fileobj=app_file.name),
+ ]
+
+ huggingface_hub.create_repo(
+ space_id,
+ repo_type="space",
+ space_sdk="gradio",
+ token=hf_token,
+ exist_ok=True,
+ private=private,
+ )
+
+ api.create_commit(
+ repo_id=space_id,
+ commit_message="Updating theme",
+ repo_type="space",
+ operations=operations,
+ token=hf_token,
+ )
+ url = f"https://huggingface.co/spaces/{space_id}"
+ print(f"See your theme here! {url}")
+ return url
+
+
+@document("push_to_hub", "from_hub", "load", "dump", "from_dict", "to_dict")
+class Base(ThemeClass):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.blue,
+ secondary_hue: colors.Color | str = colors.blue,
+ neutral_hue: colors.Color | str = colors.gray,
+ text_size: sizes.Size | str = sizes.text_md,
+ spacing_size: sizes.Size | str = sizes.spacing_md,
+ radius_size: sizes.Size | str = sizes.radius_md,
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Source Sans Pro"),
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "Consolas",
+ "monospace",
+ ),
+ ):
+ """
+ Parameters:
+ primary_hue: The primary hue of the theme. Load a preset, like gradio.themes.colors.green (or just the string "green"), or pass your own gradio.themes.utils.Color object.
+ secondary_hue: The secondary hue of the theme. Load a preset, like gradio.themes.colors.green (or just the string "green"), or pass your own gradio.themes.utils.Color object.
+ neutral_hue: The neutral hue of the theme, used . Load a preset, like gradio.themes.colors.green (or just the string "green"), or pass your own gradio.themes.utils.Color object.
+ text_size: The size of the text. Load a preset, like gradio.themes.sizes.text_sm (or just the string "sm"), or pass your own gradio.themes.utils.Size object.
+ spacing_size: The size of the spacing. Load a preset, like gradio.themes.sizes.spacing_sm (or just the string "sm"), or pass your own gradio.themes.utils.Size object.
+ radius_size: The radius size of corners. Load a preset, like gradio.themes.sizes.radius_sm (or just the string "sm"), or pass your own gradio.themes.utils.Size object.
+ font: The primary font to use for the theme. Pass a string for a system font, or a gradio.themes.font.GoogleFont object to load a font from Google Fonts. Pass a list of fonts for fallbacks.
+ font_mono: The monospace font to use for the theme, applies to code. Pass a string for a system font, or a gradio.themes.font.GoogleFont object to load a font from Google Fonts. Pass a list of fonts for fallbacks.
+ """
+
+ self.name = "base"
+
+ def expand_shortcut(shortcut, mode="color", prefix=None):
+ if not isinstance(shortcut, str):
+ return shortcut
+ if mode == "color":
+ for color in colors.Color.all:
+ if color.name == shortcut:
+ return color
+ raise ValueError(f"Color shortcut {shortcut} not found.")
+ elif mode == "size":
+ for size in sizes.Size.all:
+ if size.name == f"{prefix}_{shortcut}":
+ return size
+ raise ValueError(f"Size shortcut {shortcut} not found.")
+
+ primary_hue = expand_shortcut(primary_hue, mode="color")
+ secondary_hue = expand_shortcut(secondary_hue, mode="color")
+ neutral_hue = expand_shortcut(neutral_hue, mode="color")
+ text_size = expand_shortcut(text_size, mode="size", prefix="text")
+ spacing_size = expand_shortcut(spacing_size, mode="size", prefix="spacing")
+ radius_size = expand_shortcut(radius_size, mode="size", prefix="radius")
+
+ # Hue ranges
+ self.primary_50 = primary_hue.c50
+ self.primary_100 = primary_hue.c100
+ self.primary_200 = primary_hue.c200
+ self.primary_300 = primary_hue.c300
+ self.primary_400 = primary_hue.c400
+ self.primary_500 = primary_hue.c500
+ self.primary_600 = primary_hue.c600
+ self.primary_700 = primary_hue.c700
+ self.primary_800 = primary_hue.c800
+ self.primary_900 = primary_hue.c900
+ self.primary_950 = primary_hue.c950
+
+ self.secondary_50 = secondary_hue.c50
+ self.secondary_100 = secondary_hue.c100
+ self.secondary_200 = secondary_hue.c200
+ self.secondary_300 = secondary_hue.c300
+ self.secondary_400 = secondary_hue.c400
+ self.secondary_500 = secondary_hue.c500
+ self.secondary_600 = secondary_hue.c600
+ self.secondary_700 = secondary_hue.c700
+ self.secondary_800 = secondary_hue.c800
+ self.secondary_900 = secondary_hue.c900
+ self.secondary_950 = secondary_hue.c950
+
+ self.neutral_50 = neutral_hue.c50
+ self.neutral_100 = neutral_hue.c100
+ self.neutral_200 = neutral_hue.c200
+ self.neutral_300 = neutral_hue.c300
+ self.neutral_400 = neutral_hue.c400
+ self.neutral_500 = neutral_hue.c500
+ self.neutral_600 = neutral_hue.c600
+ self.neutral_700 = neutral_hue.c700
+ self.neutral_800 = neutral_hue.c800
+ self.neutral_900 = neutral_hue.c900
+ self.neutral_950 = neutral_hue.c950
+
+ # Spacing
+ self.spacing_xxs = spacing_size.xxs
+ self.spacing_xs = spacing_size.xs
+ self.spacing_sm = spacing_size.sm
+ self.spacing_md = spacing_size.md
+ self.spacing_lg = spacing_size.lg
+ self.spacing_xl = spacing_size.xl
+ self.spacing_xxl = spacing_size.xxl
+
+ self.radius_xxs = radius_size.xxs
+ self.radius_xs = radius_size.xs
+ self.radius_sm = radius_size.sm
+ self.radius_md = radius_size.md
+ self.radius_lg = radius_size.lg
+ self.radius_xl = radius_size.xl
+ self.radius_xxl = radius_size.xxl
+
+ self.text_xxs = text_size.xxs
+ self.text_xs = text_size.xs
+ self.text_sm = text_size.sm
+ self.text_md = text_size.md
+ self.text_lg = text_size.lg
+ self.text_xl = text_size.xl
+ self.text_xxl = text_size.xxl
+
+ # Font
+ if not isinstance(font, Iterable):
+ font = [font]
+ self._font = [
+ fontfam if isinstance(fontfam, fonts.Font) else fonts.Font(fontfam)
+ for fontfam in font
+ ]
+ if not isinstance(font_mono, Iterable):
+ font_mono = [font_mono]
+ self._font_mono = [
+ fontfam if isinstance(fontfam, fonts.Font) else fonts.Font(fontfam)
+ for fontfam in font_mono
+ ]
+ self.font = ", ".join(str(font) for font in self._font)
+ self.font_mono = ", ".join(str(font) for font in self._font_mono)
+
+ self._stylesheets = []
+ for font in self._font + self._font_mono:
+ font_stylesheet = font.stylesheet()
+ if font_stylesheet:
+ self._stylesheets.append(font_stylesheet)
+
+ self.set()
+
+ def set(
+ self,
+ *,
+ # Body Attributes: These set set the values for the entire body of the app.
+ body_background_fill=None,
+ body_background_fill_dark=None,
+ body_text_color=None,
+ body_text_color_dark=None,
+ body_text_size=None,
+ body_text_color_subdued=None,
+ body_text_color_subdued_dark=None,
+ body_text_weight=None,
+ embed_radius=None,
+ # Element Colors: These set the colors for common elements.
+ background_fill_primary=None,
+ background_fill_primary_dark=None,
+ background_fill_secondary=None,
+ background_fill_secondary_dark=None,
+ border_color_accent=None,
+ border_color_accent_dark=None,
+ border_color_accent_subdued=None,
+ border_color_accent_subdued_dark=None,
+ border_color_primary=None,
+ border_color_primary_dark=None,
+ color_accent=None,
+ color_accent_soft=None,
+ color_accent_soft_dark=None,
+ # Text: This sets the text styling for text elements.
+ link_text_color=None,
+ link_text_color_dark=None,
+ link_text_color_active=None,
+ link_text_color_active_dark=None,
+ link_text_color_hover=None,
+ link_text_color_hover_dark=None,
+ link_text_color_visited=None,
+ link_text_color_visited_dark=None,
+ prose_text_size=None,
+ prose_text_weight=None,
+ prose_header_text_weight=None,
+ code_background_fill=None,
+ code_background_fill_dark=None,
+ # Shadows: These set the high-level shadow rendering styles. These variables are often referenced by other component-specific shadow variables.
+ shadow_drop=None,
+ shadow_drop_lg=None,
+ shadow_inset=None,
+ shadow_spread=None,
+ shadow_spread_dark=None,
+ # Layout Atoms: These set the style for common layout elements, such as the blocks that wrap components.
+ block_background_fill=None,
+ block_background_fill_dark=None,
+ block_border_color=None,
+ block_border_color_dark=None,
+ block_border_width=None,
+ block_border_width_dark=None,
+ block_info_text_color=None,
+ block_info_text_color_dark=None,
+ block_info_text_size=None,
+ block_info_text_weight=None,
+ block_label_background_fill=None,
+ block_label_background_fill_dark=None,
+ block_label_border_color=None,
+ block_label_border_color_dark=None,
+ block_label_border_width=None,
+ block_label_border_width_dark=None,
+ block_label_shadow=None,
+ block_label_text_color=None,
+ block_label_text_color_dark=None,
+ block_label_margin=None,
+ block_label_padding=None,
+ block_label_radius=None,
+ block_label_right_radius=None,
+ block_label_text_size=None,
+ block_label_text_weight=None,
+ block_padding=None,
+ block_radius=None,
+ block_shadow=None,
+ block_shadow_dark=None,
+ block_title_background_fill=None,
+ block_title_background_fill_dark=None,
+ block_title_border_color=None,
+ block_title_border_color_dark=None,
+ block_title_border_width=None,
+ block_title_border_width_dark=None,
+ block_title_text_color=None,
+ block_title_text_color_dark=None,
+ block_title_padding=None,
+ block_title_radius=None,
+ block_title_text_size=None,
+ block_title_text_weight=None,
+ container_radius=None,
+ form_gap_width=None,
+ layout_gap=None,
+ panel_background_fill=None,
+ panel_background_fill_dark=None,
+ panel_border_color=None,
+ panel_border_color_dark=None,
+ panel_border_width=None,
+ panel_border_width_dark=None,
+ section_header_text_size=None,
+ section_header_text_weight=None,
+ # Component Atoms: These set the style for elements within components.
+ checkbox_background_color=None,
+ checkbox_background_color_dark=None,
+ checkbox_background_color_focus=None,
+ checkbox_background_color_focus_dark=None,
+ checkbox_background_color_hover=None,
+ checkbox_background_color_hover_dark=None,
+ checkbox_background_color_selected=None,
+ checkbox_background_color_selected_dark=None,
+ checkbox_border_color=None,
+ checkbox_border_color_dark=None,
+ checkbox_border_color_focus=None,
+ checkbox_border_color_focus_dark=None,
+ checkbox_border_color_hover=None,
+ checkbox_border_color_hover_dark=None,
+ checkbox_border_color_selected=None,
+ checkbox_border_color_selected_dark=None,
+ checkbox_border_radius=None,
+ checkbox_border_width=None,
+ checkbox_border_width_dark=None,
+ checkbox_check=None,
+ radio_circle=None,
+ checkbox_shadow=None,
+ checkbox_label_background_fill=None,
+ checkbox_label_background_fill_dark=None,
+ checkbox_label_background_fill_hover=None,
+ checkbox_label_background_fill_hover_dark=None,
+ checkbox_label_background_fill_selected=None,
+ checkbox_label_background_fill_selected_dark=None,
+ checkbox_label_border_color=None,
+ checkbox_label_border_color_dark=None,
+ checkbox_label_border_color_hover=None,
+ checkbox_label_border_color_hover_dark=None,
+ checkbox_label_border_width=None,
+ checkbox_label_border_width_dark=None,
+ checkbox_label_gap=None,
+ checkbox_label_padding=None,
+ checkbox_label_shadow=None,
+ checkbox_label_text_size=None,
+ checkbox_label_text_weight=None,
+ checkbox_label_text_color=None,
+ checkbox_label_text_color_dark=None,
+ checkbox_label_text_color_selected=None,
+ checkbox_label_text_color_selected_dark=None,
+ error_background_fill=None,
+ error_background_fill_dark=None,
+ error_border_color=None,
+ error_border_color_dark=None,
+ error_border_width=None,
+ error_border_width_dark=None,
+ error_text_color=None,
+ error_text_color_dark=None,
+ error_icon_color=None,
+ error_icon_color_dark=None,
+ input_background_fill=None,
+ input_background_fill_dark=None,
+ input_background_fill_focus=None,
+ input_background_fill_focus_dark=None,
+ input_background_fill_hover=None,
+ input_background_fill_hover_dark=None,
+ input_border_color=None,
+ input_border_color_dark=None,
+ input_border_color_focus=None,
+ input_border_color_focus_dark=None,
+ input_border_color_hover=None,
+ input_border_color_hover_dark=None,
+ input_border_width=None,
+ input_border_width_dark=None,
+ input_padding=None,
+ input_placeholder_color=None,
+ input_placeholder_color_dark=None,
+ input_radius=None,
+ input_shadow=None,
+ input_shadow_dark=None,
+ input_shadow_focus=None,
+ input_shadow_focus_dark=None,
+ input_text_size=None,
+ input_text_weight=None,
+ loader_color=None,
+ loader_color_dark=None,
+ slider_color=None,
+ slider_color_dark=None,
+ stat_background_fill=None,
+ stat_background_fill_dark=None,
+ table_border_color=None,
+ table_border_color_dark=None,
+ table_even_background_fill=None,
+ table_even_background_fill_dark=None,
+ table_odd_background_fill=None,
+ table_odd_background_fill_dark=None,
+ table_radius=None,
+ table_row_focus=None,
+ table_row_focus_dark=None,
+ # Buttons: These set the style for buttons.
+ button_border_width=None,
+ button_border_width_dark=None,
+ button_shadow=None,
+ button_shadow_active=None,
+ button_shadow_hover=None,
+ button_transition=None,
+ button_large_padding=None,
+ button_large_radius=None,
+ button_large_text_size=None,
+ button_large_text_weight=None,
+ button_small_padding=None,
+ button_small_radius=None,
+ button_small_text_size=None,
+ button_small_text_weight=None,
+ button_primary_background_fill=None,
+ button_primary_background_fill_dark=None,
+ button_primary_background_fill_hover=None,
+ button_primary_background_fill_hover_dark=None,
+ button_primary_border_color=None,
+ button_primary_border_color_dark=None,
+ button_primary_border_color_hover=None,
+ button_primary_border_color_hover_dark=None,
+ button_primary_text_color=None,
+ button_primary_text_color_dark=None,
+ button_primary_text_color_hover=None,
+ button_primary_text_color_hover_dark=None,
+ button_secondary_background_fill=None,
+ button_secondary_background_fill_dark=None,
+ button_secondary_background_fill_hover=None,
+ button_secondary_background_fill_hover_dark=None,
+ button_secondary_border_color=None,
+ button_secondary_border_color_dark=None,
+ button_secondary_border_color_hover=None,
+ button_secondary_border_color_hover_dark=None,
+ button_secondary_text_color=None,
+ button_secondary_text_color_dark=None,
+ button_secondary_text_color_hover=None,
+ button_secondary_text_color_hover_dark=None,
+ button_cancel_background_fill=None,
+ button_cancel_background_fill_dark=None,
+ button_cancel_background_fill_hover=None,
+ button_cancel_background_fill_hover_dark=None,
+ button_cancel_border_color=None,
+ button_cancel_border_color_dark=None,
+ button_cancel_border_color_hover=None,
+ button_cancel_border_color_hover_dark=None,
+ button_cancel_text_color=None,
+ button_cancel_text_color_dark=None,
+ button_cancel_text_color_hover=None,
+ button_cancel_text_color_hover_dark=None,
+ ) -> Base:
+ """
+ Parameters:
+ body_background_fill: The background of the entire app.
+ body_background_fill_dark: The background of the entire app in dark mode.
+ body_text_color: The default text color.
+ body_text_color_dark: The default text color in dark mode.
+ body_text_size: The default text size.
+ body_text_color_subdued: The text color used for softer, less important text.
+ body_text_color_subdued_dark: The text color used for softer, less important text in dark mode.
+ body_text_weight: The default text weight.
+ embed_radius: The corner radius used for embedding when the app is embedded within a page.
+ background_fill_primary: The background primarily used for items placed directly on the page.
+ background_fill_primary_dark: The background primarily used for items placed directly on the page in dark mode.
+ background_fill_secondary: The background primarily used for items placed on top of another item.
+ background_fill_secondary_dark: The background primarily used for items placed on top of another item in dark mode.
+ border_color_accent: The border color used for accented items.
+ border_color_accent_dark: The border color used for accented items in dark mode.
+ border_color_accent_subdued: The subdued border color for accented items.
+ border_color_accent_subdued_dark: The subdued border color for accented items in dark mode.
+ border_color_primary: The border color primarily used for items placed directly on the page.
+ border_color_primary_dark: The border color primarily used for items placed directly on the page in dark mode.
+ color_accent: The color used for accented items.
+ color_accent_soft: The softer color used for accented items.
+ color_accent_soft_dark: The softer color used for accented items in dark mode.
+ link_text_color: The text color used for links.
+ link_text_color_dark: The text color used for links in dark mode.
+ link_text_color_active: The text color used for links when they are active.
+ link_text_color_active_dark: The text color used for links when they are active in dark mode.
+ link_text_color_hover: The text color used for links when they are hovered over.
+ link_text_color_hover_dark: The text color used for links when they are hovered over in dark mode.
+ link_text_color_visited: The text color used for links when they have been visited.
+ link_text_color_visited_dark: The text color used for links when they have been visited in dark mode.
+ prose_text_size: The text size used for markdown and other prose.
+ prose_text_weight: The text weight used for markdown and other prose.
+ prose_header_text_weight: The text weight of a header used for markdown and other prose.
+ code_background_fill: The background color of code blocks.
+ code_background_fill_dark: The background color of code blocks in dark mode.
+ shadow_drop: Drop shadow used by other shadowed items.
+ shadow_drop_lg: Larger drop shadow used by other shadowed items.
+ shadow_inset: Inset shadow used by other shadowed items.
+ shadow_spread: Size of shadow spread used by shadowed items.
+ shadow_spread_dark: Size of shadow spread used by shadowed items in dark mode.
+ block_background_fill: The background around an item.
+ block_background_fill_dark: The background around an item in dark mode.
+ block_border_color: The border color around an item.
+ block_border_color_dark: The border color around an item in dark mode.
+ block_border_width: The border width around an item.
+ block_border_width_dark: The border width around an item in dark mode.
+ block_info_text_color: The color of the info text.
+ block_info_text_color_dark: The color of the info text in dark mode.
+ block_info_text_size: The size of the info text.
+ block_info_text_weight: The weight of the info text.
+ block_label_background_fill: The background of the title label of a media element (e.g. image).
+ block_label_background_fill_dark: The background of the title label of a media element (e.g. image) in dark mode.
+ block_label_border_color: The border color of the title label of a media element (e.g. image).
+ block_label_border_color_dark: The border color of the title label of a media element (e.g. image) in dark mode.
+ block_label_border_width: The border width of the title label of a media element (e.g. image).
+ block_label_border_width_dark: The border width of the title label of a media element (e.g. image) in dark mode.
+ block_label_shadow: The shadow of the title label of a media element (e.g. image).
+ block_label_text_color: The text color of the title label of a media element (e.g. image).
+ block_label_text_color_dark: The text color of the title label of a media element (e.g. image) in dark mode.
+ block_label_margin: The margin of the title label of a media element (e.g. image) from its surrounding container.
+ block_label_padding: The padding of the title label of a media element (e.g. image).
+ block_label_radius: The corner radius of the title label of a media element (e.g. image).
+ block_label_right_radius: The corner radius of a right-aligned helper label.
+ block_label_text_size: The text size of the title label of a media element (e.g. image).
+ block_label_text_weight: The text weight of the title label of a media element (e.g. image).
+ block_padding: The padding around an item.
+ block_radius: The corner radius around an item.
+ block_shadow: The shadow under an item.
+ block_shadow_dark: The shadow under an item in dark mode.
+ block_title_background_fill: The background of the title of a form element (e.g. textbox).
+ block_title_background_fill_dark: The background of the title of a form element (e.g. textbox) in dark mode.
+ block_title_border_color: The border color of the title of a form element (e.g. textbox).
+ block_title_border_color_dark: The border color of the title of a form element (e.g. textbox) in dark mode.
+ block_title_border_width: The border width of the title of a form element (e.g. textbox).
+ block_title_border_width_dark: The border width of the title of a form element (e.g. textbox) in dark mode.
+ block_title_text_color: The text color of the title of a form element (e.g. textbox).
+ block_title_text_color_dark: The text color of the title of a form element (e.g. textbox) in dark mode.
+ block_title_padding: The padding of the title of a form element (e.g. textbox).
+ block_title_radius: The corner radius of the title of a form element (e.g. textbox).
+ block_title_text_size: The text size of the title of a form element (e.g. textbox).
+ block_title_text_weight: The text weight of the title of a form element (e.g. textbox).
+ container_radius: The corner radius of a layout component that holds other content.
+ form_gap_width: The border gap between form elements, (e.g. consecutive textboxes).
+ layout_gap: The gap between items within a row or column.
+ panel_background_fill: The background of a panel.
+ panel_background_fill_dark: The background of a panel in dark mode.
+ panel_border_color: The border color of a panel.
+ panel_border_color_dark: The border color of a panel in dark mode.
+ panel_border_width: The border width of a panel.
+ panel_border_width_dark: The border width of a panel in dark mode.
+ section_header_text_size: The text size of a section header (e.g. tab name).
+ section_header_text_weight: The text weight of a section header (e.g. tab name).
+ checkbox_background_color: The background of a checkbox square or radio circle.
+ checkbox_background_color_dark: The background of a checkbox square or radio circle in dark mode.
+ checkbox_background_color_focus: The background of a checkbox square or radio circle when focused.
+ checkbox_background_color_focus_dark: The background of a checkbox square or radio circle when focused in dark mode.
+ checkbox_background_color_hover: The background of a checkbox square or radio circle when hovered over.
+ checkbox_background_color_hover_dark: The background of a checkbox square or radio circle when hovered over in dark mode.
+ checkbox_background_color_selected: The background of a checkbox square or radio circle when selected.
+ checkbox_background_color_selected_dark: The background of a checkbox square or radio circle when selected in dark mode.
+ checkbox_border_color: The border color of a checkbox square or radio circle.
+ checkbox_border_color_dark: The border color of a checkbox square or radio circle in dark mode.
+ checkbox_border_color_focus: The border color of a checkbox square or radio circle when focused.
+ checkbox_border_color_focus_dark: The border color of a checkbox square or radio circle when focused in dark mode.
+ checkbox_border_color_hover: The border color of a checkbox square or radio circle when hovered over.
+ checkbox_border_color_hover_dark: The border color of a checkbox square or radio circle when hovered over in dark mode.
+ checkbox_border_color_selected: The border color of a checkbox square or radio circle when selected.
+ checkbox_border_color_selected_dark: The border color of a checkbox square or radio circle when selected in dark mode.
+ checkbox_border_radius: The corner radius of a checkbox square.
+ checkbox_border_width: The border width of a checkbox square or radio circle.
+ checkbox_border_width_dark: The border width of a checkbox square or radio circle in dark mode.
+ checkbox_check: The checkmark visual of a checkbox square.
+ radio_circle: The circle visual of a radio circle.
+ checkbox_shadow: The shadow of a checkbox square or radio circle.
+ checkbox_label_background_fill: The background of the surrounding button of a checkbox or radio element.
+ checkbox_label_background_fill_dark: The background of the surrounding button of a checkbox or radio element in dark mode.
+ checkbox_label_background_fill_hover: The background of the surrounding button of a checkbox or radio element when hovered over.
+ checkbox_label_background_fill_hover_dark: The background of the surrounding button of a checkbox or radio element when hovered over in dark mode.
+ checkbox_label_background_fill_selected: The background of the surrounding button of a checkbox or radio element when selected.
+ checkbox_label_background_fill_selected_dark: The background of the surrounding button of a checkbox or radio element when selected in dark mode.
+ checkbox_label_border_color: The border color of the surrounding button of a checkbox or radio element.
+ checkbox_label_border_color_dark: The border color of the surrounding button of a checkbox or radio element in dark mode.
+ checkbox_label_border_color_hover: The border color of the surrounding button of a checkbox or radio element when hovered over.
+ checkbox_label_border_color_hover_dark: The border color of the surrounding button of a checkbox or radio element when hovered over in dark mode.
+ checkbox_label_border_width: The border width of the surrounding button of a checkbox or radio element.
+ checkbox_label_border_width_dark: The border width of the surrounding button of a checkbox or radio element in dark mode.
+ checkbox_label_gap: The gap consecutive checkbox or radio elements.
+ checkbox_label_padding: The padding of the surrounding button of a checkbox or radio element.
+ checkbox_label_shadow: The shadow of the surrounding button of a checkbox or radio element.
+ checkbox_label_text_size: The text size of the label accompanying a checkbox or radio element.
+ checkbox_label_text_weight: The text weight of the label accompanying a checkbox or radio element.
+ checkbox_label_text_color: The text color of the label accompanying a checkbox or radio element.
+ checkbox_label_text_color_dark: The text color of the label accompanying a checkbox or radio element in dark mode.
+ checkbox_label_text_color_selected: The text color of the label accompanying a checkbox or radio element when selected.
+ checkbox_label_text_color_selected_dark: The text color of the label accompanying a checkbox or radio element when selected in dark mode.
+ error_background_fill: The background of an error message.
+ error_background_fill_dark: The background of an error message in dark mode.
+ error_border_color: The border color of an error message.
+ error_border_color_dark: The border color of an error message in dark mode.
+ error_border_width: The border width of an error message.
+ error_border_width_dark: The border width of an error message in dark mode.
+ error_text_color: The text color of an error message.
+ error_text_color_dark: The text color of an error message in dark mode.
+ input_background_fill: The background of an input field.
+ input_background_fill_dark: The background of an input field in dark mode.
+ input_background_fill_focus: The background of an input field when focused.
+ input_background_fill_focus_dark: The background of an input field when focused in dark mode.
+ input_background_fill_hover: The background of an input field when hovered over.
+ input_background_fill_hover_dark: The background of an input field when hovered over in dark mode.
+ input_border_color: The border color of an input field.
+ input_border_color_dark: The border color of an input field in dark mode.
+ input_border_color_focus: The border color of an input field when focused.
+ input_border_color_focus_dark: The border color of an input field when focused in dark mode.
+ input_border_color_hover: The border color of an input field when hovered over.
+ input_border_color_hover_dark: The border color of an input field when hovered over in dark mode.
+ input_border_width: The border width of an input field.
+ input_border_width_dark: The border width of an input field in dark mode.
+ input_padding: The padding of an input field.
+ input_placeholder_color: The placeholder text color of an input field.
+ input_placeholder_color_dark: The placeholder text color of an input field in dark mode.
+ input_radius: The corner radius of an input field.
+ input_shadow: The shadow of an input field.
+ input_shadow_dark: The shadow of an input field in dark mode.
+ input_shadow_focus: The shadow of an input field when focused.
+ input_shadow_focus_dark: The shadow of an input field when focused in dark mode.
+ input_text_size: The text size of an input field.
+ input_text_weight: The text weight of an input field.
+ loader_color: The color of the loading animation while a request is pending.
+ loader_color_dark: The color of the loading animation while a request is pending in dark mode.
+ slider_color: The color of the slider in a range element.
+ slider_color_dark: The color of the slider in a range element in dark mode.
+ stat_background_fill: The background used for stats visuals (e.g. confidence bars in label).
+ stat_background_fill_dark: The background used for stats visuals (e.g. confidence bars in label) in dark mode.
+ table_border_color: The border color of a table.
+ table_border_color_dark: The border color of a table in dark mode.
+ table_even_background_fill: The background of even rows in a table.
+ table_even_background_fill_dark: The background of even rows in a table in dark mode.
+ table_odd_background_fill: The background of odd rows in a table.
+ table_odd_background_fill_dark: The background of odd rows in a table in dark mode.
+ table_radius: The corner radius of a table.
+ table_row_focus: The background of a focused row in a table.
+ table_row_focus_dark: The background of a focused row in a table in dark mode.
+ button_border_width: The border width of a button.
+ button_border_width_dark: The border width of a button in dark mode.
+ button_cancel_background_fill: The background of a button of "cancel" variant.
+ button_cancel_background_fill_dark: The background of a button of "cancel" variant in dark mode.
+ button_cancel_background_fill_hover: The background of a button of "cancel" variant when hovered over.
+ button_cancel_background_fill_hover_dark: The background of a button of "cancel" variant when hovered over in dark mode.
+ button_cancel_border_color: The border color of a button of "cancel" variant.
+ button_cancel_border_color_dark: The border color of a button of "cancel" variant in dark mode.
+ button_cancel_border_color_hover: The border color of a button of "cancel" variant when hovered over.
+ button_cancel_border_color_hover_dark: The border color of a button of "cancel" variant when hovered over in dark mode.
+ button_cancel_text_color: The text color of a button of "cancel" variant.
+ button_cancel_text_color_dark: The text color of a button of "cancel" variant in dark mode.
+ button_cancel_text_color_hover: The text color of a button of "cancel" variant when hovered over.
+ button_cancel_text_color_hover_dark: The text color of a button of "cancel" variant when hovered over in dark mode.
+ button_large_padding: The padding of a button with the default "large" size.
+ button_large_radius: The corner radius of a button with the default "large" size.
+ button_large_text_size: The text size of a button with the default "large" size.
+ button_large_text_weight: The text weight of a button with the default "large" size.
+ button_primary_background_fill: The background of a button of "primary" variant.
+ button_primary_background_fill_dark: The background of a button of "primary" variant in dark mode.
+ button_primary_background_fill_hover: The background of a button of "primary" variant when hovered over.
+ button_primary_background_fill_hover_dark: The background of a button of "primary" variant when hovered over in dark mode.
+ button_primary_border_color: The border color of a button of "primary" variant.
+ button_primary_border_color_dark: The border color of a button of "primary" variant in dark mode.
+ button_primary_border_color_hover: The border color of a button of "primary" variant when hovered over.
+ button_primary_border_color_hover_dark: The border color of a button of "primary" variant when hovered over in dark mode.
+ button_primary_text_color: The text color of a button of "primary" variant.
+ button_primary_text_color_dark: The text color of a button of "primary" variant in dark mode.
+ button_primary_text_color_hover: The text color of a button of "primary" variant when hovered over.
+ button_primary_text_color_hover_dark: The text color of a button of "primary" variant when hovered over in dark mode.
+ button_secondary_background_fill: The background of a button of default "secondary" variant.
+ button_secondary_background_fill_dark: The background of a button of default "secondary" variant in dark mode.
+ button_secondary_background_fill_hover: The background of a button of default "secondary" variant when hovered over.
+ button_secondary_background_fill_hover_dark: The background of a button of default "secondary" variant when hovered over in dark mode.
+ button_secondary_border_color: The border color of a button of default "secondary" variant.
+ button_secondary_border_color_dark: The border color of a button of default "secondary" variant in dark mode.
+ button_secondary_border_color_hover: The border color of a button of default "secondary" variant when hovered over.
+ button_secondary_border_color_hover_dark: The border color of a button of default "secondary" variant when hovered over in dark mode.
+ button_secondary_text_color: The text color of a button of default "secondary" variant.
+ button_secondary_text_color_dark: The text color of a button of default "secondary" variant in dark mode.
+ button_secondary_text_color_hover: The text color of a button of default "secondary" variant when hovered over.
+ button_secondary_text_color_hover_dark: The text color of a button of default "secondary" variant when hovered over in dark mode.
+ button_shadow: The shadow under a button.
+ button_shadow_active: The shadow under a button when pressed.
+ button_shadow_hover: The shadow under a button when hovered over.
+ button_small_padding: The padding of a button set to "small" size.
+ button_small_radius: The corner radius of a button set to "small" size.
+ button_small_text_size: The text size of a button set to "small" size.
+ button_small_text_weight: The text weight of a button set to "small" size.
+ button_transition: The transition animation duration of a button between regular, hover, and focused states.
+ """
+
+ # Body
+ self.body_background_fill = body_background_fill or getattr(
+ self, "body_background_fill", "*background_fill_primary"
+ )
+ self.body_background_fill_dark = body_background_fill_dark or getattr(
+ self, "body_background_fill_dark", "*background_fill_primary"
+ )
+ self.body_text_color = body_text_color or getattr(
+ self, "body_text_color", "*neutral_800"
+ )
+ self.body_text_color_dark = body_text_color_dark or getattr(
+ self, "body_text_color_dark", "*neutral_100"
+ )
+ self.body_text_size = body_text_size or getattr(
+ self, "body_text_size", "*text_md"
+ )
+ self.body_text_weight = body_text_weight or getattr(
+ self, "body_text_weight", "400"
+ )
+ self.embed_radius = embed_radius or getattr(self, "embed_radius", "*radius_lg")
+ # Core Colors
+ self.color_accent = color_accent or getattr(
+ self, "color_accent", "*primary_500"
+ )
+ self.color_accent_soft = color_accent_soft or getattr(
+ self, "color_accent_soft", "*primary_50"
+ )
+ self.color_accent_soft_dark = color_accent_soft_dark or getattr(
+ self, "color_accent_soft_dark", "*neutral_700"
+ )
+ self.background_fill_primary = background_fill_primary or getattr(
+ self, "background_primary", "white"
+ )
+ self.background_fill_primary_dark = background_fill_primary_dark or getattr(
+ self, "background_primary_dark", "*neutral_950"
+ )
+ self.background_fill_secondary = background_fill_secondary or getattr(
+ self, "background_secondary", "*neutral_50"
+ )
+ self.background_fill_secondary_dark = background_fill_secondary_dark or getattr(
+ self, "background_secondary_dark", "*neutral_900"
+ )
+ self.border_color_accent = border_color_accent or getattr(
+ self, "border_color_accent", "*primary_300"
+ )
+ self.border_color_accent_dark = border_color_accent_dark or getattr(
+ self, "border_color_accent_dark", "*neutral_600"
+ )
+ self.border_color_primary = border_color_primary or getattr(
+ self, "border_color_primary", "*neutral_200"
+ )
+ self.border_color_primary_dark = border_color_primary_dark or getattr(
+ self, "border_color_primary_dark", "*neutral_700"
+ )
+ # Text Colors
+ self.link_text_color = link_text_color or getattr(
+ self, "link_text_color", "*secondary_600"
+ )
+ self.link_text_color_active = link_text_color_active or getattr(
+ self, "link_text_color_active", "*secondary_600"
+ )
+ self.link_text_color_active_dark = link_text_color_active_dark or getattr(
+ self, "link_text_color_active_dark", "*secondary_500"
+ )
+ self.link_text_color_dark = link_text_color_dark or getattr(
+ self, "link_text_color_dark", "*secondary_500"
+ )
+ self.link_text_color_hover = link_text_color_hover or getattr(
+ self, "link_text_color_hover", "*secondary_700"
+ )
+ self.link_text_color_hover_dark = link_text_color_hover_dark or getattr(
+ self, "link_text_color_hover_dark", "*secondary_400"
+ )
+ self.link_text_color_visited = link_text_color_visited or getattr(
+ self, "link_text_color_visited", "*secondary_500"
+ )
+ self.link_text_color_visited_dark = link_text_color_visited_dark or getattr(
+ self, "link_text_color_visited_dark", "*secondary_600"
+ )
+ self.body_text_color_subdued = body_text_color_subdued or getattr(
+ self, "body_text_color_subdued", "*neutral_400"
+ )
+ self.body_text_color_subdued_dark = body_text_color_subdued_dark or getattr(
+ self, "body_text_color_subdued_dark", "*neutral_400"
+ )
+ # Shadows
+ self.shadow_drop = shadow_drop or getattr(
+ self, "shadow_drop", "rgba(0,0,0,0.05) 0px 1px 2px 0px"
+ )
+ self.shadow_drop_lg = shadow_drop_lg or getattr(
+ self,
+ "shadow_drop_lg",
+ "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
+ )
+ self.shadow_inset = shadow_inset or getattr(
+ self, "shadow_inset", "rgba(0,0,0,0.05) 0px 2px 4px 0px inset"
+ )
+ self.shadow_spread = shadow_spread or getattr(self, "shadow_spread", "3px")
+ self.shadow_spread_dark = shadow_spread_dark or getattr(
+ self, "shadow_spread_dark", "1px"
+ )
+ # Layout Atoms
+ self.block_background_fill = block_background_fill or getattr(
+ self, "block_background_fill", "*background_fill_primary"
+ )
+ self.block_background_fill_dark = block_background_fill_dark or getattr(
+ self, "block_background_fill_dark", "*neutral_800"
+ )
+ self.block_border_color = block_border_color or getattr(
+ self, "block_border_color", "*border_color_primary"
+ )
+ self.block_border_color_dark = block_border_color_dark or getattr(
+ self, "block_border_color_dark", "*border_color_primary"
+ )
+ self.block_border_width = block_border_width or getattr(
+ self, "block_border_width", "1px"
+ )
+ self.block_border_width_dark = block_border_width_dark or getattr(
+ self, "block_border_width_dark", None
+ )
+ self.block_info_text_color = block_info_text_color or getattr(
+ self, "block_info_text_color", "*body_text_color_subdued"
+ )
+ self.block_info_text_color_dark = block_info_text_color_dark or getattr(
+ self, "block_info_text_color_dark", "*body_text_color_subdued"
+ )
+ self.block_info_text_size = block_info_text_size or getattr(
+ self, "block_info_text_size", "*text_sm"
+ )
+ self.block_info_text_weight = block_info_text_weight or getattr(
+ self, "block_info_text_weight", "400"
+ )
+ self.block_label_background_fill = block_label_background_fill or getattr(
+ self, "block_label_background_fill", "*background_fill_primary"
+ )
+ self.block_label_background_fill_dark = (
+ block_label_background_fill_dark
+ or getattr(
+ self, "block_label_background_fill_dark", "*background_fill_secondary"
+ )
+ )
+ self.block_label_border_color = block_label_border_color or getattr(
+ self, "block_label_border_color", "*border_color_primary"
+ )
+ self.block_label_border_color_dark = block_label_border_color_dark or getattr(
+ self, "block_label_border_color_dark", "*border_color_primary"
+ )
+ self.block_label_border_width = block_label_border_width or getattr(
+ self, "block_label_border_width", "1px"
+ )
+ self.block_label_border_width_dark = block_label_border_width_dark or getattr(
+ self, "block_label_border_width_dark", None
+ )
+ self.block_label_shadow = block_label_shadow or getattr(
+ self, "block_label_shadow", "*block_shadow"
+ )
+ self.block_label_text_color = block_label_text_color or getattr(
+ self, "block_label_text_color", "*neutral_500"
+ )
+ self.block_label_text_color_dark = block_label_text_color_dark or getattr(
+ self, "block_label_text_color_dark", "*neutral_200"
+ )
+ self.block_label_margin = block_label_margin or getattr(
+ self, "block_label_margin", "0"
+ )
+ self.block_label_padding = block_label_padding or getattr(
+ self, "block_label_padding", "*spacing_sm *spacing_lg"
+ )
+ self.block_label_radius = block_label_radius or getattr(
+ self,
+ "block_label_radius",
+ "calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px) 0",
+ )
+ self.block_label_right_radius = block_label_right_radius or getattr(
+ self,
+ "block_label_right_radius",
+ "0 calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px)",
+ )
+ self.block_label_text_size = block_label_text_size or getattr(
+ self, "block_label_text_size", "*text_sm"
+ )
+ self.block_label_text_weight = block_label_text_weight or getattr(
+ self, "block_label_text_weight", "400"
+ )
+ self.block_padding = block_padding or getattr(
+ self, "block_padding", "*spacing_xl calc(*spacing_xl + 2px)"
+ )
+ self.block_radius = block_radius or getattr(self, "block_radius", "*radius_lg")
+ self.block_shadow = block_shadow or getattr(self, "block_shadow", "none")
+ self.block_shadow_dark = block_shadow_dark or getattr(
+ self, "block_shadow_dark", None
+ )
+ self.block_title_background_fill = block_title_background_fill or getattr(
+ self, "block_title_background_fill", "none"
+ )
+ self.block_title_background_fill_dark = (
+ block_title_background_fill_dark
+ or getattr(self, "block_title_background_fill_dark", None)
+ )
+ self.block_title_border_color = block_title_border_color or getattr(
+ self, "block_title_border_color", "none"
+ )
+ self.block_title_border_color_dark = block_title_border_color_dark or getattr(
+ self, "block_title_border_color_dark", None
+ )
+ self.block_title_border_width = block_title_border_width or getattr(
+ self, "block_title_border_width", "0px"
+ )
+ self.block_title_border_width_dark = block_title_border_width_dark or getattr(
+ self, "block_title_border_width_dark", None
+ )
+ self.block_title_text_color = block_title_text_color or getattr(
+ self, "block_title_text_color", "*neutral_500"
+ )
+ self.block_title_text_color_dark = block_title_text_color_dark or getattr(
+ self, "block_title_text_color_dark", "*neutral_200"
+ )
+ self.block_title_padding = block_title_padding or getattr(
+ self, "block_title_padding", "0"
+ )
+ self.block_title_radius = block_title_radius or getattr(
+ self, "block_title_radius", "none"
+ )
+ self.block_title_text_size = block_title_text_size or getattr(
+ self, "block_title_text_size", "*text_md"
+ )
+ self.block_title_text_weight = block_title_text_weight or getattr(
+ self, "block_title_text_weight", "400"
+ )
+ self.container_radius = container_radius or getattr(
+ self, "container_radius", "*radius_lg"
+ )
+ self.form_gap_width = form_gap_width or getattr(self, "form_gap_width", "0px")
+ self.layout_gap = layout_gap or getattr(self, "layout_gap", "*spacing_xxl")
+ self.panel_background_fill = panel_background_fill or getattr(
+ self, "panel_background_fill", "*background_fill_secondary"
+ )
+ self.panel_background_fill_dark = panel_background_fill_dark or getattr(
+ self, "panel_background_fill_dark", "*background_fill_secondary"
+ )
+ self.panel_border_color = panel_border_color or getattr(
+ self, "panel_border_color", "*border_color_primary"
+ )
+ self.panel_border_color_dark = panel_border_color_dark or getattr(
+ self, "panel_border_color_dark", "*border_color_primary"
+ )
+ self.panel_border_width = panel_border_width or getattr(
+ self, "panel_border_width", "0"
+ )
+ self.panel_border_width_dark = panel_border_width_dark or getattr(
+ self, "panel_border_width_dark", None
+ )
+ self.section_header_text_size = section_header_text_size or getattr(
+ self, "section_header_text_size", "*text_md"
+ )
+ self.section_header_text_weight = section_header_text_weight or getattr(
+ self, "section_header_text_weight", "400"
+ )
+ self.border_color_accent_subdued = border_color_accent_subdued or getattr(
+ self, "border_color_accent_subdued", "*border_color_accent"
+ )
+ self.border_color_accent_subdued_dark = (
+ border_color_accent_subdued_dark
+ or getattr(self, "border_color_accent_subdued_dark", "*border_color_accent")
+ )
+ # Component Atoms
+ self.code_background_fill = code_background_fill or getattr(
+ self, "code_background_fill", "*neutral_100"
+ )
+ self.code_background_fill_dark = code_background_fill_dark or getattr(
+ self, "code_background_fill_dark", "*neutral_800"
+ )
+ self.checkbox_background_color = checkbox_background_color or getattr(
+ self, "checkbox_background_color", "*background_fill_primary"
+ )
+ self.checkbox_background_color_dark = checkbox_background_color_dark or getattr(
+ self, "checkbox_background_color_dark", "*neutral_800"
+ )
+ self.checkbox_background_color_focus = (
+ checkbox_background_color_focus
+ or getattr(
+ self, "checkbox_background_color_focus", "*checkbox_background_color"
+ )
+ )
+ self.checkbox_background_color_focus_dark = (
+ checkbox_background_color_focus_dark
+ or getattr(
+ self,
+ "checkbox_background_color_focus_dark",
+ "*checkbox_background_color",
+ )
+ )
+ self.checkbox_background_color_hover = (
+ checkbox_background_color_hover
+ or getattr(
+ self, "checkbox_background_color_hover", "*checkbox_background_color"
+ )
+ )
+ self.checkbox_background_color_hover_dark = (
+ checkbox_background_color_hover_dark
+ or getattr(
+ self,
+ "checkbox_background_color_hover_dark",
+ "*checkbox_background_color",
+ )
+ )
+ self.checkbox_background_color_selected = (
+ checkbox_background_color_selected
+ or getattr(self, "checkbox_background_color_selected", "*secondary_600")
+ )
+ self.checkbox_background_color_selected_dark = (
+ checkbox_background_color_selected_dark
+ or getattr(
+ self, "checkbox_background_color_selected_dark", "*secondary_600"
+ )
+ )
+ self.checkbox_border_color = checkbox_border_color or getattr(
+ self, "checkbox_border_color", "*neutral_300"
+ )
+ self.checkbox_border_color_dark = checkbox_border_color_dark or getattr(
+ self, "checkbox_border_color_dark", "*neutral_700"
+ )
+ self.checkbox_border_color_focus = checkbox_border_color_focus or getattr(
+ self, "checkbox_border_color_focus", "*secondary_500"
+ )
+ self.checkbox_border_color_focus_dark = (
+ checkbox_border_color_focus_dark
+ or getattr(self, "checkbox_border_color_focus_dark", "*secondary_500")
+ )
+ self.checkbox_border_color_hover = checkbox_border_color_hover or getattr(
+ self, "checkbox_border_color_hover", "*neutral_300"
+ )
+ self.checkbox_border_color_hover_dark = (
+ checkbox_border_color_hover_dark
+ or getattr(self, "checkbox_border_color_hover_dark", "*neutral_600")
+ )
+ self.checkbox_border_color_selected = checkbox_border_color_selected or getattr(
+ self, "checkbox_border_color_selected", "*secondary_600"
+ )
+ self.checkbox_border_color_selected_dark = (
+ checkbox_border_color_selected_dark
+ or getattr(self, "checkbox_border_color_selected_dark", "*secondary_600")
+ )
+ self.checkbox_border_radius = checkbox_border_radius or getattr(
+ self, "checkbox_border_radius", "*radius_sm"
+ )
+ self.checkbox_border_width = checkbox_border_width or getattr(
+ self, "checkbox_border_width", "*input_border_width"
+ )
+ self.checkbox_border_width_dark = checkbox_border_width_dark or getattr(
+ self, "checkbox_border_width_dark", "*input_border_width"
+ )
+ self.checkbox_label_background_fill = checkbox_label_background_fill or getattr(
+ self, "checkbox_label_background_fill", "*button_secondary_background_fill"
+ )
+ self.checkbox_label_background_fill_dark = (
+ checkbox_label_background_fill_dark
+ or getattr(
+ self,
+ "checkbox_label_background_fill_dark",
+ "*button_secondary_background_fill",
+ )
+ )
+ self.checkbox_label_background_fill_hover = (
+ checkbox_label_background_fill_hover
+ or getattr(
+ self,
+ "checkbox_label_background_fill_hover",
+ "*button_secondary_background_fill_hover",
+ )
+ )
+ self.checkbox_label_background_fill_hover_dark = (
+ checkbox_label_background_fill_hover_dark
+ or getattr(
+ self,
+ "checkbox_label_background_fill_hover_dark",
+ "*button_secondary_background_fill_hover",
+ )
+ )
+ self.checkbox_label_background_fill_selected = (
+ checkbox_label_background_fill_selected
+ or getattr(
+ self,
+ "checkbox_label_background_fill_selected",
+ "*checkbox_label_background_fill",
+ )
+ )
+ self.checkbox_label_background_fill_selected_dark = (
+ checkbox_label_background_fill_selected_dark
+ or getattr(
+ self,
+ "checkbox_label_background_fill_selected_dark",
+ "*checkbox_label_background_fill",
+ )
+ )
+ self.checkbox_label_border_color = checkbox_label_border_color or getattr(
+ self, "checkbox_label_border_color", "*border_color_primary"
+ )
+ self.checkbox_label_border_color_dark = (
+ checkbox_label_border_color_dark
+ or getattr(
+ self, "checkbox_label_border_color_dark", "*border_color_primary"
+ )
+ )
+ self.checkbox_label_border_color_hover = (
+ checkbox_label_border_color_hover
+ or getattr(
+ self,
+ "checkbox_label_border_color_hover",
+ "*checkbox_label_border_color",
+ )
+ )
+ self.checkbox_label_border_color_hover_dark = (
+ checkbox_label_border_color_hover_dark
+ or getattr(
+ self,
+ "checkbox_label_border_color_hover_dark",
+ "*checkbox_label_border_color",
+ )
+ )
+ self.checkbox_label_border_width = checkbox_label_border_width or getattr(
+ self, "checkbox_label_border_width", "*input_border_width"
+ )
+ self.checkbox_label_border_width_dark = (
+ checkbox_label_border_width_dark
+ or getattr(self, "checkbox_label_border_width_dark", "*input_border_width")
+ )
+ self.checkbox_label_gap = checkbox_label_gap or getattr(
+ self, "checkbox_label_gap", "*spacing_lg"
+ )
+ self.checkbox_label_padding = checkbox_label_padding or getattr(
+ self, "checkbox_label_padding", "*spacing_md calc(2 * *spacing_md)"
+ )
+ self.checkbox_label_shadow = checkbox_label_shadow or getattr(
+ self, "checkbox_label_shadow", "none"
+ )
+ self.checkbox_label_text_size = checkbox_label_text_size or getattr(
+ self, "checkbox_label_text_size", "*text_md"
+ )
+ self.checkbox_label_text_weight = checkbox_label_text_weight or getattr(
+ self, "checkbox_label_text_weight", "400"
+ )
+ self.checkbox_check = checkbox_check or getattr(
+ self,
+ "checkbox_check",
+ """url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")""",
+ )
+ self.radio_circle = radio_circle or getattr(
+ self,
+ "radio_circle",
+ """url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")""",
+ )
+ self.checkbox_shadow = checkbox_shadow or getattr(
+ self, "checkbox_shadow", "*input_shadow"
+ )
+ self.checkbox_label_text_color = checkbox_label_text_color or getattr(
+ self, "checkbox_label_text_color", "*body_text_color"
+ )
+ self.checkbox_label_text_color_dark = checkbox_label_text_color_dark or getattr(
+ self, "checkbox_label_text_color_dark", "*body_text_color"
+ )
+ self.checkbox_label_text_color_selected = (
+ checkbox_label_text_color_selected
+ or getattr(
+ self, "checkbox_label_text_color_selected", "*checkbox_label_text_color"
+ )
+ )
+ self.checkbox_label_text_color_selected_dark = (
+ checkbox_label_text_color_selected_dark
+ or getattr(
+ self,
+ "checkbox_label_text_color_selected_dark",
+ "*checkbox_label_text_color",
+ )
+ )
+ self.error_background_fill = error_background_fill or getattr(
+ self, "error_background_fill", colors.red.c50
+ )
+ self.error_background_fill_dark = error_background_fill_dark or getattr(
+ self, "error_background_fill_dark", "*background_fill_primary"
+ )
+ self.error_border_color = error_border_color or getattr(
+ self, "error_border_color", colors.red.c700
+ )
+ self.error_border_color_dark = error_border_color_dark or getattr(
+ self, "error_border_color_dark", colors.red.c500
+ )
+ self.error_border_width = error_border_width or getattr(
+ self, "error_border_width", "1px"
+ )
+ self.error_border_width_dark = error_border_width_dark or getattr(
+ self, "error_border_width_dark", None
+ )
+ self.error_text_color = error_text_color or getattr(
+ self, "error_text_color", colors.red.c700
+ )
+ self.error_text_color_dark = error_text_color_dark or getattr(
+ self, "error_text_color_dark", colors.red.c50
+ )
+ self.error_icon_color = error_icon_color or getattr(
+ self, "error_icon_color", colors.red.c700
+ )
+ self.error_icon_color_dark = error_icon_color_dark or getattr(
+ self, "error_icon_color_dark", colors.red.c500
+ )
+ self.input_background_fill = input_background_fill or getattr(
+ self, "input_background_fill", "*neutral_100"
+ )
+ self.input_background_fill_dark = input_background_fill_dark or getattr(
+ self, "input_background_fill_dark", "*neutral_700"
+ )
+ self.input_background_fill_focus = input_background_fill_focus or getattr(
+ self, "input_background_fill_focus", "*secondary_500"
+ )
+ self.input_background_fill_focus_dark = (
+ input_background_fill_focus_dark
+ or getattr(self, "input_background_fill_focus_dark", "*secondary_600")
+ )
+ self.input_background_fill_hover = input_background_fill_hover or getattr(
+ self, "input_background_fill_hover", "*input_background_fill"
+ )
+ self.input_background_fill_hover_dark = (
+ input_background_fill_hover_dark
+ or getattr(
+ self, "input_background_fill_hover_dark", "*input_background_fill"
+ )
+ )
+ self.input_border_color = input_border_color or getattr(
+ self, "input_border_color", "*border_color_primary"
+ )
+ self.input_border_color_dark = input_border_color_dark or getattr(
+ self, "input_border_color_dark", "*border_color_primary"
+ )
+ self.input_border_color_focus = input_border_color_focus or getattr(
+ self, "input_border_color_focus", "*secondary_300"
+ )
+ self.input_border_color_focus_dark = input_border_color_focus_dark or getattr(
+ self, "input_border_color_focus_dark", "*neutral_700"
+ )
+ self.input_border_color_hover = input_border_color_hover or getattr(
+ self, "input_border_color_hover", "*input_border_color"
+ )
+ self.input_border_color_hover_dark = input_border_color_hover_dark or getattr(
+ self, "input_border_color_hover_dark", "*input_border_color"
+ )
+ self.input_border_width = input_border_width or getattr(
+ self, "input_border_width", "0px"
+ )
+ self.input_border_width_dark = input_border_width_dark or getattr(
+ self, "input_border_width_dark", None
+ )
+ self.input_padding = input_padding or getattr(
+ self, "input_padding", "*spacing_xl"
+ )
+ self.input_placeholder_color = input_placeholder_color or getattr(
+ self, "input_placeholder_color", "*neutral_400"
+ )
+ self.input_placeholder_color_dark = input_placeholder_color_dark or getattr(
+ self, "input_placeholder_color_dark", "*neutral_500"
+ )
+ self.input_radius = input_radius or getattr(self, "input_radius", "*radius_lg")
+ self.input_shadow = input_shadow or getattr(self, "input_shadow", "none")
+ self.input_shadow_dark = input_shadow_dark or getattr(
+ self, "input_shadow_dark", None
+ )
+ self.input_shadow_focus = input_shadow_focus or getattr(
+ self, "input_shadow_focus", "*input_shadow"
+ )
+ self.input_shadow_focus_dark = input_shadow_focus_dark or getattr(
+ self, "input_shadow_focus_dark", None
+ )
+ self.input_text_size = input_text_size or getattr(
+ self, "input_text_size", "*text_md"
+ )
+ self.input_text_weight = input_text_weight or getattr(
+ self, "input_text_weight", "400"
+ )
+ self.loader_color = loader_color or getattr(
+ self, "loader_color", "*color_accent"
+ )
+ self.loader_color_dark = loader_color_dark or getattr(
+ self, "loader_color_dark", None
+ )
+ self.prose_text_size = prose_text_size or getattr(
+ self, "prose_text_size", "*text_md"
+ )
+ self.prose_text_weight = prose_text_weight or getattr(
+ self, "prose_text_weight", "400"
+ )
+ self.prose_header_text_weight = prose_header_text_weight or getattr(
+ self, "prose_header_text_weight", "600"
+ )
+ self.slider_color = slider_color or getattr(
+ self, "slider_color", colors.blue.c600
+ )
+ self.slider_color_dark = slider_color_dark or getattr(
+ self, "slider_color_dark", None
+ )
+ self.stat_background_fill = stat_background_fill or getattr(
+ self, "stat_background_fill", "*primary_300"
+ )
+ self.stat_background_fill_dark = stat_background_fill_dark or getattr(
+ self, "stat_background_fill_dark", "*primary_500"
+ )
+ self.table_border_color = table_border_color or getattr(
+ self, "table_border_color", "*neutral_300"
+ )
+ self.table_border_color_dark = table_border_color_dark or getattr(
+ self, "table_border_color_dark", "*neutral_700"
+ )
+ self.table_even_background_fill = table_even_background_fill or getattr(
+ self, "table_even_background_fill", "white"
+ )
+ self.table_even_background_fill_dark = (
+ table_even_background_fill_dark
+ or getattr(self, "table_even_background_fill_dark", "*neutral_950")
+ )
+ self.table_odd_background_fill = table_odd_background_fill or getattr(
+ self, "table_odd_background_fill", "*neutral_50"
+ )
+ self.table_odd_background_fill_dark = table_odd_background_fill_dark or getattr(
+ self, "table_odd_background_fill_dark", "*neutral_900"
+ )
+ self.table_radius = table_radius or getattr(self, "table_radius", "*radius_lg")
+ self.table_row_focus = table_row_focus or getattr(
+ self, "table_row_focus", "*color_accent_soft"
+ )
+ self.table_row_focus_dark = table_row_focus_dark or getattr(
+ self, "table_row_focus_dark", "*color_accent_soft"
+ )
+ # Buttons
+ self.button_border_width = button_border_width or getattr(
+ self, "button_border_width", "*input_border_width"
+ )
+ self.button_border_width_dark = button_border_width_dark or getattr(
+ self, "button_border_width_dark", "*input_border_width"
+ )
+ self.button_cancel_background_fill = button_cancel_background_fill or getattr(
+ self, "button_cancel_background_fill", "*button_secondary_background_fill"
+ )
+ self.button_cancel_background_fill_dark = (
+ button_cancel_background_fill_dark
+ or getattr(
+ self,
+ "button_cancel_background_fill_dark",
+ "*button_secondary_background_fill",
+ )
+ )
+ self.button_cancel_background_fill_hover = (
+ button_cancel_background_fill_hover
+ or getattr(
+ self,
+ "button_cancel_background_fill_hover",
+ "*button_cancel_background_fill",
+ )
+ )
+ self.button_cancel_background_fill_hover_dark = (
+ button_cancel_background_fill_hover_dark
+ or getattr(
+ self,
+ "button_cancel_background_fill_hover_dark",
+ "*button_cancel_background_fill",
+ )
+ )
+ self.button_cancel_border_color = button_cancel_border_color or getattr(
+ self, "button_cancel_border_color", "*button_secondary_border_color"
+ )
+ self.button_cancel_border_color_dark = (
+ button_cancel_border_color_dark
+ or getattr(
+ self,
+ "button_cancel_border_color_dark",
+ "*button_secondary_border_color",
+ )
+ )
+ self.button_cancel_border_color_hover = (
+ button_cancel_border_color_hover
+ or getattr(
+ self,
+ "button_cancel_border_color_hover",
+ "*button_cancel_border_color",
+ )
+ )
+ self.button_cancel_border_color_hover_dark = (
+ button_cancel_border_color_hover_dark
+ or getattr(
+ self,
+ "button_cancel_border_color_hover_dark",
+ "*button_cancel_border_color",
+ )
+ )
+ self.button_cancel_text_color = button_cancel_text_color or getattr(
+ self, "button_cancel_text_color", "*button_secondary_text_color"
+ )
+ self.button_cancel_text_color_dark = button_cancel_text_color_dark or getattr(
+ self, "button_cancel_text_color_dark", "*button_secondary_text_color"
+ )
+ self.button_cancel_text_color_hover = button_cancel_text_color_hover or getattr(
+ self, "button_cancel_text_color_hover", "*button_cancel_text_color"
+ )
+ self.button_cancel_text_color_hover_dark = (
+ button_cancel_text_color_hover_dark
+ or getattr(
+ self, "button_cancel_text_color_hover_dark", "*button_cancel_text_color"
+ )
+ )
+ self.button_large_padding = button_large_padding or getattr(
+ self, "button_large_padding", "*spacing_lg calc(2 * *spacing_lg)"
+ )
+ self.button_large_radius = button_large_radius or getattr(
+ self, "button_large_radius", "*radius_lg"
+ )
+ self.button_large_text_size = button_large_text_size or getattr(
+ self, "button_large_text_size", "*text_lg"
+ )
+ self.button_large_text_weight = button_large_text_weight or getattr(
+ self, "button_large_text_weight", "600"
+ )
+ self.button_primary_background_fill = button_primary_background_fill or getattr(
+ self, "button_primary_background_fill", "*primary_200"
+ )
+ self.button_primary_background_fill_dark = (
+ button_primary_background_fill_dark
+ or getattr(self, "button_primary_background_fill_dark", "*primary_700")
+ )
+ self.button_primary_background_fill_hover = (
+ button_primary_background_fill_hover
+ or getattr(
+ self,
+ "button_primary_background_fill_hover",
+ "*button_primary_background_fill",
+ )
+ )
+ self.button_primary_background_fill_hover_dark = (
+ button_primary_background_fill_hover_dark
+ or getattr(
+ self,
+ "button_primary_background_fill_hover_dark",
+ "*button_primary_background_fill",
+ )
+ )
+ self.button_primary_border_color = button_primary_border_color or getattr(
+ self, "button_primary_border_color", "*primary_200"
+ )
+ self.button_primary_border_color_dark = (
+ button_primary_border_color_dark
+ or getattr(self, "button_primary_border_color_dark", "*primary_600")
+ )
+ self.button_primary_border_color_hover = (
+ button_primary_border_color_hover
+ or getattr(
+ self,
+ "button_primary_border_color_hover",
+ "*button_primary_border_color",
+ )
+ )
+ self.button_primary_border_color_hover_dark = (
+ button_primary_border_color_hover_dark
+ or getattr(
+ self,
+ "button_primary_border_color_hover_dark",
+ "*button_primary_border_color",
+ )
+ )
+ self.button_primary_text_color = button_primary_text_color or getattr(
+ self, "button_primary_text_color", "*primary_600"
+ )
+ self.button_primary_text_color_dark = button_primary_text_color_dark or getattr(
+ self, "button_primary_text_color_dark", "white"
+ )
+ self.button_primary_text_color_hover = (
+ button_primary_text_color_hover
+ or getattr(
+ self, "button_primary_text_color_hover", "*button_primary_text_color"
+ )
+ )
+ self.button_primary_text_color_hover_dark = (
+ button_primary_text_color_hover_dark
+ or getattr(
+ self,
+ "button_primary_text_color_hover_dark",
+ "*button_primary_text_color",
+ )
+ )
+ self.button_secondary_background_fill = (
+ button_secondary_background_fill
+ or getattr(self, "button_secondary_background_fill", "*neutral_200")
+ )
+ self.button_secondary_background_fill_dark = (
+ button_secondary_background_fill_dark
+ or getattr(self, "button_secondary_background_fill_dark", "*neutral_600")
+ )
+ self.button_secondary_background_fill_hover = (
+ button_secondary_background_fill_hover
+ or getattr(
+ self,
+ "button_secondary_background_fill_hover",
+ "*button_secondary_background_fill",
+ )
+ )
+ self.button_secondary_background_fill_hover_dark = (
+ button_secondary_background_fill_hover_dark
+ or getattr(
+ self,
+ "button_secondary_background_fill_hover_dark",
+ "*button_secondary_background_fill",
+ )
+ )
+ self.button_secondary_border_color = button_secondary_border_color or getattr(
+ self, "button_secondary_border_color", "*neutral_200"
+ )
+ self.button_secondary_border_color_dark = (
+ button_secondary_border_color_dark
+ or getattr(self, "button_secondary_border_color_dark", "*neutral_600")
+ )
+ self.button_secondary_border_color_hover = (
+ button_secondary_border_color_hover
+ or getattr(
+ self,
+ "button_secondary_border_color_hover",
+ "*button_secondary_border_color",
+ )
+ )
+ self.button_secondary_border_color_hover_dark = (
+ button_secondary_border_color_hover_dark
+ or getattr(
+ self,
+ "button_secondary_border_color_hover_dark",
+ "*button_secondary_border_color",
+ )
+ )
+ self.button_secondary_text_color = button_secondary_text_color or getattr(
+ self, "button_secondary_text_color", "*neutral_700"
+ )
+ self.button_secondary_text_color_dark = (
+ button_secondary_text_color_dark
+ or getattr(self, "button_secondary_text_color_dark", "white")
+ )
+ self.button_secondary_text_color_hover = (
+ button_secondary_text_color_hover
+ or getattr(
+ self,
+ "button_secondary_text_color_hover",
+ "*button_secondary_text_color",
+ )
+ )
+ self.button_secondary_text_color_hover_dark = (
+ button_secondary_text_color_hover_dark
+ or getattr(
+ self,
+ "button_secondary_text_color_hover_dark",
+ "*button_secondary_text_color",
+ )
+ )
+ self.button_shadow = button_shadow or getattr(self, "button_shadow", "none")
+ self.button_shadow_active = button_shadow_active or getattr(
+ self, "button_shadow_active", "none"
+ )
+ self.button_shadow_hover = button_shadow_hover or getattr(
+ self, "button_shadow_hover", "none"
+ )
+ self.button_small_padding = button_small_padding or getattr(
+ self, "button_small_padding", "*spacing_sm calc(2 * *spacing_sm)"
+ )
+ self.button_small_radius = button_small_radius or getattr(
+ self, "button_small_radius", "*radius_lg"
+ )
+ self.button_small_text_size = button_small_text_size or getattr(
+ self, "button_small_text_size", "*text_md"
+ )
+ self.button_small_text_weight = button_small_text_weight or getattr(
+ self, "button_small_text_weight", "400"
+ )
+ self.button_transition = button_transition or getattr(
+ self, "button_transition", "background-color 0.2s ease"
+ )
+ return self
diff --git a/gradio/themes/builder_app.py b/gradio/themes/builder_app.py
new file mode 100644
index 0000000000000000000000000000000000000000..44293fd919b968756376774f5f438fbb63824971
--- /dev/null
+++ b/gradio/themes/builder_app.py
@@ -0,0 +1,981 @@
+import inspect
+import time
+from typing import Iterable
+
+from gradio_client.documentation import document_fn
+
+import gradio as gr
+
+themes = [
+ gr.themes.Base,
+ gr.themes.Default,
+ gr.themes.Soft,
+ gr.themes.Monochrome,
+ gr.themes.Glass,
+]
+colors = gr.themes.Color.all
+sizes = gr.themes.Size.all
+
+palette_range = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
+size_range = ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"]
+docs_theme_core = document_fn(gr.themes.Base.__init__, gr.themes.Base)[1]
+docs_theme_vars = document_fn(gr.themes.Base.set, gr.themes.Base)[1]
+
+
+def get_docstr(var):
+ for parameters in docs_theme_core + docs_theme_vars:
+ if parameters["name"] == var:
+ return parameters["doc"]
+ raise ValueError(f"Variable {var} not found in theme documentation.")
+
+
+def get_doc_theme_var_groups():
+ source = inspect.getsource(gr.themes.Base.set)
+ groups = []
+ group, desc, variables, flat_variables = None, None, [], []
+ for line in source.splitlines():
+ line = line.strip()
+ if line.startswith(")"):
+ break
+ elif line.startswith("# "):
+ if group is not None:
+ groups.append((group, desc, variables))
+ group, desc = line[2:].split(": ")
+ variables = []
+ elif "=" in line:
+ var = line.split("=")[0]
+ variables.append(var)
+ flat_variables.append(var)
+ groups.append((group, desc, variables))
+ return groups, flat_variables
+
+
+variable_groups, flat_variables = get_doc_theme_var_groups()
+
+css = """
+.gradio-container {
+ overflow: visible !important;
+ max-width: none !important;
+}
+#controls {
+ max-height: 100vh;
+ flex-wrap: unset;
+ overflow-y: scroll;
+ position: sticky;
+ top: 0;
+}
+#controls::-webkit-scrollbar {
+ -webkit-appearance: none;
+ width: 7px;
+}
+
+#controls::-webkit-scrollbar-thumb {
+ border-radius: 4px;
+ background-color: rgba(0, 0, 0, .5);
+ box-shadow: 0 0 1px rgba(255, 255, 255, .5);
+}
+"""
+
+with gr.Blocks( # noqa: SIM117
+ theme=gr.themes.Base(),
+ css=css,
+ title="Gradio Theme Builder",
+) as demo:
+ with gr.Row():
+ with gr.Column(scale=1, elem_id="controls", min_width=400):
+ with gr.Row():
+ undo_btn = gr.Button("Undo", size="sm")
+ dark_mode_btn = gr.Button("Dark Mode", variant="primary", size="sm")
+ with gr.Tabs():
+ with gr.TabItem("Source Theme"):
+ gr.Markdown(
+ """
+ Select a base theme below you would like to build off of. Note: when you click 'Load Theme', all variable values in other tabs will be overwritten!
+ """
+ )
+ base_theme_dropdown = gr.Dropdown(
+ [theme.__name__ for theme in themes],
+ value="Base",
+ show_label=False,
+ )
+ load_theme_btn = gr.Button("Load Theme", elem_id="load_theme")
+ with gr.TabItem("Core Colors"):
+ gr.Markdown(
+ """Set the three hues of the theme: `primary_hue`, `secondary_hue`, and `neutral_hue`.
+ Each of these is a palette ranging from 50 to 950 in brightness. Pick a preset palette - optionally, open the accordion to overwrite specific values.
+ Note that these variables do not affect elements directly, but are referenced by other variables with asterisks, such as `*primary_200` or `*neutral_950`."""
+ )
+ primary_hue = gr.Dropdown(
+ [color.name for color in colors], label="Primary Hue"
+ )
+ with gr.Accordion(label="Primary Hue Palette", open=False):
+ primary_hues = []
+ for i in palette_range:
+ primary_hues.append(
+ gr.ColorPicker(
+ label=f"primary_{i}",
+ )
+ )
+
+ secondary_hue = gr.Dropdown(
+ [color.name for color in colors], label="Secondary Hue"
+ )
+ with gr.Accordion(label="Secondary Hue Palette", open=False):
+ secondary_hues = []
+ for i in palette_range:
+ secondary_hues.append(
+ gr.ColorPicker(
+ label=f"secondary_{i}",
+ )
+ )
+
+ neutral_hue = gr.Dropdown(
+ [color.name for color in colors], label="Neutral hue"
+ )
+ with gr.Accordion(label="Neutral Hue Palette", open=False):
+ neutral_hues = []
+ for i in palette_range:
+ neutral_hues.append(
+ gr.ColorPicker(
+ label=f"neutral_{i}",
+ )
+ )
+
+ with gr.TabItem("Core Sizing"):
+ gr.Markdown(
+ """Set the sizing of the theme via: `text_size`, `spacing_size`, and `radius_size`.
+ Each of these is set to a collection of sizes ranging from `xxs` to `xxl`. Pick a preset size collection - optionally, open the accordion to overwrite specific values.
+ Note that these variables do not affect elements directly, but are referenced by other variables with asterisks, such as `*spacing_xl` or `*text_sm`.
+ """
+ )
+ text_size = gr.Dropdown(
+ [size.name for size in sizes if size.name.startswith("text_")],
+ label="Text Size",
+ )
+ with gr.Accordion(label="Text Size Range", open=False):
+ text_sizes = []
+ for i in size_range:
+ text_sizes.append(
+ gr.Textbox(
+ label=f"text_{i}",
+ )
+ )
+
+ spacing_size = gr.Dropdown(
+ [
+ size.name
+ for size in sizes
+ if size.name.startswith("spacing_")
+ ],
+ label="Spacing Size",
+ )
+ with gr.Accordion(label="Spacing Size Range", open=False):
+ spacing_sizes = []
+ for i in size_range:
+ spacing_sizes.append(
+ gr.Textbox(
+ label=f"spacing_{i}",
+ )
+ )
+
+ radius_size = gr.Dropdown(
+ [
+ size.name
+ for size in sizes
+ if size.name.startswith("radius_")
+ ],
+ label="Radius Size",
+ )
+ with gr.Accordion(label="Radius Size Range", open=False):
+ radius_sizes = []
+ for i in size_range:
+ radius_sizes.append(
+ gr.Textbox(
+ label=f"radius_{i}",
+ )
+ )
+
+ with gr.TabItem("Core Fonts"):
+ gr.Markdown(
+ """Set the main `font` and the monospace `font_mono` here.
+ Set up to 4 values for each (fallbacks in case a font is not available).
+ Check "Google Font" if font should be loaded from Google Fonts.
+ """
+ )
+ gr.Markdown("### Main Font")
+ main_fonts, main_is_google = [], []
+ for i in range(4):
+ with gr.Row():
+ font = gr.Textbox(label=f"Font {i + 1}")
+ font_is_google = gr.Checkbox(label="Google Font")
+ main_fonts.append(font)
+ main_is_google.append(font_is_google)
+
+ mono_fonts, mono_is_google = [], []
+ gr.Markdown("### Monospace Font")
+ for i in range(4):
+ with gr.Row():
+ font = gr.Textbox(label=f"Font {i + 1}")
+ font_is_google = gr.Checkbox(label="Google Font")
+ mono_fonts.append(font)
+ mono_is_google.append(font_is_google)
+
+ theme_var_input = []
+
+ core_color_suggestions = (
+ [f"*primary_{i}" for i in palette_range]
+ + [f"*secondary_{i}" for i in palette_range]
+ + [f"*neutral_{i}" for i in palette_range]
+ )
+
+ variable_suggestions = {
+ "fill": core_color_suggestions[:],
+ "color": core_color_suggestions[:],
+ "text_size": [f"*text_{i}" for i in size_range],
+ "radius": [f"*radius_{i}" for i in size_range],
+ "padding": [f"*spacing_{i}" for i in size_range],
+ "gap": [f"*spacing_{i}" for i in size_range],
+ "weight": [
+ "100",
+ "200",
+ "300",
+ "400",
+ "500",
+ "600",
+ "700",
+ "800",
+ ],
+ "shadow": ["none"],
+ "border_width": [],
+ }
+ for variable in flat_variables:
+ if variable.endswith("_dark"):
+ continue
+ for style_type in variable_suggestions:
+ if style_type in variable:
+ variable_suggestions[style_type].append("*" + variable)
+ break
+
+ variable_suggestions["fill"], variable_suggestions["color"] = (
+ variable_suggestions["fill"]
+ + variable_suggestions["color"][len(core_color_suggestions) :],
+ variable_suggestions["color"]
+ + variable_suggestions["fill"][len(core_color_suggestions) :],
+ )
+
+ for group, desc, variables in variable_groups:
+ with gr.TabItem(group):
+ gr.Markdown(
+ desc
+ + "\nYou can set these to one of the dropdown values, or clear the dropdown to set a custom value."
+ )
+ for variable in variables:
+ suggestions = []
+ for style_type in variable_suggestions:
+ if style_type in variable:
+ suggestions = variable_suggestions[style_type][:]
+ if "*" + variable in suggestions:
+ suggestions.remove("*" + variable)
+ break
+ dropdown = gr.Dropdown(
+ label=variable,
+ info=get_docstr(variable),
+ choices=suggestions,
+ allow_custom_value=True,
+ )
+ theme_var_input.append(dropdown)
+
+ # App
+
+ with gr.Column(scale=6, elem_id="app"):
+ with gr.Column(variant="panel"):
+ gr.Markdown(
+ """
+ # Theme Builder
+ Welcome to the theme builder. The left panel is where you create the theme. The different aspects of the theme are broken down into different tabs. Here's how to navigate them:
+ 1. First, set the "Source Theme". This will set the default values that you can override.
+ 2. Set the "Core Colors", "Core Sizing" and "Core Fonts". These are the core variables that are used to build the rest of the theme.
+ 3. The rest of the tabs set specific CSS theme variables. These control finer aspects of the UI. Within these theme variables, you can reference the core variables and other theme variables using the variable name preceded by an asterisk, e.g. `*primary_50` or `*body_text_color`. Clear the dropdown to set a custom value.
+ 4. Once you have finished your theme, click on "View Code" below to see how you can integrate the theme into your app. You can also click on "Upload to Hub" to upload your theme to the Hugging Face Hub, where others can download and use your theme.
+ """
+ )
+ with gr.Accordion("View Code", open=False):
+ output_code = gr.Code(language="python")
+ with gr.Accordion("Upload to Hub", open=False):
+ gr.Markdown(
+ "You can save your theme on the Hugging Face Hub. HF API write token can be found [here](https://huggingface.co/settings/tokens)."
+ )
+ with gr.Row():
+ theme_name = gr.Textbox(label="Theme Name")
+ theme_hf_token = gr.Textbox(label="Hugging Face Write Token")
+ theme_version = gr.Textbox(
+ label="Version",
+ placeholder="Leave blank to automatically update version.",
+ )
+ upload_to_hub_btn = gr.Button("Upload to Hub")
+ theme_upload_status = gr.Markdown(visible=False)
+
+ gr.Markdown("Below this panel is a dummy app to demo your theme.")
+
+ name = gr.Textbox(
+ label="Name",
+ info="Full name, including middle name. No special characters.",
+ placeholder="John Doe",
+ value="John Doe",
+ interactive=True,
+ )
+
+ with gr.Row():
+ slider1 = gr.Slider(label="Slider 1")
+ slider2 = gr.Slider(label="Slider 2")
+ gr.CheckboxGroup(["A", "B", "C"], label="Checkbox Group")
+
+ with gr.Row():
+ with gr.Column(variant="panel", scale=1):
+ gr.Markdown("## Panel 1")
+ radio = gr.Radio(
+ ["A", "B", "C"],
+ label="Radio",
+ info="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
+ )
+ drop = gr.Dropdown(
+ ["Option 1", "Option 2", "Option 3"], show_label=False
+ )
+ drop_2 = gr.Dropdown(
+ ["Option A", "Option B", "Option C"],
+ multiselect=True,
+ value=["Option A"],
+ label="Dropdown",
+ interactive=True,
+ )
+ check = gr.Checkbox(label="Go")
+ with gr.Column(variant="panel", scale=2):
+ img = gr.Image(
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/header-image.jpg",
+ label="Image",
+ height=320,
+ )
+ with gr.Row():
+ go_btn = gr.Button("Go", variant="primary")
+ clear_btn = gr.Button("Clear", variant="secondary")
+
+ def go(*args):
+ time.sleep(3)
+ return "https://gradio-static-files.s3.us-west-2.amazonaws.com/header-image.jpg"
+
+ go_btn.click(
+ go,
+ [radio, drop, drop_2, check, name],
+ img,
+ show_api=False,
+ )
+
+ def clear():
+ time.sleep(0.2)
+ return None
+
+ clear_btn.click(clear, None, img)
+
+ with gr.Row():
+ btn1 = gr.Button("Button 1", size="sm")
+ btn2 = gr.UploadButton(size="sm")
+ stop_btn = gr.Button("Stop", variant="stop", size="sm")
+
+ gr.Examples(
+ examples=[
+ [
+ "A",
+ "Option 1",
+ ["Option B"],
+ True,
+ ],
+ [
+ "B",
+ "Option 2",
+ ["Option B", "Option C"],
+ False,
+ ],
+ ],
+ inputs=[radio, drop, drop_2, check],
+ label="Examples",
+ )
+
+ with gr.Row():
+ gr.Dataframe(value=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], label="Dataframe")
+ gr.JSON(
+ value={"a": 1, "b": 2, "c": {"test": "a", "test2": [1, 2, 3]}},
+ label="JSON",
+ )
+ gr.Label(value={"cat": 0.7, "dog": 0.2, "fish": 0.1})
+ gr.File()
+ with gr.Row():
+ gr.ColorPicker()
+ gr.Video(
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/world.mp4"
+ )
+ gr.Gallery(
+ [
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/lion.jpg",
+ "lion",
+ ),
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/logo.png",
+ "logo",
+ ),
+ (
+ "https://gradio-static-files.s3.us-west-2.amazonaws.com/tower.jpg",
+ "tower",
+ ),
+ ],
+ height="200px",
+ columns=2,
+ )
+
+ with gr.Row():
+ with gr.Column(scale=2):
+ chatbot = gr.Chatbot([("Hello", "Hi")], label="Chatbot")
+ chat_btn = gr.Button("Add messages")
+
+ def chat(history):
+ time.sleep(2)
+ yield [["How are you?", "I am good."]]
+
+ chat_btn.click(
+ lambda history: history
+ + [["How are you?", "I am good."]]
+ + (time.sleep(2) or []),
+ chatbot,
+ chatbot,
+ show_api=False,
+ )
+ with gr.Column(scale=1):
+ with gr.Accordion("Advanced Settings"):
+ gr.Markdown("Hello")
+ gr.Number(label="Chatbot control 1")
+ gr.Number(label="Chatbot control 2")
+ gr.Number(label="Chatbot control 3")
+
+ # Event Listeners
+
+ secret_css = gr.Textbox(visible=False)
+ secret_font = gr.JSON(visible=False)
+
+ demo.load( # doing this via python was not working for some reason, so using this hacky method for now
+ None,
+ None,
+ None,
+ js="""() => {
+ document.head.innerHTML += "";
+ let evt_listener = window.setTimeout(
+ () => {
+ load_theme_btn = document.querySelector('#load_theme');
+ if (load_theme_btn) {
+ load_theme_btn.click();
+ window.clearTimeout(evt_listener);
+ }
+ },
+ 100
+ );
+ }""",
+ show_api=False,
+ )
+
+ theme_inputs = (
+ [primary_hue, secondary_hue, neutral_hue]
+ + primary_hues
+ + secondary_hues
+ + neutral_hues
+ + [text_size, spacing_size, radius_size]
+ + text_sizes
+ + spacing_sizes
+ + radius_sizes
+ + main_fonts
+ + main_is_google
+ + mono_fonts
+ + mono_is_google
+ + theme_var_input
+ )
+
+ def load_theme(theme_name):
+ theme = [theme for theme in themes if theme.__name__ == theme_name][0]
+
+ parameters = inspect.signature(theme.__init__).parameters
+ primary_hue = parameters["primary_hue"].default
+ secondary_hue = parameters["secondary_hue"].default
+ neutral_hue = parameters["neutral_hue"].default
+ text_size = parameters["text_size"].default
+ spacing_size = parameters["spacing_size"].default
+ radius_size = parameters["radius_size"].default
+
+ theme = theme()
+
+ font = theme._font[:4]
+ font_mono = theme._font_mono[:4]
+ font_is_google = [isinstance(f, gr.themes.GoogleFont) for f in font]
+ font_mono_is_google = [
+ isinstance(f, gr.themes.GoogleFont) for f in font_mono
+ ]
+
+ def pad_to_4(x):
+ return x + [None] * (4 - len(x))
+
+ var_output = []
+ for variable in flat_variables:
+ theme_val = getattr(theme, variable)
+ if theme_val is None and variable.endswith("_dark"):
+ theme_val = getattr(theme, variable[:-5])
+ var_output.append(theme_val)
+
+ return (
+ [primary_hue.name, secondary_hue.name, neutral_hue.name]
+ + primary_hue.expand()
+ + secondary_hue.expand()
+ + neutral_hue.expand()
+ + [text_size.name, spacing_size.name, radius_size.name]
+ + text_size.expand()
+ + spacing_size.expand()
+ + radius_size.expand()
+ + pad_to_4([f.name for f in font])
+ + pad_to_4(font_is_google)
+ + pad_to_4([f.name for f in font_mono])
+ + pad_to_4(font_mono_is_google)
+ + var_output
+ )
+
+ def generate_theme_code(
+ base_theme, final_theme, core_variables, final_main_fonts, final_mono_fonts
+ ):
+ base_theme_name = base_theme
+ base_theme = [theme for theme in themes if theme.__name__ == base_theme][
+ 0
+ ]()
+
+ parameters = inspect.signature(base_theme.__init__).parameters
+ primary_hue = parameters["primary_hue"].default
+ secondary_hue = parameters["secondary_hue"].default
+ neutral_hue = parameters["neutral_hue"].default
+ text_size = parameters["text_size"].default
+ spacing_size = parameters["spacing_size"].default
+ radius_size = parameters["radius_size"].default
+ font = parameters["font"].default
+ font = [font] if not isinstance(font, Iterable) else font
+ font = [
+ gr.themes.Font(f) if not isinstance(f, gr.themes.Font) else f
+ for f in font
+ ]
+ font_mono = parameters["font_mono"].default
+ font_mono = (
+ [font_mono] if not isinstance(font_mono, Iterable) else font_mono
+ )
+ font_mono = [
+ gr.themes.Font(f) if not isinstance(f, gr.themes.Font) else f
+ for f in font_mono
+ ]
+
+ core_diffs = {}
+ specific_core_diffs = {}
+ core_var_names = [
+ "primary_hue",
+ "secondary_hue",
+ "neutral_hue",
+ "text_size",
+ "spacing_size",
+ "radius_size",
+ ]
+ for value_name, base_value, source_class, final_value in zip(
+ core_var_names,
+ [
+ primary_hue,
+ secondary_hue,
+ neutral_hue,
+ text_size,
+ spacing_size,
+ radius_size,
+ ],
+ [
+ gr.themes.Color,
+ gr.themes.Color,
+ gr.themes.Color,
+ gr.themes.Size,
+ gr.themes.Size,
+ gr.themes.Size,
+ ],
+ core_variables,
+ ):
+ if base_value.name != final_value:
+ core_diffs[value_name] = final_value
+ source_obj = [
+ obj for obj in source_class.all if obj.name == final_value
+ ][0]
+ final_attr_values = {}
+ diff = False
+ for attr in dir(source_obj):
+ if attr in ["all", "name", "expand"] or attr.startswith("_"):
+ continue
+ final_theme_attr = (
+ value_name.split("_")[0]
+ + "_"
+ + (attr[1:] if source_class == gr.themes.Color else attr)
+ )
+ final_attr_values[final_theme_attr] = getattr(
+ final_theme, final_theme_attr
+ )
+ if getattr(source_obj, attr) != final_attr_values[final_theme_attr]:
+ diff = True
+ if diff:
+ specific_core_diffs[value_name] = (source_class, final_attr_values)
+
+ font_diffs = {}
+
+ final_main_fonts = [font for font in final_main_fonts if font[0]]
+ final_mono_fonts = [font for font in final_mono_fonts if font[0]]
+ font = font[:4]
+ font_mono = font_mono[:4]
+ for base_font_set, theme_font_set, font_set_name in [
+ (font, final_main_fonts, "font"),
+ (font_mono, final_mono_fonts, "font_mono"),
+ ]:
+ if len(base_font_set) != len(theme_font_set) or any(
+ base_font.name != theme_font[0]
+ or isinstance(base_font, gr.themes.GoogleFont) != theme_font[1]
+ for base_font, theme_font in zip(base_font_set, theme_font_set)
+ ):
+ font_diffs[font_set_name] = [
+ f"gr.themes.GoogleFont('{font_name}')"
+ if is_google_font
+ else f"'{font_name}'"
+ for font_name, is_google_font in theme_font_set
+ ]
+
+ newline = "\n"
+
+ core_diffs_code = ""
+ if len(core_diffs) + len(specific_core_diffs) > 0:
+ for var_name in core_var_names:
+ if var_name in specific_core_diffs:
+ cls, vals = specific_core_diffs[var_name]
+ core_diffs_code += f""" {var_name}=gr.themes.{cls.__name__}({', '.join(f'''{k}="{v}"''' for k, v in vals.items())}),\n"""
+ elif var_name in core_diffs:
+ core_diffs_code += (
+ f""" {var_name}="{core_diffs[var_name]}",\n"""
+ )
+
+ font_diffs_code = ""
+
+ if len(font_diffs) > 0:
+ font_diffs_code = "".join(
+ [
+ f""" {font_set_name}=[{", ".join(fonts)}],\n"""
+ for font_set_name, fonts in font_diffs.items()
+ ]
+ )
+ var_diffs = {}
+ for variable in flat_variables:
+ base_theme_val = getattr(base_theme, variable)
+ final_theme_val = getattr(final_theme, variable)
+ if base_theme_val is None and variable.endswith("_dark"):
+ base_theme_val = getattr(base_theme, variable[:-5])
+ if base_theme_val != final_theme_val:
+ var_diffs[variable] = getattr(final_theme, variable)
+
+ newline = "\n"
+
+ vars_diff_code = ""
+ if len(var_diffs) > 0:
+ vars_diff_code = f""".set(
+ {(',' + newline + " ").join([f"{k}='{v}'" for k, v in var_diffs.items()])}
+)"""
+
+ output = f"""
+import gradio as gr
+
+theme = gr.themes.{base_theme_name}({newline if core_diffs_code or font_diffs_code else ""}{core_diffs_code}{font_diffs_code}){vars_diff_code}
+
+with gr.Blocks(theme=theme) as demo:
+ ..."""
+ return output
+
+ history = gr.State([])
+ current_theme = gr.State(None)
+
+ def render_variables(history, base_theme, *args):
+ primary_hue, secondary_hue, neutral_hue = args[0:3]
+ primary_hues = args[3 : 3 + len(palette_range)]
+ secondary_hues = args[3 + len(palette_range) : 3 + 2 * len(palette_range)]
+ neutral_hues = args[3 + 2 * len(palette_range) : 3 + 3 * len(palette_range)]
+ text_size, spacing_size, radius_size = args[
+ 3 + 3 * len(palette_range) : 6 + 3 * len(palette_range)
+ ]
+ text_sizes = args[
+ 6 + 3 * len(palette_range) : 6
+ + 3 * len(palette_range)
+ + len(size_range)
+ ]
+ spacing_sizes = args[
+ 6 + 3 * len(palette_range) + len(size_range) : 6
+ + 3 * len(palette_range)
+ + 2 * len(size_range)
+ ]
+ radius_sizes = args[
+ 6 + 3 * len(palette_range) + 2 * len(size_range) : 6
+ + 3 * len(palette_range)
+ + 3 * len(size_range)
+ ]
+ main_fonts = args[
+ 6 + 3 * len(palette_range) + 3 * len(size_range) : 6
+ + 3 * len(palette_range)
+ + 3 * len(size_range)
+ + 4
+ ]
+ main_is_google = args[
+ 6 + 3 * len(palette_range) + 3 * len(size_range) + 4 : 6
+ + 3 * len(palette_range)
+ + 3 * len(size_range)
+ + 8
+ ]
+ mono_fonts = args[
+ 6 + 3 * len(palette_range) + 3 * len(size_range) + 8 : 6
+ + 3 * len(palette_range)
+ + 3 * len(size_range)
+ + 12
+ ]
+ mono_is_google = args[
+ 6 + 3 * len(palette_range) + 3 * len(size_range) + 12 : 6
+ + 3 * len(palette_range)
+ + 3 * len(size_range)
+ + 16
+ ]
+ remaining_args = args[
+ 6 + 3 * len(palette_range) + 3 * len(size_range) + 16 :
+ ]
+
+ final_primary_color = gr.themes.Color(*primary_hues)
+ final_secondary_color = gr.themes.Color(*secondary_hues)
+ final_neutral_color = gr.themes.Color(*neutral_hues)
+ final_text_size = gr.themes.Size(*text_sizes)
+ final_spacing_size = gr.themes.Size(*spacing_sizes)
+ final_radius_size = gr.themes.Size(*radius_sizes)
+
+ final_main_fonts = []
+ font_weights = set()
+ for attr, val in zip(flat_variables, remaining_args):
+ if "weight" in attr:
+ font_weights.add(val)
+ font_weights = sorted(font_weights)
+
+ for main_font, is_google in zip(main_fonts, main_is_google):
+ if not main_font:
+ continue
+ if is_google:
+ main_font = gr.themes.GoogleFont(main_font, weights=font_weights)
+ final_main_fonts.append(main_font)
+ final_mono_fonts = []
+ for mono_font, is_google in zip(mono_fonts, mono_is_google):
+ if not mono_font:
+ continue
+ if is_google:
+ mono_font = gr.themes.GoogleFont(mono_font, weights=font_weights)
+ final_mono_fonts.append(mono_font)
+
+ theme = gr.themes.Base(
+ primary_hue=final_primary_color,
+ secondary_hue=final_secondary_color,
+ neutral_hue=final_neutral_color,
+ text_size=final_text_size,
+ spacing_size=final_spacing_size,
+ radius_size=final_radius_size,
+ font=final_main_fonts,
+ font_mono=final_mono_fonts,
+ )
+
+ theme.set(**dict(zip(flat_variables, remaining_args)))
+ new_step = (base_theme, args)
+ if len(history) == 0 or str(history[-1]) != str(new_step):
+ history.append(new_step)
+
+ return (
+ history,
+ theme._get_theme_css(),
+ theme._stylesheets,
+ generate_theme_code(
+ base_theme,
+ theme,
+ (
+ primary_hue,
+ secondary_hue,
+ neutral_hue,
+ text_size,
+ spacing_size,
+ radius_size,
+ ),
+ list(zip(main_fonts, main_is_google)),
+ list(zip(mono_fonts, mono_is_google)),
+ ),
+ theme,
+ )
+
+ def attach_rerender(evt_listener):
+ return evt_listener(
+ render_variables,
+ [history, base_theme_dropdown] + theme_inputs,
+ [history, secret_css, secret_font, output_code, current_theme],
+ show_api=False,
+ ).then(
+ None,
+ [secret_css, secret_font],
+ None,
+ js="""(css, fonts) => {
+ document.getElementById('theme_css').innerHTML = css;
+ let existing_font_links = document.querySelectorAll('link[rel="stylesheet"][href^="https://fonts.googleapis.com/css"]');
+ existing_font_links.forEach(link => {
+ if (fonts.includes(link.href)) {
+ fonts = fonts.filter(font => font != link.href);
+ } else {
+ link.remove();
+ }
+ });
+ fonts.forEach(font => {
+ let link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = font;
+ document.head.appendChild(link);
+ });
+ }""",
+ show_api=False,
+ )
+
+ def load_color(color_name):
+ color = [color for color in colors if color.name == color_name][0]
+ return [getattr(color, f"c{i}") for i in palette_range]
+
+ attach_rerender(
+ primary_hue.select(
+ load_color, primary_hue, primary_hues, show_api=False
+ ).then
+ )
+ attach_rerender(
+ secondary_hue.select(
+ load_color, secondary_hue, secondary_hues, show_api=False
+ ).then
+ )
+ attach_rerender(
+ neutral_hue.select(
+ load_color, neutral_hue, neutral_hues, show_api=False
+ ).then
+ )
+ for hue_set in (primary_hues, secondary_hues, neutral_hues):
+ for hue in hue_set:
+ attach_rerender(hue.blur)
+
+ def load_size(size_name):
+ size = [size for size in sizes if size.name == size_name][0]
+ return [getattr(size, i) for i in size_range]
+
+ attach_rerender(
+ text_size.change(load_size, text_size, text_sizes, show_api=False).then
+ )
+ attach_rerender(
+ spacing_size.change(
+ load_size, spacing_size, spacing_sizes, show_api=False
+ ).then
+ )
+ attach_rerender(
+ radius_size.change(
+ load_size, radius_size, radius_sizes, show_api=False
+ ).then
+ )
+
+ attach_rerender(
+ load_theme_btn.click(
+ load_theme, base_theme_dropdown, theme_inputs, show_api=False
+ ).then
+ )
+
+ for theme_box in (
+ text_sizes + spacing_sizes + radius_sizes + main_fonts + mono_fonts
+ ):
+ attach_rerender(theme_box.blur)
+ attach_rerender(theme_box.submit)
+ for theme_box in theme_var_input:
+ attach_rerender(theme_box.blur)
+ attach_rerender(theme_box.select)
+ for checkbox in main_is_google + mono_is_google:
+ attach_rerender(checkbox.select)
+
+ dark_mode_btn.click(
+ None,
+ None,
+ None,
+ js="""() => {
+ if (document.querySelectorAll('.dark').length) {
+ document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark'));
+ } else {
+ document.querySelector('body').classList.add('dark');
+ }
+ }""",
+ show_api=False,
+ )
+
+ def undo(history_var):
+ if len(history_var) <= 1:
+ return {history: gr.skip()}
+ else:
+ history_var.pop()
+ old = history_var.pop()
+ return [history_var, old[0]] + list(old[1])
+
+ attach_rerender(
+ undo_btn.click(
+ undo,
+ [history],
+ [history, base_theme_dropdown] + theme_inputs,
+ show_api=False,
+ ).then
+ )
+
+ def upload_to_hub(data):
+ try:
+ theme_url = data[current_theme].push_to_hub(
+ repo_name=data[theme_name],
+ version=data[theme_version] or None,
+ hf_token=data[theme_hf_token],
+ theme_name=data[theme_name],
+ )
+ space_name = "/".join(theme_url.split("/")[-2:])
+ return (
+ gr.Markdown(
+ value=f"Theme uploaded [here!]({theme_url})! Load it as `gr.Blocks(theme='{space_name}')`",
+ visible=True,
+ ),
+ "Upload to Hub",
+ )
+ except Exception as e:
+ return (
+ gr.Markdown(
+ value=f"Error: {e}",
+ visible=True,
+ ),
+ "Upload to Hub",
+ )
+
+ upload_to_hub_btn.click(
+ lambda: "Uploading...",
+ None,
+ upload_to_hub_btn,
+ show_api=False,
+ ).then(
+ upload_to_hub,
+ {
+ current_theme,
+ theme_name,
+ theme_hf_token,
+ theme_version,
+ },
+ [theme_upload_status, upload_to_hub_btn],
+ show_api=False,
+ )
+
+
+if __name__ == "__main__":
+ demo.launch()
diff --git a/gradio/themes/default.py b/gradio/themes/default.py
new file mode 100644
index 0000000000000000000000000000000000000000..8f5dd2d5a1954481171aac922008c13f1634640c
--- /dev/null
+++ b/gradio/themes/default.py
@@ -0,0 +1,92 @@
+from __future__ import annotations
+
+from typing import Iterable
+
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+
+
+class Default(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.orange,
+ secondary_hue: colors.Color | str = colors.blue,
+ neutral_hue: colors.Color | str = colors.gray,
+ spacing_size: sizes.Size | str = sizes.spacing_md,
+ radius_size: sizes.Size | str = sizes.radius_md,
+ text_size: sizes.Size | str = sizes.text_md,
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Source Sans Pro"),
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "Consolas",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+ self.name = "default"
+ super().set(
+ # Colors
+ input_background_fill_dark="*neutral_800",
+ error_background_fill=colors.red.c50,
+ error_background_fill_dark="*neutral_900",
+ error_border_color=colors.red.c700,
+ error_border_color_dark=colors.red.c500,
+ error_icon_color=colors.red.c700,
+ error_icon_color_dark=colors.red.c500,
+ # Transition
+ button_transition="none",
+ # Shadows
+ button_shadow="*shadow_drop",
+ button_shadow_hover="*shadow_drop_lg",
+ button_shadow_active="*shadow_inset",
+ input_shadow="0 0 0 *shadow_spread transparent, *shadow_inset",
+ input_shadow_focus="0 0 0 *shadow_spread *secondary_50, *shadow_inset",
+ input_shadow_focus_dark="0 0 0 *shadow_spread *neutral_700, *shadow_inset",
+ checkbox_label_shadow="*shadow_drop",
+ block_shadow="*shadow_drop",
+ form_gap_width="1px",
+ # Button borders
+ input_border_width="1px",
+ input_background_fill="white",
+ # Gradients
+ stat_background_fill="linear-gradient(to right, *primary_400, *primary_200)",
+ stat_background_fill_dark="linear-gradient(to right, *primary_400, *primary_600)",
+ checkbox_label_background_fill="linear-gradient(to top, *neutral_50, white)",
+ checkbox_label_background_fill_dark="linear-gradient(to top, *neutral_900, *neutral_800)",
+ checkbox_label_background_fill_hover="linear-gradient(to top, *neutral_100, white)",
+ checkbox_label_background_fill_hover_dark="linear-gradient(to top, *neutral_900, *neutral_800)",
+ button_primary_background_fill="linear-gradient(to bottom right, *primary_100, *primary_300)",
+ button_primary_background_fill_dark="linear-gradient(to bottom right, *primary_500, *primary_600)",
+ button_primary_background_fill_hover="linear-gradient(to bottom right, *primary_100, *primary_200)",
+ button_primary_background_fill_hover_dark="linear-gradient(to bottom right, *primary_500, *primary_500)",
+ button_primary_border_color_dark="*primary_500",
+ button_secondary_background_fill="linear-gradient(to bottom right, *neutral_100, *neutral_200)",
+ button_secondary_background_fill_dark="linear-gradient(to bottom right, *neutral_600, *neutral_700)",
+ button_secondary_background_fill_hover="linear-gradient(to bottom right, *neutral_100, *neutral_100)",
+ button_secondary_background_fill_hover_dark="linear-gradient(to bottom right, *neutral_600, *neutral_600)",
+ button_cancel_background_fill=f"linear-gradient(to bottom right, {colors.red.c100}, {colors.red.c200})",
+ button_cancel_background_fill_dark=f"linear-gradient(to bottom right, {colors.red.c600}, {colors.red.c700})",
+ button_cancel_background_fill_hover=f"linear-gradient(to bottom right, {colors.red.c100}, {colors.red.c100})",
+ button_cancel_background_fill_hover_dark=f"linear-gradient(to bottom right, {colors.red.c600}, {colors.red.c600})",
+ button_cancel_border_color=colors.red.c200,
+ button_cancel_border_color_dark=colors.red.c600,
+ button_cancel_text_color=colors.red.c600,
+ button_cancel_text_color_dark="white",
+ border_color_accent_subdued="*primary_200",
+ )
diff --git a/gradio/themes/glass.py b/gradio/themes/glass.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec43ac696645b3419bddf315f3e3f03d7ca93476
--- /dev/null
+++ b/gradio/themes/glass.py
@@ -0,0 +1,95 @@
+from __future__ import annotations
+
+from typing import Iterable
+
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+
+
+class Glass(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.stone,
+ secondary_hue: colors.Color | str = colors.stone,
+ neutral_hue: colors.Color | str = colors.stone,
+ spacing_size: sizes.Size | str = sizes.spacing_sm,
+ radius_size: sizes.Size | str = sizes.radius_sm,
+ text_size: sizes.Size | str = sizes.text_sm,
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
+ "Optima",
+ "Candara",
+ "Noto Sans",
+ "source-sans-pro",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "Consolas",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+ self.name = "glass"
+ super().set(
+ body_background_fill_dark="*primary_800",
+ background_fill_secondary_dark="*primary_800",
+ block_background_fill_dark="*primary_800",
+ button_primary_background_fill="linear-gradient(180deg, *primary_50 0%, *primary_200 50%, *primary_300 50%, *primary_200 100%)",
+ button_primary_background_fill_hover="linear-gradient(180deg, *primary_100 0%, *primary_200 50%, *primary_300 50%, *primary_200 100%)",
+ button_primary_background_fill_dark="linear-gradient(180deg, *primary_400 0%, *primary_500 50%, *primary_600 50%, *primary_500 100%)",
+ button_primary_background_fill_hover_dark="linear-gradient(180deg, *primary_400 0%, *primary_500 50%, *primary_600 50%, *primary_500 100%)",
+ button_secondary_background_fill="*button_primary_background_fill",
+ button_secondary_background_fill_hover="*button_primary_background_fill_hover",
+ button_secondary_background_fill_dark="*button_primary_background_fill",
+ button_secondary_background_fill_hover_dark="*button_primary_background_fill_hover",
+ button_cancel_background_fill="*button_primary_background_fill",
+ button_cancel_background_fill_hover="*button_primary_background_fill_hover",
+ button_cancel_background_fill_dark="*button_primary_background_fill",
+ button_cancel_background_fill_hover_dark="*button_primary_background_fill_hover",
+ button_cancel_border_color="*button_secondary_border_color",
+ button_cancel_border_color_dark="*button_secondary_border_color",
+ button_cancel_text_color="*button_secondary_text_color",
+ checkbox_border_width="0px",
+ checkbox_label_background_fill="*button_secondary_background_fill",
+ checkbox_label_background_fill_dark="*button_secondary_background_fill",
+ checkbox_label_background_fill_hover="*button_secondary_background_fill_hover",
+ checkbox_label_background_fill_hover_dark="*button_secondary_background_fill_hover",
+ checkbox_label_border_width="1px",
+ checkbox_background_color_dark="*primary_600",
+ button_border_width="1px",
+ button_shadow_active="*shadow_inset",
+ input_background_fill="linear-gradient(0deg, *secondary_50 0%, white 100%)",
+ input_background_fill_dark="*secondary_600",
+ input_border_color_focus_dark="*primary_400",
+ input_border_width="1px",
+ slider_color="*primary_400",
+ block_label_text_color="*primary_500",
+ block_title_text_color="*primary_500",
+ block_label_text_weight="600",
+ block_title_text_weight="600",
+ block_label_text_size="*text_md",
+ block_title_text_size="*text_md",
+ block_label_background_fill="*primary_200",
+ block_label_background_fill_dark="*primary_700",
+ block_border_width="0px",
+ block_border_width_dark="1px",
+ panel_border_width="1px",
+ border_color_primary_dark="*primary_500",
+ background_fill_primary_dark="*neutral_700",
+ background_fill_secondary="*primary_100",
+ block_background_fill="*primary_50",
+ block_shadow="*primary_400 0px 0px 3px 0px",
+ table_even_background_fill_dark="*neutral_700",
+ table_odd_background_fill_dark="*neutral_700",
+ )
diff --git a/gradio/themes/monochrome.py b/gradio/themes/monochrome.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f39ce4935888d0ef4f2ac570bbb861f0dab571e
--- /dev/null
+++ b/gradio/themes/monochrome.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import Iterable
+
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+
+
+class Monochrome(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.neutral,
+ secondary_hue: colors.Color | str = colors.neutral,
+ neutral_hue: colors.Color | str = colors.neutral,
+ spacing_size: sizes.Size | str = sizes.spacing_lg,
+ radius_size: sizes.Size | str = sizes.radius_none,
+ text_size: sizes.Size | str = sizes.text_md,
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Quicksand"),
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "Consolas",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+ self.name = "monochrome"
+ super().set(
+ # Colors
+ slider_color="*neutral_900",
+ slider_color_dark="*neutral_500",
+ body_text_color="*neutral_900",
+ block_label_text_color="*body_text_color",
+ block_title_text_color="*body_text_color",
+ body_text_color_subdued="*neutral_700",
+ background_fill_primary_dark="*neutral_900",
+ background_fill_secondary_dark="*neutral_800",
+ block_background_fill_dark="*neutral_800",
+ input_background_fill_dark="*neutral_700",
+ # Button Colors
+ button_primary_background_fill="*neutral_900",
+ button_primary_background_fill_hover="*neutral_700",
+ button_primary_text_color="white",
+ button_primary_background_fill_dark="*neutral_600",
+ button_primary_background_fill_hover_dark="*neutral_600",
+ button_primary_text_color_dark="white",
+ button_secondary_background_fill="*button_primary_background_fill",
+ button_secondary_background_fill_hover="*button_primary_background_fill_hover",
+ button_secondary_text_color="*button_primary_text_color",
+ button_cancel_background_fill="*button_primary_background_fill",
+ button_cancel_background_fill_hover="*button_primary_background_fill_hover",
+ button_cancel_text_color="*button_primary_text_color",
+ checkbox_label_background_fill="*button_primary_background_fill",
+ checkbox_label_background_fill_hover="*button_primary_background_fill_hover",
+ checkbox_label_text_color="*button_primary_text_color",
+ checkbox_background_color_selected="*neutral_600",
+ checkbox_background_color_dark="*neutral_700",
+ checkbox_background_color_selected_dark="*neutral_700",
+ checkbox_border_color_selected_dark="*neutral_800",
+ # Padding
+ checkbox_label_padding="*spacing_md",
+ button_large_padding="*spacing_lg",
+ button_small_padding="*spacing_sm",
+ # Borders
+ block_border_width="0px",
+ block_border_width_dark="1px",
+ shadow_drop_lg="0 1px 4px 0 rgb(0 0 0 / 0.1)",
+ block_shadow="*shadow_drop_lg",
+ block_shadow_dark="none",
+ # Block Labels
+ block_title_text_weight="600",
+ block_label_text_weight="600",
+ block_label_text_size="*text_md",
+ )
diff --git a/gradio/themes/soft.py b/gradio/themes/soft.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d9e30e57bb5b6a77b59ecfb7c862059369a1748
--- /dev/null
+++ b/gradio/themes/soft.py
@@ -0,0 +1,107 @@
+from __future__ import annotations
+
+from typing import Iterable
+
+from gradio.themes.base import Base
+from gradio.themes.utils import colors, fonts, sizes
+
+
+class Soft(Base):
+ def __init__(
+ self,
+ *,
+ primary_hue: colors.Color | str = colors.indigo,
+ secondary_hue: colors.Color | str = colors.indigo,
+ neutral_hue: colors.Color | str = colors.gray,
+ spacing_size: sizes.Size | str = sizes.spacing_md,
+ radius_size: sizes.Size | str = sizes.radius_md,
+ text_size: sizes.Size | str = sizes.text_md,
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("Montserrat"),
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ ),
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
+ fonts.GoogleFont("IBM Plex Mono"),
+ "ui-monospace",
+ "Consolas",
+ "monospace",
+ ),
+ ):
+ super().__init__(
+ primary_hue=primary_hue,
+ secondary_hue=secondary_hue,
+ neutral_hue=neutral_hue,
+ spacing_size=spacing_size,
+ radius_size=radius_size,
+ text_size=text_size,
+ font=font,
+ font_mono=font_mono,
+ )
+ self.name = "soft"
+ super().set(
+ # Colors
+ background_fill_primary="*neutral_50",
+ slider_color="*primary_500",
+ slider_color_dark="*primary_600",
+ # Shadows
+ shadow_drop="0 1px 4px 0 rgb(0 0 0 / 0.1)",
+ shadow_drop_lg="0 2px 5px 0 rgb(0 0 0 / 0.1)",
+ # Block Labels
+ block_background_fill="white",
+ block_label_padding="*spacing_sm *spacing_md",
+ block_label_background_fill="*primary_100",
+ block_label_background_fill_dark="*primary_600",
+ block_label_radius="*radius_md",
+ block_label_text_size="*text_md",
+ block_label_text_weight="600",
+ block_label_text_color="*primary_500",
+ block_label_text_color_dark="white",
+ block_title_radius="*block_label_radius",
+ block_title_padding="*block_label_padding",
+ block_title_background_fill="*block_label_background_fill",
+ block_title_text_weight="600",
+ block_title_text_color="*primary_500",
+ block_title_text_color_dark="white",
+ block_label_margin="*spacing_md",
+ # Inputs
+ input_background_fill="white",
+ input_border_color="*neutral_50",
+ input_shadow="*shadow_drop",
+ input_shadow_focus="*shadow_drop_lg",
+ checkbox_shadow="none",
+ # Buttons
+ shadow_spread="6px",
+ button_shadow="*shadow_drop_lg",
+ button_shadow_hover="*shadow_drop_lg",
+ checkbox_label_shadow="*shadow_drop_lg",
+ button_shadow_active="*shadow_inset",
+ button_primary_background_fill="*primary_500",
+ button_primary_background_fill_hover="*primary_400",
+ button_primary_background_fill_hover_dark="*primary_500",
+ button_primary_text_color="white",
+ button_secondary_background_fill="white",
+ button_secondary_background_fill_hover="*neutral_100",
+ button_secondary_background_fill_hover_dark="*primary_500",
+ button_secondary_text_color="*neutral_800",
+ button_cancel_background_fill="*button_secondary_background_fill",
+ button_cancel_background_fill_hover="*button_secondary_background_fill_hover",
+ button_cancel_background_fill_hover_dark="*button_secondary_background_fill_hover",
+ button_cancel_text_color="*button_secondary_text_color",
+ checkbox_label_background_fill_selected="*primary_500",
+ checkbox_label_background_fill_selected_dark="*primary_600",
+ checkbox_border_width="1px",
+ checkbox_border_color="*neutral_100",
+ checkbox_border_color_dark="*neutral_600",
+ checkbox_background_color_selected="*primary_600",
+ checkbox_background_color_selected_dark="*primary_700",
+ checkbox_border_color_focus="*primary_500",
+ checkbox_border_color_focus_dark="*primary_600",
+ checkbox_border_color_selected="*primary_600",
+ checkbox_border_color_selected_dark="*primary_700",
+ checkbox_label_text_color_selected="white",
+ # Borders
+ block_border_width="0px",
+ panel_border_width="1px",
+ )
diff --git a/gradio/themes/upload_theme.py b/gradio/themes/upload_theme.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee11e056d488579e818bc4814d6b13892e6b6e0b
--- /dev/null
+++ b/gradio/themes/upload_theme.py
@@ -0,0 +1,59 @@
+from __future__ import annotations
+
+import argparse
+
+from gradio.themes import ThemeClass
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Upload a demo to a space")
+ parser.add_argument("theme", type=str, help="Theme json file")
+ parser.add_argument("repo_name", type=str, help="HF repo name to store the theme")
+ parser.add_argument(
+ "--org_name",
+ type=str,
+ help="The name of the org to save the space in. If None (the default), the username corresponding to the logged in user, or hƒ_token is used.",
+ )
+ parser.add_argument("--version", type=str, help="Semver version")
+ parser.add_argument("--hf_token", type=str, help="HF Token")
+ parser.add_argument(
+ "--theme-name",
+ type=str,
+ help="Name of theme.",
+ )
+ parser.add_argument(
+ "--description",
+ type=str,
+ help="Description of theme",
+ )
+ args = parser.parse_args()
+ upload_theme(
+ args.theme,
+ args.repo_name,
+ args.org_name,
+ args.version,
+ args.hf_token,
+ args.theme_name,
+ args.description,
+ )
+
+
+def upload_theme(
+ theme: str,
+ repo_name: str,
+ org_name: str | None = None,
+ version: str | None = None,
+ hf_token: str | None = None,
+ theme_name: str | None = None,
+ description: str | None = None,
+):
+ theme = ThemeClass.load(theme)
+
+ return theme.push_to_hub(
+ repo_name=repo_name,
+ version=version,
+ hf_token=hf_token,
+ theme_name=theme_name,
+ description=description,
+ org_name=org_name,
+ )
diff --git a/gradio/themes/utils/__init__.py b/gradio/themes/utils/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3e6208634fafa416b9323f5156ac56dd7bb3700
--- /dev/null
+++ b/gradio/themes/utils/__init__.py
@@ -0,0 +1,11 @@
+from .semver_match import (
+ ThemeAsset,
+ get_matching_version,
+ get_theme_assets,
+)
+
+__all__ = [
+ "ThemeAsset",
+ "get_theme_assets",
+ "get_matching_version",
+]
diff --git a/gradio/themes/utils/colors.py b/gradio/themes/utils/colors.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b2d975bdd5245e1cd82bd172ee70a733924d0d8
--- /dev/null
+++ b/gradio/themes/utils/colors.py
@@ -0,0 +1,359 @@
+from __future__ import annotations
+
+
+class Color:
+ all = []
+
+ def __init__(
+ self,
+ c50: str,
+ c100: str,
+ c200: str,
+ c300: str,
+ c400: str,
+ c500: str,
+ c600: str,
+ c700: str,
+ c800: str,
+ c900: str,
+ c950: str,
+ name: str | None = None,
+ ):
+ self.c50 = c50
+ self.c100 = c100
+ self.c200 = c200
+ self.c300 = c300
+ self.c400 = c400
+ self.c500 = c500
+ self.c600 = c600
+ self.c700 = c700
+ self.c800 = c800
+ self.c900 = c900
+ self.c950 = c950
+ self.name = name
+ Color.all.append(self)
+
+ def expand(self) -> list[str]:
+ return [
+ self.c50,
+ self.c100,
+ self.c200,
+ self.c300,
+ self.c400,
+ self.c500,
+ self.c600,
+ self.c700,
+ self.c800,
+ self.c900,
+ self.c950,
+ ]
+
+
+slate = Color(
+ name="slate",
+ c50="#f8fafc",
+ c100="#f1f5f9",
+ c200="#e2e8f0",
+ c300="#cbd5e1",
+ c400="#94a3b8",
+ c500="#64748b",
+ c600="#475569",
+ c700="#334155",
+ c800="#1e293b",
+ c900="#0f172a",
+ c950="#0a0f1e",
+)
+gray = Color(
+ name="gray",
+ c50="#f9fafb",
+ c100="#f3f4f6",
+ c200="#e5e7eb",
+ c300="#d1d5db",
+ c400="#9ca3af",
+ c500="#6b7280",
+ c600="#4b5563",
+ c700="#374151",
+ c800="#1f2937",
+ c900="#111827",
+ c950="#0b0f19",
+)
+zinc = Color(
+ name="zinc",
+ c50="#fafafa",
+ c100="#f4f4f5",
+ c200="#e4e4e7",
+ c300="#d4d4d8",
+ c400="#a1a1aa",
+ c500="#71717a",
+ c600="#52525b",
+ c700="#3f3f46",
+ c800="#27272a",
+ c900="#18181b",
+ c950="#0f0f11",
+)
+neutral = Color(
+ name="neutral",
+ c50="#fafafa",
+ c100="#f5f5f5",
+ c200="#e5e5e5",
+ c300="#d4d4d4",
+ c400="#a3a3a3",
+ c500="#737373",
+ c600="#525252",
+ c700="#404040",
+ c800="#262626",
+ c900="#171717",
+ c950="#0f0f0f",
+)
+stone = Color(
+ name="stone",
+ c50="#fafaf9",
+ c100="#f5f5f4",
+ c200="#e7e5e4",
+ c300="#d6d3d1",
+ c400="#a8a29e",
+ c500="#78716c",
+ c600="#57534e",
+ c700="#44403c",
+ c800="#292524",
+ c900="#1c1917",
+ c950="#0f0e0d",
+)
+red = Color(
+ name="red",
+ c50="#fef2f2",
+ c100="#fee2e2",
+ c200="#fecaca",
+ c300="#fca5a5",
+ c400="#f87171",
+ c500="#ef4444",
+ c600="#dc2626",
+ c700="#b91c1c",
+ c800="#991b1b",
+ c900="#7f1d1d",
+ c950="#6c1e1e",
+)
+orange = Color(
+ name="orange",
+ c50="#fff7ed",
+ c100="#ffedd5",
+ c200="#fed7aa",
+ c300="#fdba74",
+ c400="#fb923c",
+ c500="#f97316",
+ c600="#ea580c",
+ c700="#c2410c",
+ c800="#9a3412",
+ c900="#7c2d12",
+ c950="#6c2e12",
+)
+amber = Color(
+ name="amber",
+ c50="#fffbeb",
+ c100="#fef3c7",
+ c200="#fde68a",
+ c300="#fcd34d",
+ c400="#fbbf24",
+ c500="#f59e0b",
+ c600="#d97706",
+ c700="#b45309",
+ c800="#92400e",
+ c900="#78350f",
+ c950="#6c370f",
+)
+yellow = Color(
+ name="yellow",
+ c50="#fefce8",
+ c100="#fef9c3",
+ c200="#fef08a",
+ c300="#fde047",
+ c400="#facc15",
+ c500="#eab308",
+ c600="#ca8a04",
+ c700="#a16207",
+ c800="#854d0e",
+ c900="#713f12",
+ c950="#653b12",
+)
+lime = Color(
+ name="lime",
+ c50="#f7fee7",
+ c100="#ecfccb",
+ c200="#d9f99d",
+ c300="#bef264",
+ c400="#a3e635",
+ c500="#84cc16",
+ c600="#65a30d",
+ c700="#4d7c0f",
+ c800="#3f6212",
+ c900="#365314",
+ c950="#2f4e14",
+)
+green = Color(
+ name="green",
+ c50="#f0fdf4",
+ c100="#dcfce7",
+ c200="#bbf7d0",
+ c300="#86efac",
+ c400="#4ade80",
+ c500="#22c55e",
+ c600="#16a34a",
+ c700="#15803d",
+ c800="#166534",
+ c900="#14532d",
+ c950="#134e28",
+)
+emerald = Color(
+ name="emerald",
+ c50="#ecfdf5",
+ c100="#d1fae5",
+ c200="#a7f3d0",
+ c300="#6ee7b7",
+ c400="#34d399",
+ c500="#10b981",
+ c600="#059669",
+ c700="#047857",
+ c800="#065f46",
+ c900="#064e3b",
+ c950="#054436",
+)
+teal = Color(
+ name="teal",
+ c50="#f0fdfa",
+ c100="#ccfbf1",
+ c200="#99f6e4",
+ c300="#5eead4",
+ c400="#2dd4bf",
+ c500="#14b8a6",
+ c600="#0d9488",
+ c700="#0f766e",
+ c800="#115e59",
+ c900="#134e4a",
+ c950="#12443e",
+)
+cyan = Color(
+ name="cyan",
+ c50="#ecfeff",
+ c100="#cffafe",
+ c200="#a5f3fc",
+ c300="#67e8f9",
+ c400="#22d3ee",
+ c500="#06b6d4",
+ c600="#0891b2",
+ c700="#0e7490",
+ c800="#155e75",
+ c900="#164e63",
+ c950="#14455c",
+)
+sky = Color(
+ name="sky",
+ c50="#f0f9ff",
+ c100="#e0f2fe",
+ c200="#bae6fd",
+ c300="#7dd3fc",
+ c400="#38bdf8",
+ c500="#0ea5e9",
+ c600="#0284c7",
+ c700="#0369a1",
+ c800="#075985",
+ c900="#0c4a6e",
+ c950="#0b4165",
+)
+blue = Color(
+ name="blue",
+ c50="#eff6ff",
+ c100="#dbeafe",
+ c200="#bfdbfe",
+ c300="#93c5fd",
+ c400="#60a5fa",
+ c500="#3b82f6",
+ c600="#2563eb",
+ c700="#1d4ed8",
+ c800="#1e40af",
+ c900="#1e3a8a",
+ c950="#1d3660",
+)
+indigo = Color(
+ name="indigo",
+ c50="#eef2ff",
+ c100="#e0e7ff",
+ c200="#c7d2fe",
+ c300="#a5b4fc",
+ c400="#818cf8",
+ c500="#6366f1",
+ c600="#4f46e5",
+ c700="#4338ca",
+ c800="#3730a3",
+ c900="#312e81",
+ c950="#2b2c5e",
+)
+violet = Color(
+ name="violet",
+ c50="#f5f3ff",
+ c100="#ede9fe",
+ c200="#ddd6fe",
+ c300="#c4b5fd",
+ c400="#a78bfa",
+ c500="#8b5cf6",
+ c600="#7c3aed",
+ c700="#6d28d9",
+ c800="#5b21b6",
+ c900="#4c1d95",
+ c950="#431d7f",
+)
+purple = Color(
+ name="purple",
+ c50="#faf5ff",
+ c100="#f3e8ff",
+ c200="#e9d5ff",
+ c300="#d8b4fe",
+ c400="#c084fc",
+ c500="#a855f7",
+ c600="#9333ea",
+ c700="#7e22ce",
+ c800="#6b21a8",
+ c900="#581c87",
+ c950="#4c1a73",
+)
+fuchsia = Color(
+ name="fuchsia",
+ c50="#fdf4ff",
+ c100="#fae8ff",
+ c200="#f5d0fe",
+ c300="#f0abfc",
+ c400="#e879f9",
+ c500="#d946ef",
+ c600="#c026d3",
+ c700="#a21caf",
+ c800="#86198f",
+ c900="#701a75",
+ c950="#5e1a66",
+)
+pink = Color(
+ name="pink",
+ c50="#fdf2f8",
+ c100="#fce7f3",
+ c200="#fbcfe8",
+ c300="#f9a8d4",
+ c400="#f472b6",
+ c500="#ec4899",
+ c600="#db2777",
+ c700="#be185d",
+ c800="#9d174d",
+ c900="#831843",
+ c950="#6e1a3d",
+)
+rose = Color(
+ name="rose",
+ c50="#fff1f2",
+ c100="#ffe4e6",
+ c200="#fecdd3",
+ c300="#fda4af",
+ c400="#fb7185",
+ c500="#f43f5e",
+ c600="#e11d48",
+ c700="#be123c",
+ c800="#9f1239",
+ c900="#881337",
+ c950="#771d3a",
+)
diff --git a/gradio/themes/utils/fonts.py b/gradio/themes/utils/fonts.py
new file mode 100644
index 0000000000000000000000000000000000000000..5525c2c4d58092e060c02dcb02828de984c71aca
--- /dev/null
+++ b/gradio/themes/utils/fonts.py
@@ -0,0 +1,56 @@
+from __future__ import annotations
+
+import json
+from typing import Iterable
+
+
+class FontEncoder(json.JSONEncoder):
+ def default(self, obj):
+ if isinstance(obj, Font):
+ return {
+ "__gradio_font__": True,
+ "name": obj.name,
+ "class": "google" if isinstance(obj, GoogleFont) else "font",
+ }
+ # Let the base class default method raise the TypeError
+ return json.JSONEncoder.default(self, obj)
+
+
+def as_font(dct):
+ if "__gradio_font__" in dct:
+ name = dct["name"]
+ return GoogleFont(name) if dct["class"] == "google" else Font(name)
+ return dct
+
+
+class Font:
+ def __init__(self, name: str):
+ self.name = name
+
+ def __str__(self) -> str:
+ return (
+ self.name
+ if self.name in ["sans-serif", "serif", "monospace", "cursive", "fantasy"]
+ else f"'{self.name}'"
+ )
+
+ def stylesheet(self) -> str:
+ return None
+
+ def __eq__(self, other: Font) -> bool:
+ return self.name == other.name and self.stylesheet() == other.stylesheet()
+
+ def __repr__(self) -> str:
+ klass = type(self)
+ class_repr = klass.__module__ + "." + klass.__qualname__
+ attrs = ", ".join([k + "=" + repr(v) for k, v in self.__dict__.items()])
+ return f"<{class_repr} ({attrs})>"
+
+
+class GoogleFont(Font):
+ def __init__(self, name: str, weights: Iterable[int] = (400, 600)):
+ self.name = name
+ self.weights = weights
+
+ def stylesheet(self) -> str:
+ return f'https://fonts.googleapis.com/css2?family={self.name.replace(" ", "+")}:wght@{";".join(str(weight) for weight in self.weights)}&display=swap'
diff --git a/gradio/themes/utils/readme_content.py b/gradio/themes/utils/readme_content.py
new file mode 100644
index 0000000000000000000000000000000000000000..49c8ca114822f3618f5a1bcb2edd1e70d5067562
--- /dev/null
+++ b/gradio/themes/utils/readme_content.py
@@ -0,0 +1,18 @@
+README_CONTENT = """
+---
+tags: [gradio-theme]
+title: {theme_name}
+colorFrom: red
+colorTo: purple
+sdk: gradio
+sdk_version: {gradio_version}
+app_file: app.py
+pinned: false
+license: apache-2.0
+---
+# {theme_name}
+## Description
+{description}
+## Contributions
+Thanks to [@{author}](https://huggingface.co/{author}) for adding this gradio theme!
+"""
diff --git a/gradio/themes/utils/semver_match.py b/gradio/themes/utils/semver_match.py
new file mode 100644
index 0000000000000000000000000000000000000000..265c096f41794d49f2dca028afb57c3adf69534b
--- /dev/null
+++ b/gradio/themes/utils/semver_match.py
@@ -0,0 +1,41 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+
+import huggingface_hub
+import semantic_version
+import semantic_version as semver
+
+
+@dataclass
+class ThemeAsset:
+ filename: str
+ version: semver.Version = field(init=False)
+
+ def __post_init__(self):
+ self.version = semver.Version(self.filename.split("@")[1].replace(".json", ""))
+
+
+def get_theme_assets(space_info: huggingface_hub.hf_api.SpaceInfo) -> list[ThemeAsset]:
+ # Commenting out as it seems that the `huggingface_hub` library is not parsing tags
+ # if "gradio-theme" not in getattr(space_info, "tags", []):
+ # raise ValueError(f"{space_info.id} is not a valid gradio-theme space!")
+
+ return [
+ ThemeAsset(filename.rfilename)
+ for filename in space_info.siblings
+ if filename.rfilename.startswith("themes/")
+ ]
+
+
+def get_matching_version(
+ assets: list[ThemeAsset], expression: str | None
+) -> ThemeAsset | None:
+ expression = expression or "*"
+
+ # Return most recent version that matches
+ matching_version = semantic_version.SimpleSpec(expression).select(
+ [a.version for a in assets]
+ )
+
+ return next((a for a in assets if a.version == matching_version), None)
diff --git a/gradio/themes/utils/sizes.py b/gradio/themes/utils/sizes.py
new file mode 100644
index 0000000000000000000000000000000000000000..99ed6b1ce447d638448d4970bde5227eedd53835
--- /dev/null
+++ b/gradio/themes/utils/sizes.py
@@ -0,0 +1,132 @@
+from __future__ import annotations
+
+
+class Size:
+ all = []
+
+ def __init__(
+ self, xxs: str, xs: str, sm: str, md: str, lg: str, xl: str, xxl: str, name=None
+ ):
+ self.xxs = xxs
+ self.xs = xs
+ self.sm = sm
+ self.md = md
+ self.lg = lg
+ self.xl = xl
+ self.xxl = xxl
+ self.name = name
+ Size.all.append(self)
+
+ def expand(self) -> list[str]:
+ return [self.xxs, self.xs, self.sm, self.md, self.lg, self.xl, self.xxl]
+
+
+radius_none = Size(
+ name="radius_none",
+ xxs="0px",
+ xs="0px",
+ sm="0px",
+ md="0px",
+ lg="0px",
+ xl="0px",
+ xxl="0px",
+)
+
+radius_sm = Size(
+ name="radius_sm",
+ xxs="1px",
+ xs="1px",
+ sm="2px",
+ md="4px",
+ lg="6px",
+ xl="8px",
+ xxl="12px",
+)
+
+radius_md = Size(
+ name="radius_md",
+ xxs="1px",
+ xs="2px",
+ sm="4px",
+ md="6px",
+ lg="8px",
+ xl="12px",
+ xxl="22px",
+)
+
+radius_lg = Size(
+ name="radius_lg",
+ xxs="2px",
+ xs="4px",
+ sm="6px",
+ md="8px",
+ lg="12px",
+ xl="16px",
+ xxl="24px",
+)
+
+spacing_sm = Size(
+ name="spacing_sm",
+ xxs="1px",
+ xs="1px",
+ sm="2px",
+ md="4px",
+ lg="6px",
+ xl="9px",
+ xxl="12px",
+)
+
+spacing_md = Size(
+ name="spacing_md",
+ xxs="1px",
+ xs="2px",
+ sm="4px",
+ md="6px",
+ lg="8px",
+ xl="10px",
+ xxl="16px",
+)
+
+spacing_lg = Size(
+ name="spacing_lg",
+ xxs="2px",
+ xs="4px",
+ sm="6px",
+ md="8px",
+ lg="10px",
+ xl="14px",
+ xxl="28px",
+)
+
+text_sm = Size(
+ name="text_sm",
+ xxs="8px",
+ xs="9px",
+ sm="11px",
+ md="13px",
+ lg="16px",
+ xl="20px",
+ xxl="24px",
+)
+
+text_md = Size(
+ name="text_md",
+ xxs="9px",
+ xs="10px",
+ sm="12px",
+ md="14px",
+ lg="16px",
+ xl="22px",
+ xxl="26px",
+)
+
+text_lg = Size(
+ name="text_lg",
+ xxs="10px",
+ xs="12px",
+ sm="14px",
+ md="16px",
+ lg="20px",
+ xl="24px",
+ xxl="28px",
+)
diff --git a/gradio/themes/utils/theme_dropdown.py b/gradio/themes/utils/theme_dropdown.py
new file mode 100644
index 0000000000000000000000000000000000000000..06956e561084548e455c2c04878ace8ddb0bcaf2
--- /dev/null
+++ b/gradio/themes/utils/theme_dropdown.py
@@ -0,0 +1,58 @@
+import os
+import pathlib
+
+from gradio.themes.utils import ThemeAsset
+
+
+def create_theme_dropdown():
+ import gradio as gr
+
+ asset_path = pathlib.Path() / "themes"
+ themes = []
+ for theme_asset in os.listdir(str(asset_path)):
+ themes.append(
+ (ThemeAsset(theme_asset), gr.Theme.load(str(asset_path / theme_asset)))
+ )
+
+ def make_else_if(theme_asset):
+ return f"""
+ else if (theme == '{str(theme_asset[0].version)}') {{
+ var theme_css = `{theme_asset[1]._get_theme_css()}`
+ }}"""
+
+ head, tail = themes[0], themes[1:]
+ if_statement = f"""
+ if (theme == "{str(head[0].version)}") {{
+ var theme_css = `{head[1]._get_theme_css()}`
+ }} {" ".join(make_else_if(t) for t in tail)}
+ """
+
+ latest_to_oldest = sorted([t[0] for t in themes], key=lambda asset: asset.version)[
+ ::-1
+ ]
+ latest_to_oldest = [str(t.version) for t in latest_to_oldest]
+
+ component = gr.Dropdown(
+ choices=latest_to_oldest,
+ value=latest_to_oldest[0],
+ render=False,
+ label="Select Version",
+ container=False,
+ )
+
+ return (
+ component,
+ f"""
+ (theme) => {{
+ if (!document.querySelector('.theme-css')) {{
+ var theme_elem = document.createElement('style');
+ theme_elem.classList.add('theme-css');
+ document.head.appendChild(theme_elem);
+ }} else {{
+ var theme_elem = document.querySelector('.theme-css');
+ }}
+ {if_statement}
+ theme_elem.innerHTML = theme_css;
+ }}
+ """,
+ )
diff --git a/gradio/tunneling.py b/gradio/tunneling.py
new file mode 100644
index 0000000000000000000000000000000000000000..18691420d2a0d67495c59924cea4bdf8a01dd685
--- /dev/null
+++ b/gradio/tunneling.py
@@ -0,0 +1,138 @@
+import atexit
+import os
+import platform
+import re
+import stat
+import subprocess
+import sys
+import time
+from pathlib import Path
+from typing import List
+
+import httpx
+
+VERSION = "0.2"
+CURRENT_TUNNELS: List["Tunnel"] = []
+
+machine = platform.machine()
+if machine == "x86_64":
+ machine = "amd64"
+
+BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}"
+EXTENSION = ".exe" if os.name == "nt" else ""
+BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}"
+
+BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}"
+BINARY_FOLDER = Path(__file__).parent
+BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}"
+
+TUNNEL_TIMEOUT_SECONDS = 30
+TUNNEL_ERROR_MESSAGE = (
+ "Could not create share URL. "
+ "Please check the appended log from frpc for more information:"
+)
+
+
+class Tunnel:
+ def __init__(self, remote_host, remote_port, local_host, local_port, share_token):
+ self.proc = None
+ self.url = None
+ self.remote_host = remote_host
+ self.remote_port = remote_port
+ self.local_host = local_host
+ self.local_port = local_port
+ self.share_token = share_token
+
+ @staticmethod
+ def download_binary():
+ if not Path(BINARY_PATH).exists():
+ resp = httpx.get(BINARY_URL, timeout=30)
+
+ if resp.status_code == 403:
+ raise OSError(
+ f"Cannot set up a share link as this platform is incompatible. Please "
+ f"create a GitHub issue with information about your platform: {platform.uname()}"
+ )
+
+ resp.raise_for_status()
+
+ # Save file data to local copy
+ with open(BINARY_PATH, "wb") as file:
+ file.write(resp.content)
+ st = os.stat(BINARY_PATH)
+ os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC)
+
+ def start_tunnel(self) -> str:
+ self.download_binary()
+ self.url = self._start_tunnel(BINARY_PATH)
+ return self.url
+
+ def kill(self):
+ if self.proc is not None:
+ print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}")
+ self.proc.terminate()
+ self.proc = None
+
+ def _start_tunnel(self, binary: str) -> str:
+ CURRENT_TUNNELS.append(self)
+ command = [
+ binary,
+ "http",
+ "-n",
+ self.share_token,
+ "-l",
+ str(self.local_port),
+ "-i",
+ self.local_host,
+ "--uc",
+ "--sd",
+ "random",
+ "--ue",
+ "--server_addr",
+ f"{self.remote_host}:{self.remote_port}",
+ "--disable_log_color",
+ ]
+ self.proc = subprocess.Popen(
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ atexit.register(self.kill)
+ return self._read_url_from_tunnel_stream()
+
+ def _read_url_from_tunnel_stream(self) -> str:
+ start_timestamp = time.time()
+
+ log = []
+ url = ""
+
+ def _raise_tunnel_error():
+ log_text = "\n".join(log)
+ print(log_text, file=sys.stderr)
+ raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}")
+
+ while url == "":
+ # check for timeout and log
+ if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS:
+ _raise_tunnel_error()
+
+ assert self.proc is not None
+ if self.proc.stdout is None:
+ continue
+
+ line = self.proc.stdout.readline()
+ line = line.decode("utf-8")
+
+ if line == "":
+ continue
+
+ log.append(line.strip())
+
+ if "start proxy success" in line:
+ result = re.search("start proxy success: (.+)\n", line)
+ if result is None:
+ _raise_tunnel_error()
+ else:
+ url = result.group(1)
+ elif "login to server failed" in line:
+ _raise_tunnel_error()
+
+ return url
diff --git a/gradio/utils.py b/gradio/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9b2ab52fe0a49267914c7b7fa6aa07ad8d408b6
--- /dev/null
+++ b/gradio/utils.py
@@ -0,0 +1,1042 @@
+""" Handy utility functions. """
+
+from __future__ import annotations
+
+import asyncio
+import copy
+import dataclasses
+import functools
+import importlib
+import inspect
+import json
+import json.decoder
+import os
+import pkgutil
+import re
+import threading
+import time
+import traceback
+import typing
+import urllib.parse
+import warnings
+from abc import ABC, abstractmethod
+from collections import OrderedDict
+from contextlib import contextmanager
+from io import BytesIO
+from numbers import Number
+from pathlib import Path
+from types import AsyncGeneratorType, GeneratorType
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ Generic,
+ Iterable,
+ Iterator,
+ Optional,
+ TypeVar,
+)
+
+import anyio
+import httpx
+import matplotlib
+from typing_extensions import ParamSpec
+
+import gradio
+from gradio.context import Context
+from gradio.strings import en
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from gradio.blocks import BlockContext, Blocks
+ from gradio.components import Component
+ from gradio.routes import App, Request
+
+JSON_PATH = os.path.join(os.path.dirname(gradio.__file__), "launches.json")
+
+P = ParamSpec("P")
+T = TypeVar("T")
+
+
+def get_package_version() -> str:
+ try:
+ package_json_data = (
+ pkgutil.get_data(__name__, "package.json").decode("utf-8").strip() # type: ignore
+ )
+ package_data = json.loads(package_json_data)
+ version = package_data.get("version", "")
+ return version
+ except Exception:
+ return ""
+
+
+def safe_get_lock() -> asyncio.Lock:
+ """Get asyncio.Lock() without fear of getting an Exception.
+
+ Needed because in reload mode we import the Blocks object outside
+ the main thread.
+ """
+ try:
+ asyncio.get_event_loop()
+ return asyncio.Lock()
+ except RuntimeError:
+ return None # type: ignore
+
+
+class BaseReloader(ABC):
+ @property
+ @abstractmethod
+ def running_app(self) -> App:
+ pass
+
+ def queue_changed(self, demo: Blocks):
+ return (
+ hasattr(self.running_app.blocks, "_queue") and not hasattr(demo, "_queue")
+ ) or (
+ not hasattr(self.running_app.blocks, "_queue") and hasattr(demo, "_queue")
+ )
+
+ def swap_blocks(self, demo: Blocks):
+ assert self.running_app.blocks
+ # Copy over the blocks to get new components and events but
+ # not a new queue
+ self.running_app.blocks._queue.block_fns = demo.fns
+ demo._queue = self.running_app.blocks._queue
+ self.running_app.blocks = demo
+ demo._queue.reload()
+
+
+class SourceFileReloader(BaseReloader):
+ def __init__(
+ self,
+ app: App,
+ watch_dirs: list[str],
+ watch_module_name: str,
+ stop_event: threading.Event,
+ change_event: threading.Event,
+ demo_name: str = "demo",
+ ) -> None:
+ super().__init__()
+ self.app = app
+ self.watch_dirs = watch_dirs
+ self.watch_module_name = watch_module_name
+ self.stop_event = stop_event
+ self.change_event = change_event
+ self.demo_name = demo_name
+
+ @property
+ def running_app(self) -> App:
+ return self.app
+
+ def should_watch(self) -> bool:
+ return not self.stop_event.is_set()
+
+ def stop(self) -> None:
+ self.stop_event.set()
+
+ def alert_change(self):
+ self.change_event.set()
+
+ def swap_blocks(self, demo: Blocks):
+ super().swap_blocks(demo)
+ self.alert_change()
+
+
+def watchfn(reloader: SourceFileReloader):
+ """Watch python files in a given module.
+
+ get_changes is taken from uvicorn's default file watcher.
+ """
+
+ # The thread running watchfn will be the thread reloading
+ # the app. So we need to modify this thread_data attr here
+ # so that subsequent calls to reload don't launch the app
+ from gradio.cli.commands.reload import reload_thread
+
+ reload_thread.running_reload = True
+
+ def get_changes() -> Path | None:
+ for file in iter_py_files():
+ try:
+ mtime = file.stat().st_mtime
+ except OSError: # pragma: nocover
+ continue
+
+ old_time = mtimes.get(file)
+ if old_time is None:
+ mtimes[file] = mtime
+ continue
+ elif mtime > old_time:
+ return file
+ return None
+
+ def iter_py_files() -> Iterator[Path]:
+ for reload_dir in reload_dirs:
+ for path in list(reload_dir.rglob("*.py")):
+ yield path.resolve()
+ for path in list(reload_dir.rglob("*.css")):
+ yield path.resolve()
+
+ module = None
+ reload_dirs = [Path(dir_) for dir_ in reloader.watch_dirs]
+ import sys
+
+ for dir_ in reload_dirs:
+ sys.path.insert(0, str(dir_))
+
+ mtimes = {}
+ while reloader.should_watch():
+ changed = get_changes()
+ if changed:
+ print(f"Changes detected in: {changed}")
+ # To simulate a fresh reload, delete all module references from sys.modules
+ # for the modules in the package the change came from.
+ dir_ = next(d for d in reload_dirs if is_in_or_equal(changed, d))
+ modules = list(sys.modules)
+ for k in modules:
+ v = sys.modules[k]
+ sourcefile = getattr(v, "__file__", None)
+ # Do not reload `reload.py` to keep thread data
+ if (
+ sourcefile
+ and dir_ == Path(inspect.getfile(gradio)).parent
+ and sourcefile.endswith("reload.py")
+ ):
+ continue
+ if sourcefile and is_in_or_equal(sourcefile, dir_):
+ del sys.modules[k]
+ try:
+ module = importlib.import_module(reloader.watch_module_name)
+ module = importlib.reload(module)
+ except Exception:
+ print(
+ f"Reloading {reloader.watch_module_name} failed with the following exception: "
+ )
+ traceback.print_exc()
+ mtimes = {}
+ continue
+
+ demo = getattr(module, reloader.demo_name)
+ if reloader.queue_changed(demo):
+ print(
+ "Reloading failed. The new demo has a queue and the old one doesn't (or vice versa). "
+ "Please launch your demo again"
+ )
+ else:
+ reloader.swap_blocks(demo)
+ mtimes = {}
+ time.sleep(0.05)
+
+
+def colab_check() -> bool:
+ """
+ Check if interface is launching from Google Colab
+ :return is_colab (bool): True or False
+ """
+ is_colab = False
+ try: # Check if running interactively using ipython.
+ from IPython.core.getipython import get_ipython
+
+ from_ipynb = get_ipython()
+ if "google.colab" in str(from_ipynb):
+ is_colab = True
+ except (ImportError, NameError):
+ pass
+ return is_colab
+
+
+def kaggle_check() -> bool:
+ return bool(
+ os.environ.get("KAGGLE_KERNEL_RUN_TYPE") or os.environ.get("GFOOTBALL_DATA_DIR")
+ )
+
+
+def sagemaker_check() -> bool:
+ try:
+ import boto3 # type: ignore
+
+ client = boto3.client("sts")
+ response = client.get_caller_identity()
+ return "sagemaker" in response["Arn"].lower()
+ except Exception:
+ return False
+
+
+def ipython_check() -> bool:
+ """
+ Check if interface is launching from iPython (not colab)
+ :return is_ipython (bool): True or False
+ """
+ is_ipython = False
+ try: # Check if running interactively using ipython.
+ from IPython.core.getipython import get_ipython
+
+ if get_ipython() is not None:
+ is_ipython = True
+ except (ImportError, NameError):
+ pass
+ return is_ipython
+
+
+def get_space() -> str | None:
+ if os.getenv("SYSTEM") == "spaces":
+ return os.getenv("SPACE_ID")
+ return None
+
+
+def is_zero_gpu_space() -> bool:
+ return os.getenv("SPACES_ZERO_GPU") == "true"
+
+
+def readme_to_html(article: str) -> str:
+ try:
+ response = httpx.get(article, timeout=3)
+ if response.status_code == httpx.codes.OK: # pylint: disable=no-member
+ article = response.text
+ except httpx.RequestError:
+ pass
+ return article
+
+
+def launch_counter() -> None:
+ try:
+ if not os.path.exists(JSON_PATH):
+ launches = {"launches": 1}
+ with open(JSON_PATH, "w+") as j:
+ json.dump(launches, j)
+ else:
+ with open(JSON_PATH) as j:
+ launches = json.load(j)
+ launches["launches"] += 1
+ if launches["launches"] in [25, 50, 150, 500, 1000]:
+ print(en["BETA_INVITE"])
+ with open(JSON_PATH, "w") as j:
+ j.write(json.dumps(launches))
+ except Exception:
+ pass
+
+
+def get_default_args(func: Callable) -> list[Any]:
+ signature = inspect.signature(func)
+ return [
+ v.default if v.default is not inspect.Parameter.empty else None
+ for v in signature.parameters.values()
+ ]
+
+
+def assert_configs_are_equivalent_besides_ids(
+ config1: dict, config2: dict, root_keys: tuple = ("mode",)
+):
+ """Allows you to test if two different Blocks configs produce the same demo.
+
+ Parameters:
+ config1 (dict): nested dict with config from the first Blocks instance
+ config2 (dict): nested dict with config from the second Blocks instance
+ root_keys (Tuple): an interable consisting of which keys to test for equivalence at
+ the root level of the config. By default, only "mode" is tested,
+ so keys like "version" are ignored.
+ """
+ config1 = copy.deepcopy(config1)
+ config2 = copy.deepcopy(config2)
+ config1 = json.loads(json.dumps(config1)) # convert tuples to lists
+ config2 = json.loads(json.dumps(config2))
+
+ for key in root_keys:
+ if config1[key] != config2[key]:
+ raise ValueError(f"Configs have different: {key}")
+
+ if len(config1["components"]) != len(config2["components"]):
+ raise ValueError("# of components are different")
+
+ def assert_same_components(config1_id, config2_id):
+ c1 = list(filter(lambda c: c["id"] == config1_id, config1["components"]))
+ if len(c1) == 0:
+ raise ValueError(f"Could not find component with id {config1_id}")
+ c1 = c1[0]
+ c2 = list(filter(lambda c: c["id"] == config2_id, config2["components"]))
+ if len(c2) == 0:
+ raise ValueError(f"Could not find component with id {config2_id}")
+ c2 = c2[0]
+ c1 = copy.deepcopy(c1)
+ c1.pop("id")
+ c2 = copy.deepcopy(c2)
+ c2.pop("id")
+ if c1 != c2:
+ raise ValueError(f"{c1} does not match {c2}")
+
+ def same_children_recursive(children1, chidren2):
+ for child1, child2 in zip(children1, chidren2):
+ assert_same_components(child1["id"], child2["id"])
+ if "children" in child1 or "children" in child2:
+ same_children_recursive(child1["children"], child2["children"])
+
+ children1 = config1["layout"]["children"]
+ children2 = config2["layout"]["children"]
+ same_children_recursive(children1, children2)
+
+ for d1, d2 in zip(config1["dependencies"], config2["dependencies"]):
+ for t1, t2 in zip(d1.pop("targets"), d2.pop("targets")):
+ assert_same_components(t1[0], t2[0])
+ for i1, i2 in zip(d1.pop("inputs"), d2.pop("inputs")):
+ assert_same_components(i1, i2)
+ for o1, o2 in zip(d1.pop("outputs"), d2.pop("outputs")):
+ assert_same_components(o1, o2)
+
+ if d1 != d2:
+ raise ValueError(f"{d1} does not match {d2}")
+
+ return True
+
+
+def format_ner_list(input_string: str, ner_groups: list[dict[str, str | int]]):
+ if len(ner_groups) == 0:
+ return [(input_string, None)]
+
+ output = []
+ end = 0
+ prev_end = 0
+
+ for group in ner_groups:
+ entity, start, end = group["entity_group"], group["start"], group["end"]
+ output.append((input_string[prev_end:start], None))
+ output.append((input_string[start:end], entity))
+ prev_end = end
+
+ output.append((input_string[end:], None))
+ return output
+
+
+def delete_none(_dict: dict, skip_value: bool = False) -> dict:
+ """
+ Delete keys whose values are None from a dictionary
+ """
+ for key, value in list(_dict.items()):
+ if skip_value and key == "value":
+ continue
+ elif value is None:
+ del _dict[key]
+ return _dict
+
+
+def resolve_singleton(_list: list[Any] | Any) -> Any:
+ if len(_list) == 1:
+ return _list[0]
+ else:
+ return _list
+
+
+def component_or_layout_class(cls_name: str) -> type[Component] | type[BlockContext]:
+ """
+ Returns the component, template, or layout class with the given class name, or
+ raises a ValueError if not found.
+
+ Parameters:
+ cls_name (str): lower-case string class name of a component
+ Returns:
+ cls: the component class
+ """
+ import gradio.blocks
+ import gradio.components
+ import gradio.layouts
+ import gradio.templates
+
+ components = [
+ (name, cls)
+ for name, cls in gradio.components.__dict__.items()
+ if isinstance(cls, type)
+ ]
+ templates = [
+ (name, cls)
+ for name, cls in gradio.templates.__dict__.items()
+ if isinstance(cls, type)
+ ]
+ layouts = [
+ (name, cls)
+ for name, cls in gradio.layouts.__dict__.items()
+ if isinstance(cls, type)
+ ]
+ for name, cls in components + templates + layouts:
+ if name.lower() == cls_name.replace("_", "") and (
+ issubclass(cls, gradio.components.Component)
+ or issubclass(cls, gradio.blocks.BlockContext)
+ ):
+ return cls
+ raise ValueError(f"No such component or layout: {cls_name}")
+
+
+def run_coro_in_background(func: Callable, *args, **kwargs):
+ """
+ Runs coroutines in background.
+
+ Warning, be careful to not use this function in other than FastAPI scope, because the event_loop has not started yet.
+ You can use it in any scope reached by FastAPI app.
+
+ correct scope examples: endpoints in routes, Blocks.process_api
+ incorrect scope examples: Blocks.launch
+
+ Use startup_events in routes.py if you need to run a coro in background in Blocks.launch().
+
+
+ Example:
+ utils.run_coro_in_background(fn, *args, **kwargs)
+
+ Args:
+ func:
+ *args:
+ **kwargs:
+
+ Returns:
+
+ """
+ event_loop = asyncio.get_event_loop()
+ return event_loop.create_task(func(*args, **kwargs))
+
+
+def run_sync_iterator_async(iterator):
+ """Helper for yielding StopAsyncIteration from sync iterators."""
+ try:
+ return next(iterator)
+ except StopIteration:
+ # raise a ValueError here because co-routines can't raise StopIteration themselves
+ raise StopAsyncIteration() from None
+
+
+class SyncToAsyncIterator:
+ """Treat a synchronous iterator as async one."""
+
+ def __init__(self, iterator, limiter) -> None:
+ self.iterator = iterator
+ self.limiter = limiter
+
+ def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ return await anyio.to_thread.run_sync(
+ run_sync_iterator_async, self.iterator, limiter=self.limiter
+ )
+
+
+async def async_iteration(iterator):
+ # anext not introduced until 3.10 :(
+ return await iterator.__anext__()
+
+
+@contextmanager
+def set_directory(path: Path | str):
+ """Context manager that sets the working directory to the given path."""
+ origin = Path().absolute()
+ try:
+ os.chdir(path)
+ yield
+ finally:
+ os.chdir(origin)
+
+
+@contextmanager
+def no_raise_exception():
+ """Context manager that suppresses exceptions."""
+ try:
+ yield
+ except Exception:
+ pass
+
+
+def sanitize_value_for_csv(value: str | Number) -> str | Number:
+ """
+ Sanitizes a value that is being written to a CSV file to prevent CSV injection attacks.
+ Reference: https://owasp.org/www-community/attacks/CSV_Injection
+ """
+ if isinstance(value, Number):
+ return value
+ unsafe_prefixes = ["=", "+", "-", "@", "\t", "\n"]
+ unsafe_sequences = [",=", ",+", ",-", ",@", ",\t", ",\n"]
+ if any(value.startswith(prefix) for prefix in unsafe_prefixes) or any(
+ sequence in value for sequence in unsafe_sequences
+ ):
+ value = f"'{value}"
+ return value
+
+
+def sanitize_list_for_csv(values: list[Any]) -> list[Any]:
+ """
+ Sanitizes a list of values (or a list of list of values) that is being written to a
+ CSV file to prevent CSV injection attacks.
+ """
+ sanitized_values = []
+ for value in values:
+ if isinstance(value, list):
+ sanitized_value = [sanitize_value_for_csv(v) for v in value]
+ sanitized_values.append(sanitized_value)
+ else:
+ sanitized_value = sanitize_value_for_csv(value)
+ sanitized_values.append(sanitized_value)
+ return sanitized_values
+
+
+def append_unique_suffix(name: str, list_of_names: list[str]):
+ """Appends a numerical suffix to `name` so that it does not appear in `list_of_names`."""
+ set_of_names: set[str] = set(list_of_names) # for O(1) lookup
+ if name not in set_of_names:
+ return name
+ else:
+ suffix_counter = 1
+ new_name = f"{name}_{suffix_counter}"
+ while new_name in set_of_names:
+ suffix_counter += 1
+ new_name = f"{name}_{suffix_counter}"
+ return new_name
+
+
+def validate_url(possible_url: str) -> bool:
+ headers = {"User-Agent": "gradio (https://gradio.app/; gradio-team@huggingface.co)"}
+ try:
+ head_request = httpx.head(possible_url, headers=headers, follow_redirects=True)
+ # some URLs, such as AWS S3 presigned URLs, return a 405 or a 403 for HEAD requests
+ if head_request.status_code == 405 or head_request.status_code == 403:
+ return httpx.get(possible_url, headers=headers).is_success
+ return head_request.is_success
+ except Exception:
+ return False
+
+
+def is_update(val):
+ return isinstance(val, dict) and "update" in val.get("__type__", "")
+
+
+def get_continuous_fn(fn: Callable, every: float) -> Callable:
+ # For Wasm-compatibility, we need to use asyncio.sleep() instead of time.sleep(),
+ # so we need to make the function async.
+ async def continuous_coro(*args):
+ while True:
+ output = fn(*args)
+ if isinstance(output, GeneratorType):
+ for item in output:
+ yield item
+ elif isinstance(output, AsyncGeneratorType):
+ async for item in output:
+ yield item
+ elif inspect.isawaitable(output):
+ yield await output
+ else:
+ yield output
+ await asyncio.sleep(every)
+
+ return continuous_coro
+
+
+def function_wrapper(
+ f: Callable,
+ before_fn: Callable | None = None,
+ before_args: Iterable | None = None,
+ after_fn: Callable | None = None,
+ after_args: Iterable | None = None,
+):
+ before_args = [] if before_args is None else before_args
+ after_args = [] if after_args is None else after_args
+ if inspect.isasyncgenfunction(f):
+
+ @functools.wraps(f)
+ async def asyncgen_wrapper(*args, **kwargs):
+ iterator = f(*args, **kwargs)
+ while True:
+ if before_fn:
+ before_fn(*before_args)
+ try:
+ response = await iterator.__anext__()
+ except StopAsyncIteration:
+ if after_fn:
+ after_fn(*after_args)
+ break
+ if after_fn:
+ after_fn(*after_args)
+ yield response
+
+ return asyncgen_wrapper
+
+ elif asyncio.iscoroutinefunction(f):
+
+ @functools.wraps(f)
+ async def async_wrapper(*args, **kwargs):
+ if before_fn:
+ before_fn(*before_args)
+ response = await f(*args, **kwargs)
+ if after_fn:
+ after_fn(*after_args)
+ return response
+
+ return async_wrapper
+
+ elif inspect.isgeneratorfunction(f):
+
+ @functools.wraps(f)
+ def gen_wrapper(*args, **kwargs):
+ iterator = f(*args, **kwargs)
+ while True:
+ if before_fn:
+ before_fn(*before_args)
+ try:
+ response = next(iterator)
+ except StopIteration:
+ if after_fn:
+ after_fn(*after_args)
+ break
+ if after_fn:
+ after_fn(*after_args)
+ yield response
+
+ return gen_wrapper
+
+ else:
+
+ @functools.wraps(f)
+ def wrapper(*args, **kwargs):
+ if before_fn:
+ before_fn(*before_args)
+ response = f(*args, **kwargs)
+ if after_fn:
+ after_fn(*after_args)
+ return response
+
+ return wrapper
+
+
+def get_function_with_locals(
+ fn: Callable,
+ blocks: Blocks,
+ event_id: str | None,
+ in_event_listener: bool,
+ request: Request | None,
+):
+ def before_fn(blocks, event_id):
+ from gradio.context import LocalContext
+
+ LocalContext.blocks.set(blocks)
+ LocalContext.in_event_listener.set(in_event_listener)
+ LocalContext.event_id.set(event_id)
+ LocalContext.request.set(request)
+
+ def after_fn():
+ from gradio.context import LocalContext
+
+ LocalContext.in_event_listener.set(False)
+ LocalContext.request.set(None)
+
+ return function_wrapper(
+ fn,
+ before_fn=before_fn,
+ before_args=(blocks, event_id),
+ after_fn=after_fn,
+ )
+
+
+async def cancel_tasks(task_ids: set[str]):
+ matching_tasks = [
+ task for task in asyncio.all_tasks() if task.get_name() in task_ids
+ ]
+ for task in matching_tasks:
+ task.cancel()
+ await asyncio.gather(*matching_tasks, return_exceptions=True)
+
+
+def set_task_name(task, session_hash: str, fn_index: int, batch: bool):
+ if not batch:
+ task.set_name(f"{session_hash}_{fn_index}")
+
+
+def get_cancel_function(
+ dependencies: list[dict[str, Any]],
+) -> tuple[Callable, list[int]]:
+ fn_to_comp = {}
+ for dep in dependencies:
+ if Context.root_block:
+ fn_index = next(
+ i for i, d in enumerate(Context.root_block.dependencies) if d == dep
+ )
+ fn_to_comp[fn_index] = [
+ Context.root_block.blocks[o] for o in dep["outputs"]
+ ]
+
+ async def cancel(session_hash: str) -> None:
+ task_ids = {f"{session_hash}_{fn}" for fn in fn_to_comp}
+ await cancel_tasks(task_ids)
+
+ return (
+ cancel,
+ list(fn_to_comp.keys()),
+ )
+
+
+def get_type_hints(fn):
+ # Importing gradio with the canonical abbreviation. Used in typing._eval_type.
+ import gradio as gr # noqa: F401
+ from gradio import OAuthProfile, OAuthToken, Request # noqa: F401
+
+ if inspect.isfunction(fn) or inspect.ismethod(fn):
+ pass
+ elif callable(fn):
+ fn = fn.__call__
+ else:
+ return {}
+
+ try:
+ return typing.get_type_hints(fn)
+ except TypeError:
+ # On Python 3.9 or earlier, get_type_hints throws a TypeError if the function
+ # has a type annotation that include "|". We resort to parsing the signature
+ # manually using inspect.signature.
+ type_hints = {}
+ sig = inspect.signature(fn)
+ for name, param in sig.parameters.items():
+ if param.annotation is inspect.Parameter.empty:
+ continue
+ if param.annotation == "gr.OAuthProfile | None":
+ # Special case: we want to inject the OAuthProfile value even on Python 3.9
+ type_hints[name] = Optional[OAuthProfile]
+ if param.annotation == "gr.OAuthToken | None":
+ # Special case: we want to inject the OAuthToken value even on Python 3.9
+ type_hints[name] = Optional[OAuthToken]
+ if "|" in str(param.annotation):
+ continue
+ # To convert the string annotation to a class, we use the
+ # internal typing._eval_type function. This is not ideal, but
+ # it's the only way to do it without eval-ing the string.
+ # Since the API is internal, it may change in the future.
+ try:
+ type_hints[name] = typing._eval_type( # type: ignore
+ typing.ForwardRef(param.annotation), globals(), locals()
+ )
+ except (NameError, TypeError):
+ pass
+ return type_hints
+
+
+def is_special_typed_parameter(name, parameter_types):
+ from gradio.helpers import EventData
+ from gradio.oauth import OAuthProfile, OAuthToken
+ from gradio.routes import Request
+
+ """Checks if parameter has a type hint designating it as a gr.Request, gr.EventData, gr.OAuthProfile or gr.OAuthToken."""
+ hint = parameter_types.get(name)
+ if not hint:
+ return False
+ is_request = hint == Request
+ is_oauth_arg = hint in (
+ OAuthProfile,
+ Optional[OAuthProfile],
+ OAuthToken,
+ Optional[OAuthToken],
+ )
+ is_event_data = inspect.isclass(hint) and issubclass(hint, EventData)
+ return is_request or is_event_data or is_oauth_arg
+
+
+def check_function_inputs_match(fn: Callable, inputs: list, inputs_as_dict: bool):
+ """
+ Checks if the input component set matches the function
+ Returns: None if valid or if the function does not have a signature (e.g. is a built in),
+ or a string error message if mismatch
+ """
+ try:
+ signature = inspect.signature(fn)
+ except ValueError:
+ return None
+ parameter_types = get_type_hints(fn)
+ min_args = 0
+ max_args = 0
+ infinity = -1
+ for name, param in signature.parameters.items():
+ has_default = param.default != param.empty
+ if param.kind in [param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD]:
+ if not is_special_typed_parameter(name, parameter_types):
+ if not has_default:
+ min_args += 1
+ max_args += 1
+ elif param.kind == param.VAR_POSITIONAL:
+ max_args = infinity
+ elif param.kind == param.KEYWORD_ONLY and not has_default:
+ return f"Keyword-only args must have default values for function {fn}"
+ arg_count = 1 if inputs_as_dict else len(inputs)
+ if min_args == max_args and max_args != arg_count:
+ warnings.warn(
+ f"Expected {max_args} arguments for function {fn}, received {arg_count}."
+ )
+ if arg_count < min_args:
+ warnings.warn(
+ f"Expected at least {min_args} arguments for function {fn}, received {arg_count}."
+ )
+ if max_args != infinity and arg_count > max_args:
+ warnings.warn(
+ f"Expected maximum {max_args} arguments for function {fn}, received {arg_count}."
+ )
+
+
+class TupleNoPrint(tuple):
+ # To remove printing function return in notebook
+ def __repr__(self):
+ return ""
+
+ def __str__(self):
+ return ""
+
+
+class MatplotlibBackendMananger:
+ def __enter__(self):
+ self._original_backend = matplotlib.get_backend()
+ matplotlib.use("agg")
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ matplotlib.use(self._original_backend)
+
+
+def tex2svg(formula, *args):
+ with MatplotlibBackendMananger():
+ import matplotlib.pyplot as plt
+
+ fontsize = 20
+ dpi = 300
+ plt.rc("mathtext", fontset="cm")
+ fig = plt.figure(figsize=(0.01, 0.01))
+ fig.text(0, 0, rf"${formula}$", fontsize=fontsize)
+ output = BytesIO()
+ fig.savefig( # type: ignore
+ output,
+ dpi=dpi,
+ transparent=True,
+ format="svg",
+ bbox_inches="tight",
+ pad_inches=0.0,
+ )
+ plt.close(fig)
+ output.seek(0)
+ xml_code = output.read().decode("utf-8")
+ svg_start = xml_code.index(".*<\/metadata>", "", svg_code, flags=re.DOTALL)
+ svg_code = re.sub(r' width="[^"]+"', "", svg_code)
+ height_match = re.search(r'height="([\d.]+)pt"', svg_code)
+ if height_match:
+ height = float(height_match.group(1))
+ new_height = height / fontsize # conversion from pt to em
+ svg_code = re.sub(
+ r'height="[\d.]+pt"', f'height="{new_height}em"', svg_code
+ )
+ copy_code = f"{formula} "
+ return f"{copy_code}{svg_code}"
+
+
+def abspath(path: str | Path) -> Path:
+ """Returns absolute path of a str or Path path, but does not resolve symlinks."""
+ path = Path(path)
+
+ if path.is_absolute():
+ return path
+
+ # recursively check if there is a symlink within the path
+ is_symlink = path.is_symlink() or any(
+ parent.is_symlink() for parent in path.parents
+ )
+
+ if is_symlink or path == path.resolve(): # in case path couldn't be resolved
+ return Path.cwd() / path
+ else:
+ return path.resolve()
+
+
+def is_in_or_equal(path_1: str | Path, path_2: str | Path):
+ """
+ True if path_1 is a descendant (i.e. located within) path_2 or if the paths are the
+ same, returns False otherwise.
+ Parameters:
+ path_1: str or Path (should be a file)
+ path_2: str or Path (can be a file or directory)
+ """
+ path_1, path_2 = abspath(path_1), abspath(path_2)
+ try:
+ if ".." in str(path_1.relative_to(path_2)): # prevent path traversal
+ return False
+ except ValueError:
+ return False
+ return True
+
+
+HTML_TAG_RE = re.compile("<.*?>")
+
+
+def remove_html_tags(raw_html: str | None) -> str:
+ return re.sub(HTML_TAG_RE, "", raw_html or "")
+
+
+def find_user_stack_level() -> int:
+ """
+ Find the first stack frame not inside Gradio.
+ """
+ frame = inspect.currentframe()
+ n = 0
+ while frame:
+ fname = inspect.getfile(frame)
+ if "/gradio/" not in fname.replace(os.sep, "/"):
+ break
+ frame = frame.f_back
+ n += 1
+ return n
+
+
+class NamedString(str):
+ """
+ Subclass of str that includes a .name attribute equal to the value of the string itself. This class is used when returning
+ a value from the `.preprocess()` methods of the File and UploadButton components. Before Gradio 4.0, these methods returned a file
+ object which was then converted to a string filepath using the `.name` attribute. In Gradio 4.0, these methods now return a str
+ filepath directly, but to maintain backwards compatibility, we use this class instead of a regular str.
+ """
+
+ def __init__(self, *args):
+ super().__init__()
+ self.name = str(self) if args else ""
+
+
+def default_input_labels():
+ """
+ A generator that provides default input labels for components when the user's function
+ does not have named parameters. The labels are of the form "input 0", "input 1", etc.
+ """
+ n = 0
+ while True:
+ yield f"input {n}"
+ n += 1
+
+
+def get_extension_from_file_path_or_url(file_path_or_url: str) -> str:
+ """
+ Returns the file extension (without the dot) from a file path or URL. If the file path or URL does not have a file extension, returns an empty string.
+ For example, "https://example.com/avatar/xxxx.mp4?se=2023-11-16T06:51:23Z&sp=r" would return "mp4".
+ """
+ parsed_url = urllib.parse.urlparse(file_path_or_url)
+ file_extension = os.path.splitext(os.path.basename(parsed_url.path))[1]
+ return file_extension[1:] if file_extension else ""
+
+
+def convert_to_dict_if_dataclass(value):
+ if dataclasses.is_dataclass(value):
+ return dataclasses.asdict(value)
+ return value
+
+
+K = TypeVar("K")
+V = TypeVar("V")
+
+
+class LRUCache(OrderedDict, Generic[K, V]):
+ def __init__(self, max_size: int = 100):
+ super().__init__()
+ self.max_size: int = max_size
+
+ def __setitem__(self, key: K, value: V) -> None:
+ if key in self:
+ self.move_to_end(key)
+ elif len(self) >= self.max_size:
+ self.popitem(last=False)
+ super().__setitem__(key, value)
+
+
+def get_cache_folder() -> Path:
+ return Path(os.environ.get("GRADIO_EXAMPLES_CACHE", "gradio_cached_examples"))
diff --git a/gradio/wasm_utils.py b/gradio/wasm_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c067ff2cf699e58f2f859647465f801cd7d8ac9
--- /dev/null
+++ b/gradio/wasm_utils.py
@@ -0,0 +1,53 @@
+from __future__ import annotations
+
+import sys
+from contextlib import contextmanager
+from contextvars import ContextVar
+
+# See https://pyodide.org/en/stable/usage/faq.html#how-to-detect-that-code-is-run-with-pyodide
+IS_WASM = sys.platform == "emscripten"
+
+
+class WasmUnsupportedError(Exception):
+ pass
+
+
+# Mapping from app ID to the Gradio's FastAPI app instance (`app`).
+# To support the SharedWorker mode where multiple apps are running in the same worker,
+# we need to keep track of the app instances for each app ID.
+app_map = {}
+
+
+# `with app_id_context(app_id):` is used to set the app ID
+# which `register_app()` uses to register the app instance.
+# Context variables are natively supported in asyncio and
+# can manage data in each task (https://docs.python.org/3/library/contextvars.html#asyncio-support),
+# so we can use them for this purpose.
+_app_id_context_var: ContextVar[str | None] = ContextVar("app_id", default=None)
+
+
+@contextmanager
+def app_id_context(app_id: str):
+ token = _app_id_context_var.set(app_id)
+ yield
+ _app_id_context_var.reset(token)
+
+
+# `register_app` and `get_registered_app` are used
+# for the Wasm worker to get a reference to
+# the Gradio's FastAPI app instance (`app`).
+def register_app(_app):
+ global app_map
+
+ app_id = _app_id_context_var.get()
+
+ if app_id in app_map:
+ app = app_map[app_id]
+ app.blocks.close()
+
+ app_map[app_id] = _app
+
+
+def get_registered_app(app_id: str):
+ global app_map
+ return app_map[app_id]
diff --git a/guides/01_getting-started/01_quickstart.md b/guides/01_getting-started/01_quickstart.md
new file mode 100644
index 0000000000000000000000000000000000000000..211979b5e8148df2e3d3289127b86ecac981f485
--- /dev/null
+++ b/guides/01_getting-started/01_quickstart.md
@@ -0,0 +1,118 @@
+# Quickstart
+
+Gradio is an open-source Python package that allows you to quickly **build** a demo or web application for your machine learning model, API, or any arbitary Python function. You can then **share** a link to your demo or web application in just a few seconds using Gradio's built-in sharing features. *No JavaScript, CSS, or web hosting experience needed!*
+
+
+
+It just takes a few lines of Python to create a beautiful demo like the one above, so let's get started 💫
+
+## Installation
+
+**Prerequisite**: Gradio requires [Python 3.8 or higher](https://www.python.org/downloads/)
+
+
+We recommend installing Gradio using `pip`, which is included by default in Python. Run this in your terminal or command prompt:
+
+```bash
+pip install gradio
+```
+
+
+Tip: it is best to install Gradio in a virtual environment. Detailed installation instructions for all common operating systems are provided here .
+
+## Building Your First Demo
+
+You can run Gradio in your favorite code editor, Jupyter notebook, Google Colab, or anywhere else you write Python. Let's write your first Gradio app:
+
+
+$code_hello_world_4
+
+
+Tip: We shorten the imported name from gradio
to gr
for better readability of code. This is a widely adopted convention that you should follow so that anyone working with your code can easily understand it.
+
+Now, run your code. If you've written the Python code in a file named, for example, `app.py`, then you would run `python app.py` from the terminal.
+
+The demo below will open in a browser on [http://localhost:7860](http://localhost:7860) if running from a file. If you are running within a notebook, the demo will appear embedded within the notebook.
+
+$demo_hello_world_4
+
+Type your name in the textbox on the left, drag the slider, and then press the Submit button. You should see a friendly greeting on the right.
+
+Tip: When developing locally, you can run your Gradio app in hot reload mode , which automatically reloads the Gradio app whenever you make changes to the file. To do this, simply type in gradio
before the name of the file instead of python
. In the example above, you would type: `gradio app.py` in your terminal. Learn more about hot reloading in the Hot Reloading Guide .
+
+
+**Understanding the `Interface` Class**
+
+You'll notice that in order to make your first demo, you created an instance of the `gr.Interface` class. The `Interface` class is designed to create demos for machine learning models which accept one or more inputs, and return one or more outputs.
+
+The `Interface` class has three core arguments:
+
+- `fn`: the function to wrap a user interface (UI) around
+- `inputs`: the Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.
+- `outputs`: the Gradio component(s) to use for the output. The number of components should match the number of return values from your function.
+
+The `fn` argument is very flexible -- you can pass *any* Python function that you want to wrap with a UI. In the example above, we saw a relatively simple function, but the function could be anything from a music generator to a tax calculator to the prediction function of a pretrained machine learning model.
+
+The `input` and `output` arguments take one or more Gradio components. As we'll see, Gradio includes more than [30 built-in components](https://www.gradio.app/docs/components) (such as the `gr.Textbox()`, `gr.Image()`, and `gr.HTML()` components) that are designed for machine learning applications.
+
+Tip: For the `inputs` and `outputs` arguments, you can pass in the name of these components as a string (`"textbox"`) or an instance of the class (`gr.Textbox()`).
+
+If your function accepts more than one argument, as is the case above, pass a list of input components to `inputs`, with each input component corresponding to one of the arguments of the function, in order. The same holds true if your function returns more than one value: simply pass in a list of components to `outputs`. This flexibility makes the `Interface` class a very powerful way to create demos.
+
+We'll dive deeper into the `gr.Interface` on our series on [building Interfaces](https://www.gradio.app/main/guides/the-interface-class).
+
+## Sharing Your Demo
+
+What good is a beautiful demo if you can't share it? Gradio lets you easily share a machine learning demo without having to worry about the hassle of hosting on a web server. Simply set `share=True` in `launch()`, and a publicly accessible URL will be created for your demo. Let's revisit our example demo, but change the last line as follows:
+
+```python
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
+
+demo.launch(share=True) # Share your demo with just 1 extra parameter 🚀
+```
+
+When you run this code, a public URL will be generated for your demo in a matter of seconds, something like:
+
+👉 `https://a23dsf231adb.gradio.live`
+
+Now, anyone around the world can try your Gradio demo from their browser, while the machine learning model and all computation continues to run locally on your computer.
+
+To learn more about sharing your demo, read our dedicated guide on [sharing your Gradio application](https://www.gradio.app/guides/sharing-your-app).
+
+
+## An Overview of Gradio
+
+So far, we've been discussing the `Interface` class, which is a high-level class that lets to build demos quickly with Gradio. But what else does Gradio do?
+
+### Chatbots with `gr.ChatInterface`
+
+Gradio includes another high-level class, `gr.ChatInterface`, which is specifically designed to create Chatbot UIs. Similar to `Interface`, you supply a function and Gradio creates a fully working Chatbot UI. If you're interested in creating a chatbot, you can jump straight to [our dedicated guide on `gr.ChatInterface`](https://www.gradio.app/guides/creating-a-chatbot-fast).
+
+### Custom Demos with `gr.Blocks`
+
+Gradio also offers a low-level approach for designing web apps with more flexible layouts and data flows with the `gr.Blocks` class. Blocks allows you to do things like control where components appear on the page, handle complex data flows (e.g. outputs can serve as inputs to other functions), and update properties/visibility of components based on user interaction — still all in Python.
+
+You can build very custom and complex applications using `gr.Blocks()`. For example, the popular image generation [Automatic1111 Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) is built using Gradio Blocks. We dive deeper into the `gr.Blocks` on our series on [building with Blocks](https://www.gradio.app/guides/blocks-and-event-listeners).
+
+
+### The Gradio Python & JavaScript Ecosystem
+
+That's the gist of the core `gradio` Python library, but Gradio is actually so much more! Its an entire ecosystem of Python and JavaScript libraries that let you build machine learning applications, or query them programmatically, in Python or JavaScript. Here are other related parts of the Gradio ecosystem:
+
+* [Gradio Python Client](https://www.gradio.app/guides/getting-started-with-the-python-client) (`gradio_client`): query any Gradio app programmatically in Python.
+* [Gradio JavaScript Client](https://www.gradio.app/guides/getting-started-with-the-js-client) (`@gradio/client`): query any Gradio app programmatically in JavaScript.
+* [Gradio-Lite](https://www.gradio.app/guides/gradio-lite) (`@gradio/lite`): write Gradio apps in Python that run entirely in the browser (no server needed!), thanks to Pyodide.
+* [Hugging Face Spaces](https://huggingface.co/spaces): the most popular place to host Gradio applications — for free!
+
+## What's Next?
+
+Keep learning about Gradio sequentially using the Gradio Guides, which include explanations as well as example code and embedded interactive demos. Next up: [key features about Gradio demos](https://www.gradio.app/guides/key-features).
+
+Or, if you already know the basics and are looking for something specific, you can search the more [technical API documentation](https://www.gradio.app/docs/).
+
+
diff --git a/guides/01_getting-started/02_key-features.md b/guides/01_getting-started/02_key-features.md
new file mode 100644
index 0000000000000000000000000000000000000000..68f88afcc614a6294cf04540ece3dc36c4eefe61
--- /dev/null
+++ b/guides/01_getting-started/02_key-features.md
@@ -0,0 +1,192 @@
+# Key Features
+
+Let's go through some of the key features of Gradio. This guide is intended to be a high-level overview of various things that you should be aware of as you build your demo. Where appropriate, we link to more detailed guides on specific topics.
+
+1. [Components](#components)
+2. [Queuing](#queuing)
+3. [Streaming outputs](#streaming-outputs)
+4. [Streaming inputs](#streaming-inputs)
+5. [Alert modals](#alert-modals)
+6. [Styling](#styling)
+7. [Progress bars](#progress-bars)
+8. [Batch functions](#batch-functions)
+
+## Components
+
+Gradio includes more than 30 pre-built components (as well as many user-built _custom components_) that can be used as inputs or outputs in your demo with a single line of code. These components correspond to common data types in machine learning and data science, e.g. the `gr.Image` component is designed to handle input or output images, the `gr.Label` component displays classification labels and probabilities, the `gr.Plot` component displays various kinds of plots, and so on.
+
+Each component includes various constructor attributes that control the properties of the component. For example, you can control the number of lines in a `gr.Textbox` using the `lines` argument (which takes a positive integer) in its constructor. Or you can control the way that a user can provide an image in the `gr.Image` component using the `sources` parameter (which takes a list like `["webcam", "upload"]`).
+
+**Static and Interactive Components**
+
+Every component has a _static_ version that is designed to *display* data, and most components also have an _interactive_ version designed to let users input or modify the data. Typically, you don't need to think about this distinction, because when you build a Gradio demo, Gradio automatically figures out whether the component should be static or interactive based on whether it is being used as an input or output. However, you can set this manually using the `interactive` argument that every component supports.
+
+**Preprocessing and Postprocessing**
+
+When a component is used as an input, Gradio automatically handles the _preprocessing_ needed to convert the data from a type sent by the user's browser (such as an uploaded image) to a form that can be accepted by your function (such as a `numpy` array).
+
+
+Similarly, when a component is used as an output, Gradio automatically handles the _postprocessing_ needed to convert the data from what is returned by your function (such as a list of image paths) to a form that can be displayed in the user's browser (a gallery of images).
+
+Consider an example demo with three input components (`gr.Textbox`, `gr.Number`, and `gr.Image`) and two outputs (`gr.Number` and `gr.Gallery`) that serve as a UI for your image-to-image generation model. Below is a diagram of what our preprocessing will send to the model and what our postprocessing will require from it.
+
+![](https://github.com/gradio-app/gradio/blob/main/guides/assets/dataflow.svg?raw=true)
+
+In this image, the following preprocessing steps happen to send the data from the browser to your function:
+
+* The text in the textbox is converted to a Python `str` (essentially no preprocessing)
+* The number in the number input in converted to a Python `float` (essentially no preprocessing)
+* Most importantly, ihe image supplied by the user is converted to a `numpy.array` representation of the RGB values in the image
+
+Images are converted to NumPy arrays because they are a common format for machine learning workflows. You can control the _preprocessing_ using the component's parameters when constructing the component. For example, if you instantiate the `Image` component with the following parameters, it will preprocess the image to the `PIL` format instead:
+
+```py
+img = gr.Image(type="pil")
+```
+
+Postprocessing is even simpler! Gradio automatically recognizes the format of the returned data (e.g. does the user's function return a `numpy` array or a `str` filepath for the `gr.Image` component?) and postprocesses it appropriately into a format that can be displayed by the browser.
+
+So in the image above, the following postprocessing steps happen to send the data returned from a user's function to the browser:
+
+* The `float` is displayed as a number and displayed directly to the user
+* The list of string filepaths (`list[str]`) is interpreted as a list of image filepaths and displayed as a gallery in the browser
+
+Take a look at the [Docs](https://gradio.app/docs) to see all the parameters for each Gradio component.
+
+## Queuing
+
+Every Gradio app comes with a built-in queuing system that can scale to thousands of concurrent users. You can configure the queue by using `queue()` method which is supported by the `gr.Interface`, `gr.Blocks`, and `gr.ChatInterface` classes.
+
+For example, you can control the number of requests processed at a single time by setting the `default_concurrency_limit` parameter of `queue()`, e.g.
+
+```python
+demo = gr.Interface(...).queue(default_concurrency_limit=5)
+demo.launch()
+```
+
+This limits the number of requests processed for this event listener at a single time to 5. By default, the `default_concurrency_limit` is actually set to `1`, which means that when many users are using your app, only a single user's request will be processed at a time. This is because many machine learning functions consume a significant amount of memory and so it is only suitable to have a single user using the demo at a time. However, you can change this parameter in your demo easily.
+
+See the [docs on queueing](/docs/interface#interface-queue) for more details on configuring the queuing parameters.
+
+## Streaming outputs
+
+In some cases, you may want to stream a sequence of outputs rather than show a single output at once. For example, you might have an image generation model and you want to show the image that is generated at each step, leading up to the final image. Or you might have a chatbot which streams its response one token at a time instead of returning it all at once.
+
+In such cases, you can supply a **generator** function into Gradio instead of a regular function. Creating generators in Python is very simple: instead of a single `return` value, a function should `yield` a series of values instead. Usually the `yield` statement is put in some kind of loop. Here's an example of an generator that simply counts up to a given number:
+
+```python
+def my_generator(x):
+ for i in range(x):
+ yield i
+```
+
+You supply a generator into Gradio the same way as you would a regular function. For example, here's a a (fake) image generation model that generates noise for several steps before outputting an image using the `gr.Interface` class:
+
+$code_fake_diffusion
+$demo_fake_diffusion
+
+Note that we've added a `time.sleep(1)` in the iterator to create an artificial pause between steps so that you are able to observe the steps of the iterator (in a real image generation model, this probably wouldn't be necessary).
+
+## Streaming inputs
+
+Similarly, Gradio can handle streaming inputs, e.g. a live audio stream that can gets transcribed to text in real time, or an image generation model that reruns every time a user types a letter in a textbox. This is covered in more details in our guide on building [reactive Interfaces](/guides/reactive-interfaces).
+
+## Alert modals
+
+You may wish to raise alerts to the user. To do so, raise a `gr.Error("custom message")` to display an error message. You can also issue `gr.Warning("message")` and `gr.Info("message")` by having them as standalone lines in your function, which will immediately display modals while continuing the execution of your function. Queueing needs to be enabled for this to work.
+
+Note below how the `gr.Error` has to be raised, while the `gr.Warning` and `gr.Info` are single lines.
+
+```python
+def start_process(name):
+ gr.Info("Starting process")
+ if name is None:
+ gr.Warning("Name is empty")
+ ...
+ if success == False:
+ raise gr.Error("Process failed")
+```
+
+
+
+## Styling
+
+Gradio themes are the easiest way to customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Interface` constructor. For example:
+
+```python
+demo = gr.Interface(..., theme=gr.themes.Monochrome())
+```
+
+Gradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. You can extend these themes or create your own themes from scratch - see the [theming guide](https://gradio.app/guides/theming-guide) for more details.
+
+For additional styling ability, you can pass any CSS (as well as custom JavaScript) to your Gradio application. This is discussed in more detail in our [custom JS and CSS guide](/guides/custom-CSS-and-JS).
+
+
+## Progress bars
+
+Gradio supports the ability to create custom Progress Bars so that you have customizability and control over the progress update that you show to the user. In order to enable this, simply add an argument to your method that has a default value of a `gr.Progress` instance. Then you can update the progress levels by calling this instance directly with a float between 0 and 1, or using the `tqdm()` method of the `Progress` instance to track progress over an iterable, as shown below.
+
+$code_progress_simple
+$demo_progress_simple
+
+If you use the `tqdm` library, you can even report progress updates automatically from any `tqdm.tqdm` that already exists within your function by setting the default argument as `gr.Progress(track_tqdm=True)`!
+
+## Batch functions
+
+Gradio supports the ability to pass _batch_ functions. Batch functions are just
+functions which take in a list of inputs and return a list of predictions.
+
+For example, here is a batched function that takes in two lists of inputs (a list of
+words and a list of ints), and returns a list of trimmed words as output:
+
+```py
+import time
+
+def trim_words(words, lens):
+ trimmed_words = []
+ time.sleep(5)
+ for w, l in zip(words, lens):
+ trimmed_words.append(w[:int(l)])
+ return [trimmed_words]
+```
+
+The advantage of using batched functions is that if you enable queuing, the Gradio server can automatically _batch_ incoming requests and process them in parallel,
+potentially speeding up your demo. Here's what the Gradio code looks like (notice the `batch=True` and `max_batch_size=16`)
+
+With the `gr.Interface` class:
+
+```python
+demo = gr.Interface(
+ fn=trim_words,
+ inputs=["textbox", "number"],
+ outputs=["output"],
+ batch=True,
+ max_batch_size=16
+)
+
+demo.launch()
+```
+
+With the `gr.Blocks` class:
+
+```py
+import gradio as gr
+
+with gr.Blocks() as demo:
+ with gr.Row():
+ word = gr.Textbox(label="word")
+ leng = gr.Number(label="leng")
+ output = gr.Textbox(label="Output")
+ with gr.Row():
+ run = gr.Button()
+
+ event = run.click(trim_words, [word, leng], output, batch=True, max_batch_size=16)
+
+demo.launch()
+```
+
+In the example above, 16 requests could be processed in parallel (for a total inference time of 5 seconds), instead of each request being processed separately (for a total
+inference time of 80 seconds). Many Hugging Face `transformers` and `diffusers` models work very naturally with Gradio's batch mode: here's [an example demo using diffusers to
+generate images in batches](https://github.com/gradio-app/gradio/blob/main/demo/diffusers_with_batching/run.py)
+
+
diff --git a/guides/01_getting-started/03_sharing-your-app.md b/guides/01_getting-started/03_sharing-your-app.md
new file mode 100644
index 0000000000000000000000000000000000000000..4e8003e793cf13d8dfba57eda695912d41b73021
--- /dev/null
+++ b/guides/01_getting-started/03_sharing-your-app.md
@@ -0,0 +1,299 @@
+# Sharing Your App
+
+How to share your Gradio app:
+
+1. [Sharing demos with the share parameter](#sharing-demos)
+2. [Hosting on HF Spaces](#hosting-on-hf-spaces)
+3. [Embedding hosted spaces](#embedding-hosted-spaces)
+4. [Using the API page](#api-page)
+5. [Authentication](#authentication)
+6. [Accessing network requests](#accessing-the-network-request-directly)
+7. [Mounting within FastAPI](#mounting-within-another-fast-api-app)
+8. [Security and file access](#security-and-file-access)
+
+## Sharing Demos
+
+Gradio demos can be easily shared publicly by setting `share=True` in the `launch()` method. Like this:
+
+```python
+import gradio as gr
+
+def greet(name):
+ return "Hello " + name + "!"
+
+demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
+
+demo.launch(share=True) # Share your demo with just 1 extra parameter 🚀
+```
+
+This generates a public, shareable link that you can send to anybody! When you send this link, the user on the other side can try out the model in their browser. Because the processing happens on your device (as long as your device stays on), you don't have to worry about any packaging any dependencies.
+
+![sharing](https://github.com/gradio-app/gradio/blob/main/guides/assets/sharing.svg?raw=true)
+
+
+A share link usually looks something like this: **https://07ff8706ab.gradio.live**. Although the link is served through the Gradio Share Servers, these servers are only a proxy for your local server, and do not store any data sent through your app. Share links expire after 72 hours. (it is [also possible to set up your own Share Server](https://github.com/huggingface/frp/) on your own cloud server to overcome this restriction.)
+
+Tip: Keep in mind that share links are publicly accessible, meaning that anyone can use your model for prediction! Therefore, make sure not to expose any sensitive information through the functions you write, or allow any critical changes to occur on your device. Or you can [add authentication to your Gradio app](#authentication) as discussed below.
+
+Note that by default, `share=False`, which means that your server is only running locally. (This is the default, except in Google Colab notebooks, where share links are automatically created). As an alternative to using share links, you can use use [SSH port-forwarding](https://www.ssh.com/ssh/tunneling/example) to share your local server with specific users.
+
+
+## Hosting on HF Spaces
+
+If you'd like to have a permanent link to your Gradio demo on the internet, use Hugging Face Spaces. [Hugging Face Spaces](http://huggingface.co/spaces/) provides the infrastructure to permanently host your machine learning model for free!
+
+After you have [created a free Hugging Face account](https://huggingface.co/join), you have two methods to deploy your Gradio app to Hugging Face Spaces:
+
+1. From terminal: run `gradio deploy` in your app directory. The CLI will gather some basic metadata and then launch your app. To update your space, you can re-run this command or enable the Github Actions option to automatically update the Spaces on `git push`.
+
+2. From your browser: Drag and drop a folder containing your Gradio model and all related files [here](https://huggingface.co/new-space). See [this guide how to host on Hugging Face Spaces](https://huggingface.co/blog/gradio-spaces) for more information, or watch the embedded video:
+
+
+
+
+
+
+## Embedding Hosted Spaces
+
+Once you have hosted your app on Hugging Face Spaces (or on your own server), you may want to embed the demo on a different website, such as your blog or your portfolio. Embedding an interactive demo allows people to try out the machine learning model that you have built, without needing to download or install anything — right in their browser! The best part is that you can embed interactive demos even in static websites, such as GitHub pages.
+
+There are two ways to embed your Gradio demos. You can find quick links to both options directly on the Hugging Face Space page, in the "Embed this Space" dropdown option:
+
+![Embed this Space dropdown option](https://github.com/gradio-app/gradio/blob/main/guides/assets/embed_this_space.png?raw=true)
+
+### Embedding with Web Components
+
+Web components typically offer a better experience to users than IFrames. Web components load lazily, meaning that they won't slow down the loading time of your website, and they automatically adjust their height based on the size of the Gradio app.
+
+To embed with Web Components:
+
+1. Import the gradio JS library into into your site by adding the script below in your site (replace {GRADIO_VERSION} in the URL with the library version of Gradio you are using).
+
+```html
+
+```
+
+2. Add
+
+```html
+
+```
+
+element where you want to place the app. Set the `src=` attribute to your Space's embed URL, which you can find in the "Embed this Space" button. For example:
+
+```html
+
+```
+
+
+
+You can see examples of how web components look on the Gradio landing page .
+
+You can also customize the appearance and behavior of your web component with attributes that you pass into the `` tag:
+
+- `src`: as we've seen, the `src` attributes links to the URL of the hosted Gradio demo that you would like to embed
+- `space`: an optional shorthand if your Gradio demo is hosted on Hugging Face Space. Accepts a `username/space_name` instead of a full URL. Example: `gradio/Echocardiogram-Segmentation`. If this attribute attribute is provided, then `src` does not need to be provided.
+- `control_page_title`: a boolean designating whether the html title of the page should be set to the title of the Gradio app (by default `"false"`)
+- `initial_height`: the initial height of the web component while it is loading the Gradio app, (by default `"300px"`). Note that the final height is set based on the size of the Gradio app.
+- `container`: whether to show the border frame and information about where the Space is hosted (by default `"true"`)
+- `info`: whether to show just the information about where the Space is hosted underneath the embedded app (by default `"true"`)
+- `autoscroll`: whether to autoscroll to the output when prediction has finished (by default `"false"`)
+- `eager`: whether to load the Gradio app as soon as the page loads (by default `"false"`)
+- `theme_mode`: whether to use the `dark`, `light`, or default `system` theme mode (by default `"system"`)
+- `render`: an event that is triggered once the embedded space has finished rendering.
+
+Here's an example of how to use these attributes to create a Gradio app that does not lazy load and has an initial height of 0px.
+
+```html
+
+```
+
+Here's another example of how to use the `render` event. An event listener is used to capture the `render` event and will call the `handleLoadComplete()` function once rendering is complete.
+
+```html
+
+```
+
+_Note: While Gradio's CSS will never impact the embedding page, the embedding page can affect the style of the embedded Gradio app. Make sure that any CSS in the parent page isn't so general that it could also apply to the embedded Gradio app and cause the styling to break. Element selectors such as `header { ... }` and `footer { ... }` will be the most likely to cause issues._
+
+### Embedding with IFrames
+
+To embed with IFrames instead (if you cannot add javascript to your website, for example), add this element:
+
+```html
+
+```
+
+Again, you can find the `src=` attribute to your Space's embed URL, which you can find in the "Embed this Space" button.
+
+Note: if you use IFrames, you'll probably want to add a fixed `height` attribute and set `style="border:0;"` to remove the boreder. In addition, if your app requires permissions such as access to the webcam or the microphone, you'll need to provide that as well using the `allow` attribute.
+
+## API Page
+
+You can use almost any Gradio app as an API! In the footer of a Gradio app [like this one](https://huggingface.co/spaces/gradio/hello_world), you'll see a "Use via API" link.
+
+![Use via API](https://github.com/gradio-app/gradio/blob/main/guides/assets/use_via_api.png?raw=true)
+
+This is a page that lists the endpoints that can be used to query the Gradio app, via our supported clients: either [the Python client](https://gradio.app/guides/getting-started-with-the-python-client/), or [the JavaScript client](https://gradio.app/guides/getting-started-with-the-js-client/). For each endpoint, Gradio automatically generates the parameters and their types, as well as example inputs.
+
+The endpoints are automatically created when you launch a Gradio `Interface`. If you are using Gradio `Blocks`, you can also set up a Gradio API page, though we recommend that you explicitly name each event listener, such as
+
+```python
+btn.click(add, [num1, num2], output, api_name="addition")
+```
+
+This will add and document the endpoint `/api/addition/` to the automatically generated API page. Otherwise, your API endpoints will appear as "unnamed" endpoints.
+
+
+## Authentication
+
+### Password-protected app
+
+You may wish to put an authentication page in front of your app to limit who can open your app. With the `auth=` keyword argument in the `launch()` method, you can provide a tuple with a username and password, or a list of acceptable username/password tuples; Here's an example that provides password-based authentication for a single user named "admin":
+
+```python
+demo.launch(auth=("admin", "pass1234"))
+```
+
+For more complex authentication handling, you can even pass a function that takes a username and password as arguments, and returns True to allow authentication, False otherwise. This can be used for, among other things, making requests to 3rd-party authentication services.
+
+Here's an example of a function that accepts any login where the username and password are the same:
+
+```python
+def same_auth(username, password):
+ return username == password
+demo.launch(auth=same_auth)
+```
+
+For authentication to work properly, third party cookies must be enabled in your browser.
+This is not the case by default for Safari, Chrome Incognito Mode.
+
+### OAuth (Login via Hugging Face)
+
+Gradio supports OAuth login via Hugging Face. This feature is currently **experimental** and only available on Spaces.
+It allows you to add a _"Sign in with Hugging Face"_ button to your demo. Check out [this Space](https://huggingface.co/spaces/Wauplin/gradio-oauth-demo) for a live demo.
+
+To enable OAuth, you must set `hf_oauth: true` as a Space metadata in your README.md file. This will register your Space
+as an OAuth application on Hugging Face. Next, you can use `gr.LoginButton` and `gr.LogoutButton` to add login and logout buttons to
+your Gradio app. Once a user is logged in with their HF account, you can retrieve their profile by adding a parameter of type
+`gr.OAuthProfile` to any Gradio function. The user profile will be automatically injected as a parameter value. If you want
+to perform actions on behalf of the user (e.g. list user's private repos, create repo, etc.), you can retrieve the user
+token by adding a parameter of type `gr.OAuthToken`. You must define which scopes you will use in your Space metadata
+(see [documentation](https://huggingface.co/docs/hub/spaces-oauth#scopes) for more details).
+
+Here is a short example:
+
+```py
+import gradio as gr
+
+
+def hello(profile: gr.OAuthProfile | None) -> str:
+ if profile is None:
+ return "I don't know you."
+ return f"Hello {profile.name}"
+
+def list_organizations(oauth_token: gr.OAuthToken | None) -> str:
+ if oauth_token is None:
+ return "Please log in to list organizations."
+ org_names = [org["name"] for org in whoami(oauth_token.token)["orgs"]]
+ return f"You belong to {', '.join(org_names)}."
+
+with gr.Blocks() as demo:
+ gr.LoginButton()
+ gr.LogoutButton()
+ m1 = gr.Markdown()
+ m2 = gr.Markdown()
+ demo.load(hello, inputs=None, outputs=m1)
+ demo.load(list_organizations, inputs=None, outputs=m2)
+```
+
+When the user clicks on the login button, they get redirected in a new page to authorize your Space.
+
+
+
+
+
+Users can revoke access to their profile at any time in their [settings](https://huggingface.co/settings/connected-applications).
+
+As seen above, OAuth features are available only when your app runs in a Space. However, you often need to test your app
+locally before deploying it. To help with that, the `gr.LoginButton` is mocked. When a user clicks on it, they are
+automatically logged in with a fake user profile. This allows you to debug your app before deploying it to a Space.
+
+## Accessing the Network Request Directly
+
+When a user makes a prediction to your app, you may need the underlying network request, in order to get the request headers (e.g. for advanced authentication), log the client's IP address, getting the query parameters, or for other reasons. Gradio supports this in a similar manner to FastAPI: simply add a function parameter whose type hint is `gr.Request` and Gradio will pass in the network request as that parameter. Here is an example:
+
+```python
+import gradio as gr
+
+def echo(text, request: gr.Request):
+ if request:
+ print("Request headers dictionary:", request.headers)
+ print("IP address:", request.client.host)
+ print("Query parameters:", dict(request.query_params))
+ return text
+
+io = gr.Interface(echo, "textbox", "textbox").launch()
+```
+
+Note: if your function is called directly instead of through the UI (this happens, for
+example, when examples are cached, or when the Gradio app is called via API), then `request` will be `None`.
+You should handle this case explicitly to ensure that your app does not throw any errors. That is why
+we have the explicit check `if request`.
+
+## Mounting Within Another FastAPI App
+
+In some cases, you might have an existing FastAPI app, and you'd like to add a path for a Gradio demo.
+You can easily do this with `gradio.mount_gradio_app()`.
+
+Here's a complete example:
+
+$code_custom_path
+
+Note that this approach also allows you run your Gradio apps on custom paths (`http://localhost:8000/gradio` in the example above).
+
+
+## Security and File Access
+
+Sharing your Gradio app with others (by hosting it on Spaces, on your own server, or through temporary share links) **exposes** certain files on the host machine to users of your Gradio app.
+
+In particular, Gradio apps ALLOW users to access to three kinds of files:
+
+- **Temporary files created by Gradio.** These are files that are created by Gradio as part of running your prediction function. For example, if your prediction function returns a video file, then Gradio will save that video to a temporary cache on your device and then send the path to the file to the front end. You can customize the location of temporary cache files created by Gradio by setting the environment variable `GRADIO_TEMP_DIR` to an absolute path, such as `/home/usr/scripts/project/temp/`.
+
+
+- **Cached examples created by Gradio.** These are files that are created by Gradio as part of caching examples for faster runtimes, if you set `cache_examples=True` in `gr.Interface()` or in `gr.Examples()`. By default, these files are saved in the `gradio_cached_examples/` subdirectory within your app's working directory. You can customize the location of cached example files created by Gradio by setting the environment variable `GRADIO_EXAMPLES_CACHE` to an absolute path or a path relative to your working directory.
+
+- **Files that you explicitly allow via the `allowed_paths` parameter in `launch()`**. This parameter allows you to pass in a list of additional directories or exact filepaths you'd like to allow users to have access to. (By default, this parameter is an empty list).
+
+Gradio DOES NOT ALLOW access to:
+
+- **Files that you explicitly block via the `blocked_paths` parameter in `launch()`**. You can pass in a list of additional directories or exact filepaths to the `blocked_paths` parameter in `launch()`. This parameter takes precedence over the files that Gradio exposes by default or by the `allowed_paths`.
+
+- **Any other paths on the host machine**. Users should NOT be able to access other arbitrary paths on the host.
+
+Please make sure you are running the latest version of `gradio` for these security settings to apply.
diff --git a/guides/02_building-interfaces/00_the-interface-class.md b/guides/02_building-interfaces/00_the-interface-class.md
new file mode 100644
index 0000000000000000000000000000000000000000..c46eb9c69c939e0c51b9109da0c08be3ff8c696a
--- /dev/null
+++ b/guides/02_building-interfaces/00_the-interface-class.md
@@ -0,0 +1,142 @@
+# The `Interface` class
+
+As mentioned in the [Quickstart](/main/guides/quickstart), the `gr.Interface` class is a high-level abstraction in Gradio that allows you to quickly create a demo for any Python function simply by specifying the input types and the output types. Revisiting our first demo:
+
+$code_hello_world_4
+
+
+We see that the `Interface` class is initialized with three required parameters:
+
+- `fn`: the function to wrap a user interface (UI) around
+- `inputs`: which Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.
+- `outputs`: which Gradio component(s) to use for the output. The number of components should match the number of return values from your function.
+
+Let's take a closer look at these components used to provide input and output.
+
+## Components Attributes
+
+We used the default versions of the `gr.Textbox` and `gr.Slider`, but what if you want to change how the UI components look or behave?
+
+Let's say you want to customize the slider to have values from 1 to 10, with a default of 2. And you wanted to customize the output text field — you want it to be larger and have a label.
+
+If you use the actual class for `gr.Textbox` and `gr.Slider` instead of using the string shortcut, you have access to much more customizability through component attributes.
+
+$code_hello_world_2
+$demo_hello_world_2
+
+## Multiple Input and Output Components
+
+Suppose you had a more complex function, with multiple outputs as well. In the example below, we define a function that takes a string, boolean, and number, and returns a string and number.
+
+$code_hello_world_3
+$demo_hello_world_3
+
+Just as each component in the `inputs` list corresponds to one of the parameters of the function, in order, each component in the `outputs` list corresponds to one of the values returned by the function, in order.
+
+## An Image Example
+
+Gradio supports many types of components, such as `Image`, `DataFrame`, `Video`, or `Label`. Let's try an image-to-image function to get a feel for these!
+
+$code_sepia_filter
+$demo_sepia_filter
+
+When using the `Image` component as input, your function will receive a NumPy array with the shape `(height, width, 3)`, where the last dimension represents the RGB values. We'll return an image as well in the form of a NumPy array.
+
+You can also set the datatype used by the component with the `type=` keyword argument. For example, if you wanted your function to take a file path to an image instead of a NumPy array, the input `Image` component could be written as:
+
+```python
+gr.Image(type="filepath", shape=...)
+```
+
+Also note that our input `Image` component comes with an edit button 🖉, which allows for cropping and zooming into images. Manipulating images in this way can help reveal biases or hidden flaws in a machine learning model!
+
+You can read more about the many components and how to use them in the [Gradio docs](https://gradio.app/docs).
+
+## Example Inputs
+
+You can provide example data that a user can easily load into `Interface`. This can be helpful to demonstrate the types of inputs the model expects, as well as to provide a way to explore your dataset in conjunction with your model. To load example data, you can provide a **nested list** to the `examples=` keyword argument of the Interface constructor. Each sublist within the outer list represents a data sample, and each element within the sublist represents an input for each input component. The format of example data for each component is specified in the [Docs](https://gradio.app/docs#components).
+
+$code_calculator
+$demo_calculator
+
+You can load a large dataset into the examples to browse and interact with the dataset through Gradio. The examples will be automatically paginated (you can configure this through the `examples_per_page` argument of `Interface`).
+
+Continue learning about examples in the [More On Examples](https://gradio.app/guides/more-on-examples) guide.
+
+## Descriptive Content
+
+In the previous example, you may have noticed the `title=` and `description=` keyword arguments in the `Interface` constructor that helps users understand your app.
+
+There are three arguments in the `Interface` constructor to specify where this content should go:
+
+- `title`: which accepts text and can display it at the very top of interface, and also becomes the page title.
+- `description`: which accepts text, markdown or HTML and places it right under the title.
+- `article`: which also accepts text, markdown or HTML and places it below the interface.
+
+![annotated](https://github.com/gradio-app/gradio/blob/main/guides/assets/annotated.png?raw=true)
+
+If you're using the `Blocks` API instead, you can insert text, markdown, or HTML anywhere using the `gr.Markdown(...)` or `gr.HTML(...)` components, with descriptive content inside the `Component` constructor.
+
+Another useful keyword argument is `label=`, which is present in every `Component`. This modifies the label text at the top of each `Component`. You can also add the `info=` keyword argument to form elements like `Textbox` or `Radio` to provide further information on their usage.
+
+```python
+gr.Number(label='Age', info='In years, must be greater than 0')
+```
+
+## Additional Inputs within an Accordion
+
+If your prediction function takes many inputs, you may want to hide some of them within a collapsed accordion to avoid cluttering the UI. The `Interface` class takes an `additional_inputs` argument which is similar to `inputs` but any input components included here are not visible by default. The user must click on the accordion to show these components. The additional inputs are passed into the prediction function, in order, after the standard inputs.
+
+You can customize the appearance of the accordion by using the optional `additional_inputs_accordion` argument, which accepts a string (in which case, it becomes the label of the accordion), or an instance of the `gr.Accordion()` class (e.g. this lets you control whether the accordion is open or closed by default).
+
+Here's an example:
+
+$code_interface_with_additional_inputs
+$demo_interface_with_additional_inputs
+
+
+## Flagging
+
+By default, an `Interface` will have "Flag" button. When a user testing your `Interface` sees input with interesting output, such as erroneous or unexpected model behaviour, they can flag the input for you to review. Within the directory provided by the `flagging_dir=` argument to the `Interface` constructor, a CSV file will log the flagged inputs. If the interface involves file data, such as for Image and Audio components, folders will be created to store those flagged data as well.
+
+For example, with the calculator interface shown above, we would have the flagged data stored in the flagged directory shown below:
+
+```directory
++-- calculator.py
++-- flagged/
+| +-- logs.csv
+```
+
+_flagged/logs.csv_
+
+```csv
+num1,operation,num2,Output
+5,add,7,12
+6,subtract,1.5,4.5
+```
+
+With the sepia interface shown earlier, we would have the flagged data stored in the flagged directory shown below:
+
+```directory
++-- sepia.py
++-- flagged/
+| +-- logs.csv
+| +-- im/
+| | +-- 0.png
+| | +-- 1.png
+| +-- Output/
+| | +-- 0.png
+| | +-- 1.png
+```
+
+_flagged/logs.csv_
+
+```csv
+im,Output
+im/0.png,Output/0.png
+im/1.png,Output/1.png
+```
+
+If you wish for the user to provide a reason for flagging, you can pass a list of strings to the `flagging_options` argument of Interface. Users will have to select one of the strings when flagging, which will be saved as an additional column to the CSV.
+
+
diff --git a/guides/02_building-interfaces/01_more-on-examples.md b/guides/02_building-interfaces/01_more-on-examples.md
new file mode 100644
index 0000000000000000000000000000000000000000..909cb05c255e588a32c3e9ef0caa406647aa31ad
--- /dev/null
+++ b/guides/02_building-interfaces/01_more-on-examples.md
@@ -0,0 +1,41 @@
+# More on Examples
+
+In the [previous Guide](/main/guides/the-interface-class), we discussed how to provide example inputs for your demo to make it easier for users to try it out. Here, we dive into more details.
+
+## Providing Examples
+
+As covered in the [Key Features](/guides/key-features/#example-inputs) guide, adding examples to an Interface is as easy as providing a list of lists to the `examples`
+keyword argument.
+Each sublist is a data sample, where each element corresponds to an input of the prediction function.
+The inputs must be ordered in the same order as the prediction function expects them.
+
+If your interface only has one input component, then you can provide your examples as a regular list instead of a list of lists.
+
+### Loading Examples from a Directory
+
+You can also specify a path to a directory containing your examples. If your Interface takes only a single file-type input, e.g. an image classifier, you can simply pass a directory filepath to the `examples=` argument, and the `Interface` will load the images in the directory as examples.
+In the case of multiple inputs, this directory must
+contain a log.csv file with the example values.
+In the context of the calculator demo, we can set `examples='/demo/calculator/examples'` and in that directory we include the following `log.csv` file:
+
+```csv
+num,operation,num2
+5,"add",3
+4,"divide",2
+5,"multiply",3
+```
+
+This can be helpful when browsing flagged data. Simply point to the flagged directory and the `Interface` will load the examples from the flagged data.
+
+### Providing Partial Examples
+
+Sometimes your app has many input components, but you would only like to provide examples for a subset of them. In order to exclude some inputs from the examples, pass `None` for all data samples corresponding to those particular components.
+
+## Caching examples
+
+You may wish to provide some cached examples of your model for users to quickly try out, in case your model takes a while to run normally.
+If `cache_examples=True`, the `Interface` will run all of your examples through your app and save the outputs when you call the `launch()` method. This data will be saved in a directory called `gradio_cached_examples` in your working directory by default. You can also set this directory with the `GRADIO_EXAMPLES_CACHE` environment variable, which can be either an absolute path or a relative path to your working directory.
+
+Whenever a user clicks on an example, the output will automatically be populated in the app now, using data from this cached directory instead of actually running the function. This is useful so users can quickly try out your model without adding any load!
+
+Keep in mind once the cache is generated, it will not be updated in future launches. If the examples or function logic change, delete the cache folder to clear the cache and rebuild it with another `launch()`.
diff --git a/guides/02_building-interfaces/02_four-kinds-of-interfaces.md b/guides/02_building-interfaces/02_four-kinds-of-interfaces.md
new file mode 100644
index 0000000000000000000000000000000000000000..36ad6e99eb716c285ba253dc8ae38632e2fa7e72
--- /dev/null
+++ b/guides/02_building-interfaces/02_four-kinds-of-interfaces.md
@@ -0,0 +1,44 @@
+# The 4 Kinds of Gradio Interfaces
+
+So far, we've always assumed that in order to build an Gradio demo, you need both inputs and outputs. But this isn't always the case for machine learning demos: for example, _unconditional image generation models_ don't take any input but produce an image as the output.
+
+It turns out that the `gradio.Interface` class can actually handle 4 different kinds of demos:
+
+1. **Standard demos**: which have both separate inputs and outputs (e.g. an image classifier or speech-to-text model)
+2. **Output-only demos**: which don't take any input but produce on output (e.g. an unconditional image generation model)
+3. **Input-only demos**: which don't produce any output but do take in some sort of input (e.g. a demo that saves images that you upload to a persistent external database)
+4. **Unified demos**: which have both input and output components, but the input and output components _are the same_. This means that the output produced overrides the input (e.g. a text autocomplete model)
+
+Depending on the kind of demo, the user interface (UI) looks slightly different:
+
+![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/interfaces4.png)
+
+Let's see how to build each kind of demo using the `Interface` class, along with examples:
+
+## Standard demos
+
+To create a demo that has both the input and the output components, you simply need to set the values of the `inputs` and `outputs` parameter in `Interface()`. Here's an example demo of a simple image filter:
+
+$code_sepia_filter
+$demo_sepia_filter
+
+## Output-only demos
+
+What about demos that only contain outputs? In order to build such a demo, you simply set the value of the `inputs` parameter in `Interface()` to `None`. Here's an example demo of a mock image generation model:
+
+$code_fake_gan_no_input
+$demo_fake_gan_no_input
+
+## Input-only demos
+
+Similarly, to create a demo that only contains inputs, set the value of `outputs` parameter in `Interface()` to be `None`. Here's an example demo that saves any uploaded image to disk:
+
+$code_save_file_no_output
+$demo_save_file_no_output
+
+## Unified demos
+
+A demo that has a single component as both the input and the output. It can simply be created by setting the values of the `inputs` and `outputs` parameter as the same component. Here's an example demo of a text generation model:
+
+$code_unified_demo_text_generation
+$demo_unified_demo_text_generation
diff --git a/guides/02_building-interfaces/03_interface-state.md b/guides/02_building-interfaces/03_interface-state.md
new file mode 100644
index 0000000000000000000000000000000000000000..52834a0febf3fd09b079b9426d4ef9b732446d82
--- /dev/null
+++ b/guides/02_building-interfaces/03_interface-state.md
@@ -0,0 +1,32 @@
+# Interface State
+
+So far, we've assumed that your demos are *stateless*: that they do not persist information beyond a single function call. What if you want to modify the behavior of your demo based on previous interactions with the demo? There are two approaches in Gradio: *global state* and *session state*.
+
+## Global State
+
+If the state is something that should be accessible to all function calls and all users, you can create a variable outside the function call and access it inside the function. For example, you may load a large model outside the function and use it inside the function so that every function call does not need to reload the model.
+
+$code_score_tracker
+
+In the code above, the `scores` array is shared between all users. If multiple users are accessing this demo, their scores will all be added to the same list, and the returned top 3 scores will be collected from this shared reference.
+
+## Session State
+
+Another type of data persistence Gradio supports is session state, where data persists across multiple submits within a page session. However, data is _not_ shared between different users of your model. To store data in a session state, you need to do three things:
+
+1. Pass in an extra parameter into your function, which represents the state of the interface.
+2. At the end of the function, return the updated value of the state as an extra return value.
+3. Add the `'state'` input and `'state'` output components when creating your `Interface`
+
+Here's a simple app to illustrate session state - this app simply stores users previous submissions and displays them back to the user:
+
+
+$code_interface_state
+$demo_interface_state
+
+
+Notice how the state persists across submits within each page, but if you load this demo in another tab (or refresh the page), the demos will not share chat history. Here, we could not store the submission history in a global variable, otherwise the submission history would then get jumbled between different users.
+
+The initial value of the `State` is `None` by default. If you pass a parameter to the `value` argument of `gr.State()`, it is used as the default value of the state instead.
+
+Note: the `Interface` class only supports a single session state variable (though it can be a list with multiple elements). For more complex use cases, you can use Blocks, [which supports multiple `State` variables](/guides/state-in-blocks/). Alternatively, if you are building a chatbot that maintains user state, consider using the `ChatInterface` abstraction, [which manages state automatically](/guides/creating-a-chatbot-fast).
diff --git a/guides/02_building-interfaces/04_reactive-interfaces.md b/guides/02_building-interfaces/04_reactive-interfaces.md
new file mode 100644
index 0000000000000000000000000000000000000000..4ebe47ca506e9232bd2e5e3cd7a4225cdde39da8
--- /dev/null
+++ b/guides/02_building-interfaces/04_reactive-interfaces.md
@@ -0,0 +1,28 @@
+# Reactive Interfaces
+
+Finally, we cover how to get Gradio demos to refresh automatically or continuously stream data.
+
+## Live Interfaces
+
+You can make interfaces automatically refresh by setting `live=True` in the interface. Now the interface will recalculate as soon as the user input changes.
+
+$code_calculator_live
+$demo_calculator_live
+
+Note there is no submit button, because the interface resubmits automatically on change.
+
+## Streaming Components
+
+Some components have a "streaming" mode, such as `Audio` component in microphone mode, or the `Image` component in webcam mode. Streaming means data is sent continuously to the backend and the `Interface` function is continuously being rerun.
+
+The difference between `gr.Audio(source='microphone')` and `gr.Audio(source='microphone', streaming=True)`, when both are used in `gr.Interface(live=True)`, is that the first `Component` will automatically submit data and run the `Interface` function when the user stops recording, whereas the second `Component` will continuously send data and run the `Interface` function _during_ recording.
+
+Here is example code of streaming images from the webcam.
+
+$code_stream_frames
+
+Streaming can also be done in an output component. A `gr.Audio(streaming=True)` output component can take a stream of audio data yielded piece-wise by a generator function and combines them into a single audio file.
+
+$code_stream_audio_out
+
+For a more detailed example, see our guide on performing [automatic speech recognition](/guides/real-time-speech-recognition) with Gradio.
diff --git a/guides/03_building-with-blocks/01_blocks-and-event-listeners.md b/guides/03_building-with-blocks/01_blocks-and-event-listeners.md
new file mode 100644
index 0000000000000000000000000000000000000000..1b83451c1debffb922f12074dc689c23b150f632
--- /dev/null
+++ b/guides/03_building-with-blocks/01_blocks-and-event-listeners.md
@@ -0,0 +1,200 @@
+# Blocks and Event Listeners
+
+We briefly descirbed the Blocks class in the [Quickstart](/main/guides/quickstart#custom-demos-with-gr-blocks) as a way to build custom demos. Let's dive deeper.
+
+
+## Blocks Structure
+
+Take a look at the demo below.
+
+$code_hello_blocks
+$demo_hello_blocks
+
+- First, note the `with gr.Blocks() as demo:` clause. The Blocks app code will be contained within this clause.
+- Next come the Components. These are the same Components used in `Interface`. However, instead of being passed to some constructor, Components are automatically added to the Blocks as they are created within the `with` clause.
+- Finally, the `click()` event listener. Event listeners define the data flow within the app. In the example above, the listener ties the two Textboxes together. The Textbox `name` acts as the input and Textbox `output` acts as the output to the `greet` method. This dataflow is triggered when the Button `greet_btn` is clicked. Like an Interface, an event listener can take multiple inputs or outputs.
+
+You can also attach event listeners using decorators - skip the `fn` argument and assign `inputs` and `outputs` directly:
+
+$code_hello_blocks_decorator
+
+## Event Listeners and Interactivity
+
+In the example above, you'll notice that you are able to edit Textbox `name`, but not Textbox `output`. This is because any Component that acts as an input to an event listener is made interactive. However, since Textbox `output` acts only as an output, Gradio determines that it should not be made interactive. You can override the default behavior and directly configure the interactivity of a Component with the boolean `interactive` keyword argument.
+
+```python
+output = gr.Textbox(label="Output", interactive=True)
+```
+
+_Note_: What happens if a Gradio component is neither an input nor an output? If a component is constructed with a default value, then it is presumed to be displaying content and is rendered non-interactive. Otherwise, it is rendered interactive. Again, this behavior can be overridden by specifying a value for the `interactive` argument.
+
+## Types of Event Listeners
+
+Take a look at the demo below:
+
+$code_blocks_hello
+$demo_blocks_hello
+
+Instead of being triggered by a click, the `welcome` function is triggered by typing in the Textbox `inp`. This is due to the `change()` event listener. Different Components support different event listeners. For example, the `Video` Component supports a `play()` event listener, triggered when a user presses play. See the [Docs](http://gradio.app/docs#components) for the event listeners for each Component.
+
+## Multiple Data Flows
+
+A Blocks app is not limited to a single data flow the way Interfaces are. Take a look at the demo below:
+
+$code_reversible_flow
+$demo_reversible_flow
+
+Note that `num1` can act as input to `num2`, and also vice-versa! As your apps get more complex, you will have many data flows connecting various Components.
+
+Here's an example of a "multi-step" demo, where the output of one model (a speech-to-text model) gets fed into the next model (a sentiment classifier).
+
+$code_blocks_speech_text_sentiment
+$demo_blocks_speech_text_sentiment
+
+## Function Input List vs Dict
+
+The event listeners you've seen so far have a single input component. If you'd like to have multiple input components pass data to the function, you have two options on how the function can accept input component values:
+
+1. as a list of arguments, or
+2. as a single dictionary of values, keyed by the component
+
+Let's see an example of each:
+$code_calculator_list_and_dict
+
+Both `add()` and `sub()` take `a` and `b` as inputs. However, the syntax is different between these listeners.
+
+1. To the `add_btn` listener, we pass the inputs as a list. The function `add()` takes each of these inputs as arguments. The value of `a` maps to the argument `num1`, and the value of `b` maps to the argument `num2`.
+2. To the `sub_btn` listener, we pass the inputs as a set (note the curly brackets!). The function `sub()` takes a single dictionary argument `data`, where the keys are the input components, and the values are the values of those components.
+
+It is a matter of preference which syntax you prefer! For functions with many input components, option 2 may be easier to manage.
+
+$demo_calculator_list_and_dict
+
+## Function Return List vs Dict
+
+Similarly, you may return values for multiple output components either as:
+
+1. a list of values, or
+2. a dictionary keyed by the component
+
+Let's first see an example of (1), where we set the values of two output components by returning two values:
+
+```python
+with gr.Blocks() as demo:
+ food_box = gr.Number(value=10, label="Food Count")
+ status_box = gr.Textbox()
+ def eat(food):
+ if food > 0:
+ return food - 1, "full"
+ else:
+ return 0, "hungry"
+ gr.Button("EAT").click(
+ fn=eat,
+ inputs=food_box,
+ outputs=[food_box, status_box]
+ )
+```
+
+Above, each return statement returns two values corresponding to `food_box` and `status_box`, respectively.
+
+Instead of returning a list of values corresponding to each output component in order, you can also return a dictionary, with the key corresponding to the output component and the value as the new value. This also allows you to skip updating some output components.
+
+```python
+with gr.Blocks() as demo:
+ food_box = gr.Number(value=10, label="Food Count")
+ status_box = gr.Textbox()
+ def eat(food):
+ if food > 0:
+ return {food_box: food - 1, status_box: "full"}
+ else:
+ return {status_box: "hungry"}
+ gr.Button("EAT").click(
+ fn=eat,
+ inputs=food_box,
+ outputs=[food_box, status_box]
+ )
+```
+
+Notice how when there is no food, we only update the `status_box` element. We skipped updating the `food_box` component.
+
+Dictionary returns are helpful when an event listener affects many components on return, or conditionally affects outputs and not others.
+
+Keep in mind that with dictionary returns, we still need to specify the possible outputs in the event listener.
+
+## Updating Component Configurations
+
+The return value of an event listener function is usually the updated value of the corresponding output Component. Sometimes we want to update the configuration of the Component as well, such as the visibility. In this case, we return a new Component, setting the properties we want to change.
+
+$code_blocks_essay_simple
+$demo_blocks_essay_simple
+
+See how we can configure the Textbox itself through a new `gr.Textbox()` method. The `value=` argument can still be used to update the value along with Component configuration. Any arguments we do not set will use their previous values.
+
+## Examples
+
+Just like with `gr.Interface`, you can also add examples for your functions when you are working with `gr.Blocks`. In this case, instantiate a `gr.Examples` similar to how you would instantiate any other component. The constructor of `gr.Examples` takes two required arguments:
+
+* `examples`: a nested list of examples, in which the outer list consists of examples and each inner list consists of an input corresponding to each input component
+* `inputs`: the component or list of components that should be populated when the examples are clicked
+
+You can also set `cache_examples=True` similar to `gr.Interface`, in which case two additional arguments must be provided:
+
+* `outputs`: the component or list of components corresponding to the output of the examples
+* `fn`: the function to run to generate the outputs corresponding to the examples
+
+Here's an example showing how to use `gr.Examples` in a `gr.Blocks` app:
+
+$code_calculator_blocks
+
+**Note**: In Gradio 4.0 or later, when you click on examples, not only does the value of the input component update to the example value, but the component's configuration also reverts to the properties with which you constructed the component. This ensures that the examples are compatible with the component even if its configuration has been changed.
+
+
+
+## Running Events Consecutively
+
+You can also run events consecutively by using the `then` method of an event listener. This will run an event after the previous event has finished running. This is useful for running events that update components in multiple steps.
+
+For example, in the chatbot example below, we first update the chatbot with the user message immediately, and then update the chatbot with the computer response after a simulated delay.
+
+$code_chatbot_consecutive
+$demo_chatbot_consecutive
+
+The `.then()` method of an event listener executes the subsequent event regardless of whether the previous event raised any errors. If you'd like to only run subsequent events if the previous event executed successfully, use the `.success()` method, which takes the same arguments as `.then()`.
+
+## Running Events Continuously
+
+You can run events on a fixed schedule using the `every` parameter of the event listener. This will run the event `every` number of seconds while the client connection is open. If the connection is closed, the event will stop running after the following iteration. Note that this does not take into account the runtime of the event itself. So a function with a 1 second runtime running with `every=5`, would actually run every 6 seconds. Also note that this parameter does not apply to the `js` function, only the Python function associated with the event listener.
+
+Here is an example of a sine curve that updates every second!
+
+$code_sine_curve
+$demo_sine_curve
+
+## Gathering Event Data
+
+You can gather specific data about an event by adding the associated event data class as a type hint to an argument in the event listener function.
+
+For example, event data for `.select()` can be type hinted by a `gradio.SelectData` argument. This event is triggered when a user selects some part of the triggering component, and the event data includes information about what the user specifically selected. If a user selected a specific word in a `Textbox`, a specific image in a `Gallery`, or a specific cell in a `DataFrame`, the event data argument would contain information about the specific selection.
+
+In the 2 player tic-tac-toe demo below, a user can select a cell in the `DataFrame` to make a move. The event data argument contains information about the specific cell that was selected. We can first check to see if the cell is empty, and then update the cell with the user's move.
+
+$code_tictactoe
+$demo_tictactoe
+
+## Binding Multiple Triggers to a Function
+
+Often times, you may want to bind multiple triggers to the same function. For example, you may want to allow a user to click a submit button, or press enter to submit a form. You can do this using the `gr.on` method and passing a list of triggers to the `trigger`.
+
+$code_on_listener_basic
+$demo_on_listener_basic
+
+You can use decorator syntax as well:
+
+$code_on_listener_decorator
+
+You can use `gr.on` to create "live" events by binding to the `change` event of components that implement it. If you do not specify any triggers, the function will automatically bind to all `change` event of all input components that include a `change` event (for example `gr.Textbox` has a `change` event whereas `gr.Button` does not).
+
+$code_on_listener_live
+$demo_on_listener_live
+
+You can follow `gr.on` with `.then`, just like any regular event listener. This handy method should save you from having to write a lot of repetitive code!
diff --git a/guides/03_building-with-blocks/02_controlling-layout.md b/guides/03_building-with-blocks/02_controlling-layout.md
new file mode 100644
index 0000000000000000000000000000000000000000..df78712f5bc5c9ec3ef7fb329a9faa158b0c46c2
--- /dev/null
+++ b/guides/03_building-with-blocks/02_controlling-layout.md
@@ -0,0 +1,137 @@
+# Controlling Layout
+
+By default, Components in Blocks are arranged vertically. Let's take a look at how we can rearrange Components. Under the hood, this layout structure uses the [flexbox model of web development](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox).
+
+## Rows
+
+Elements within a `with gr.Row` clause will all be displayed horizontally. For example, to display two Buttons side by side:
+
+```python
+with gr.Blocks() as demo:
+ with gr.Row():
+ btn1 = gr.Button("Button 1")
+ btn2 = gr.Button("Button 2")
+```
+
+To make every element in a Row have the same height, use the `equal_height` argument of the `style` method.
+
+```python
+with gr.Blocks() as demo:
+ with gr.Row(equal_height=True):
+ textbox = gr.Textbox()
+ btn2 = gr.Button("Button 2")
+```
+
+The widths of elements in a Row can be controlled via a combination of `scale` and `min_width` arguments that are present in every Component.
+
+- `scale` is an integer that defines how an element will take up space in a Row. If scale is set to `0`, and element will not expand to take up space. If scale is set to `1` or greater, the element well expand. Multiple elements in a row will expand proportional to their scale. Below, `btn1` will expand twice as much as `btn2`, while `btn0` will not expand at all:
+
+```python
+with gr.Blocks() as demo:
+ with gr.Row():
+ btn0 = gr.Button("Button 0", scale=0)
+ btn1 = gr.Button("Button 1", scale=1)
+ btn2 = gr.Button("Button 2", scale=2)
+```
+
+- `min_width` will set the minimum width the element will take. The Row will wrap if there isn't sufficient space to satisfy all `min_width` values.
+
+Learn more about Rows in the [docs](https://gradio.app/docs/row).
+
+## Columns and Nesting
+
+Components within a Column will be placed vertically atop each other. Since the vertical layout is the default layout for Blocks apps anyway, to be useful, Columns are usually nested within Rows. For example:
+
+$code_rows_and_columns
+$demo_rows_and_columns
+
+See how the first column has two Textboxes arranged vertically. The second column has an Image and Button arranged vertically. Notice how the relative widths of the two columns is set by the `scale` parameter. The column with twice the `scale` value takes up twice the width.
+
+Learn more about Columns in the [docs](https://gradio.app/docs/column).
+
+# Dimensions
+
+You can control the height and width of various components, where the parameters are available. These parameters accept either a number (interpreted as pixels) or a string. Using a string allows the direct application of any CSS unit to the encapsulating Block element, catering to more specific design requirements. When omitted, Gradio uses default dimensions suited for most use cases.
+
+Below is an example illustrating the use of viewport width (vw):
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ im = gr.ImageEditor(
+ width="50vw",
+ )
+
+demo.launch()
+```
+
+When using percentage values for dimensions, you may want to define a parent component with an absolute unit (e.g. `px` or `vw`). This approach ensures that child components with relative dimensions are sized appropriately:
+
+
+```python
+import gradio as gr
+
+css = """
+.container {
+ height: 100vh;
+}
+"""
+
+with gr.Blocks(css=css) as demo:
+ with gr.Column(elem_classes=["container"]):
+ name = gr.Chatbot(value=[["1", "2"]], height="70%")
+
+demo.launch()
+```
+
+In this example, the Column layout component is given a height of 100% of the viewport height (100vh), and the Chatbot component inside it takes up 70% of the Column's height.
+
+You can apply any valid CSS unit for these parameters. For a comprehensive list of CSS units, refer to [this guide](https://www.w3schools.com/cssref/css_units.php). We recommend you always consider responsiveness and test your interfaces on various screen sizes to ensure a consistent user experience.
+
+
+
+## Tabs and Accordions
+
+You can also create Tabs using the `with gr.Tab('tab_name'):` clause. Any component created inside of a `with gr.Tab('tab_name'):` context appears in that tab. Consecutive Tab clauses are grouped together so that a single tab can be selected at one time, and only the components within that Tab's context are shown.
+
+For example:
+
+$code_blocks_flipper
+$demo_blocks_flipper
+
+Also note the `gr.Accordion('label')` in this example. The Accordion is a layout that can be toggled open or closed. Like `Tabs`, it is a layout element that can selectively hide or show content. Any components that are defined inside of a `with gr.Accordion('label'):` will be hidden or shown when the accordion's toggle icon is clicked.
+
+Learn more about [Tabs](https://gradio.app/docs/tab) and [Accordions](https://gradio.app/docs/accordion) in the docs.
+
+## Visibility
+
+Both Components and Layout elements have a `visible` argument that can set initially and also updated. Setting `gr.Column(visible=...)` on a Column can be used to show or hide a set of Components.
+
+$code_blocks_form
+$demo_blocks_form
+
+## Variable Number of Outputs
+
+By adjusting the visibility of components in a dynamic way, it is possible to create
+demos with Gradio that support a _variable numbers of outputs_. Here's a very simple example
+where the number of output textboxes is controlled by an input slider:
+
+$code_variable_outputs
+$demo_variable_outputs
+
+## Defining and Rendering Components Separately
+
+In some cases, you might want to define components before you actually render them in your UI. For instance, you might want to show an examples section using `gr.Examples` above the corresponding `gr.Textbox` input. Since `gr.Examples` requires as a parameter the input component object, you will need to first define the input component, but then render it later, after you have defined the `gr.Examples` object.
+
+The solution to this is to define the `gr.Textbox` outside of the `gr.Blocks()` scope and use the component's `.render()` method wherever you'd like it placed in the UI.
+
+Here's a full code example:
+
+```python
+input_textbox = gr.Textbox()
+
+with gr.Blocks() as demo:
+ gr.Examples(["hello", "bonjour", "merhaba"], input_textbox)
+ input_textbox.render()
+```
diff --git a/guides/03_building-with-blocks/03_state-in-blocks.md b/guides/03_building-with-blocks/03_state-in-blocks.md
new file mode 100644
index 0000000000000000000000000000000000000000..62f7bbe6a4034c1673aa0d34c044d528b66966ef
--- /dev/null
+++ b/guides/03_building-with-blocks/03_state-in-blocks.md
@@ -0,0 +1,30 @@
+# State in Blocks
+
+We covered [State in Interfaces](https://gradio.app/interface-state), this guide takes a look at state in Blocks, which works mostly the same.
+
+## Global State
+
+Global state in Blocks works the same as in Interface. Any variable created outside a function call is a reference shared between all users.
+
+## Session State
+
+Gradio supports session **state**, where data persists across multiple submits within a page session, in Blocks apps as well. To reiterate, session data is _not_ shared between different users of your model. To store data in a session state, you need to do three things:
+
+1. Create a `gr.State()` object. If there is a default value to this stateful object, pass that into the constructor.
+2. In the event listener, put the `State` object as an input and output.
+3. In the event listener function, add the variable to the input parameters and the return value.
+
+Let's take a look at a game of hangman.
+
+$code_hangman
+$demo_hangman
+
+Let's see how we do each of the 3 steps listed above in this game:
+
+1. We store the used letters in `used_letters_var`. In the constructor of `State`, we set the initial value of this to `[]`, an empty list.
+2. In `btn.click()`, we have a reference to `used_letters_var` in both the inputs and outputs.
+3. In `guess_letter`, we pass the value of this `State` to `used_letters`, and then return an updated value of this `State` in the return statement.
+
+With more complex apps, you will likely have many State variables storing session state in a single Blocks app.
+
+Learn more about `State` in the [docs](https://gradio.app/docs/state).
diff --git a/guides/03_building-with-blocks/04_custom-CSS-and-JS.md b/guides/03_building-with-blocks/04_custom-CSS-and-JS.md
new file mode 100644
index 0000000000000000000000000000000000000000..1f31e50b63edc20dfd810853f1ee23706a7973e6
--- /dev/null
+++ b/guides/03_building-with-blocks/04_custom-CSS-and-JS.md
@@ -0,0 +1,122 @@
+# Customizing your demo with CSS and Javascript
+
+Gradio allows you to customize your demo in several ways. You can customize the layout of your demo, add custom HTML, and add custom theming as well. This tutorial will go beyond that and walk you through how to add custom CSS and JavaScript code to your demo in order to add custom styling, animations, custom UI functionality, analytics, and more.
+
+## Adding custom CSS to your demo
+
+Gradio themes are the easiest way to customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Blocks` constructor. For example:
+
+```python
+with gr.Blocks(theme=gr.themes.Glass()):
+ ...
+```
+
+Gradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. You can extend these themes or create your own themes from scratch - see the [Theming guide](/guides/theming-guide) for more details.
+
+For additional styling ability, you can pass any CSS to your app using the `css=` kwarg. You can either the filepath to a CSS file, or a string of CSS code.
+
+**Warning**: The use of query selectors in custom JS and CSS is _not_ guaranteed to work across Gradio versions as the Gradio HTML DOM may change. We recommend using query selectors sparingly.
+
+The base class for the Gradio app is `gradio-container`, so here's an example that changes the background color of the Gradio app:
+
+```python
+with gr.Blocks(css=".gradio-container {background-color: red}") as demo:
+ ...
+```
+
+If you'd like to reference external files in your css, preface the file path (which can be a relative or absolute path) with `"file="`, for example:
+
+```python
+with gr.Blocks(css=".gradio-container {background: url('file=clouds.jpg')}") as demo:
+ ...
+```
+
+Note: By default, files in the host machine are not accessible to users running the Gradio app. As a result, you should make sure that any referenced files (such as `clouds.jpg` here) are either URLs or allowed via the `allow_list` parameter in `launch()`. Read more in our [section on Security and File Access](/guides/sharing-your-app#security-and-file-access).
+
+
+## The `elem_id` and `elem_classes` Arguments
+
+You can `elem_id` to add an HTML element `id` to any component, and `elem_classes` to add a class or list of classes. This will allow you to select elements more easily with CSS. This approach is also more likely to be stable across Gradio versions as built-in class names or ids may change (however, as mentioned in the warning above, we cannot guarantee complete compatibility between Gradio versions if you use custom CSS as the DOM elements may themselves change).
+
+```python
+css = """
+#warning {background-color: #FFCCCB}
+.feedback textarea {font-size: 24px !important}
+"""
+
+with gr.Blocks(css=css) as demo:
+ box1 = gr.Textbox(value="Good Job", elem_classes="feedback")
+ box2 = gr.Textbox(value="Failure", elem_id="warning", elem_classes="feedback")
+```
+
+The CSS `#warning` ruleset will only target the second Textbox, while the `.feedback` ruleset will target both. Note that when targeting classes, you might need to put the `!important` selector to override the default Gradio styles.
+
+## Adding custom JavaScript to your demo
+
+There are 3 ways to add javascript code to your Gradio demo:
+
+1. You can add JavaScript code as a string or as a filepath to the `js` parameter of the `Blocks` or `Interface` initializer. This will run the JavaScript code when the demo is first loaded.
+
+Below is an example of adding custom js to show an animated welcome message when the demo first loads.
+
+$code_blocks_js_load
+$demo_blocks_js_load
+
+Note: You can also supply your custom js code as a file path. For example, if you have a file called `custom.js` in the same directory as your Python script, you can add it to your demo like so: `with gr.Blocks(js="custom.js") as demo:`. Same goes for `Interface` (ex: `gr.Interface(..., js="custom.js")`).
+
+2. When using `Blocks` and event listeners, events have a `js` argument that can take a JavaScript function as a string and treat it just like a Python event listener function. You can pass both a JavaScript function and a Python function (in which case the JavaScript function is run first) or only Javascript (and set the Python `fn` to `None`). Take a look at the code below:
+
+$code_blocks_js_methods
+$demo_blocks_js_methods
+
+3. Lastly, you can add JavaScript code to the `head` param of the `Blocks` initializer. This will add the code to the head of the HTML document. For example, you can add Google Analytics to your demo like so:
+
+
+```python
+head = f"""
+
+
+"""
+
+with gr.Blocks(head=head) as demo:
+ ...demo code...
+```
+
+The `head` parameter accepts any HTML tags you would normally insert into the `` of a page. For example, you can also include ` ` tags to `head`.
+
+Note that injecting custom HTML can affect browser behavior and compatibility (e.g. keyboard shortcuts). You should test your interface across different browsers and be mindful of how scripts may interact with browser defaults.
+Here's an example where pressing `Shift + s` triggers the `click` event of a specific `Button` component if the browser focus is _not_ on an input component (e.g. `Textbox` component):
+
+```python
+import gradio as gr
+
+shortcut_js = """
+
+"""
+
+with gr.Blocks(head=shortcut_js) as demo:
+ action_button = gr.Button(value="Name", elem_id="my_btn")
+ textbox = gr.Textbox()
+ action_button.click(lambda : "button pressed", None, textbox)
+
+demo.launch()
+```
diff --git a/guides/03_building-with-blocks/05_using-blocks-like-functions.md b/guides/03_building-with-blocks/05_using-blocks-like-functions.md
new file mode 100644
index 0000000000000000000000000000000000000000..a6ae89ad46dbca358c67e90d7faf86c302b4ea5a
--- /dev/null
+++ b/guides/03_building-with-blocks/05_using-blocks-like-functions.md
@@ -0,0 +1,90 @@
+# Using Gradio Blocks Like Functions
+
+Tags: TRANSLATION, HUB, SPACES
+
+**Prerequisite**: This Guide builds on the Blocks Introduction. Make sure to [read that guide first](https://gradio.app/blocks-and-event-listeners).
+
+## Introduction
+
+Did you know that apart from being a full-stack machine learning demo, a Gradio Blocks app is also a regular-old python function!?
+
+This means that if you have a gradio Blocks (or Interface) app called `demo`, you can use `demo` like you would any python function.
+
+So doing something like `output = demo("Hello", "friend")` will run the first event defined in `demo` on the inputs "Hello" and "friend" and store it
+in the variable `output`.
+
+If I put you to sleep 🥱, please bear with me! By using apps like functions, you can seamlessly compose Gradio apps.
+The following section will show how.
+
+## Treating Blocks like functions
+
+Let's say we have the following demo that translates english text to german text.
+
+$code_english_translator
+
+I already went ahead and hosted it in Hugging Face spaces at [gradio/english_translator](https://huggingface.co/spaces/gradio/english_translator).
+
+You can see the demo below as well:
+
+$demo_english_translator
+
+Now, let's say you have an app that generates english text, but you wanted to additionally generate german text.
+
+You could either:
+
+1. Copy the source code of my english-to-german translation and paste it in your app.
+
+2. Load my english-to-german translation in your app and treat it like a normal python function.
+
+Option 1 technically always works, but it often introduces unwanted complexity.
+
+Option 2 lets you borrow the functionality you want without tightly coupling our apps.
+
+All you have to do is call the `Blocks.load` class method in your source file.
+After that, you can use my translation app like a regular python function!
+
+The following code snippet and demo shows how to use `Blocks.load`.
+
+Note that the variable `english_translator` is my english to german app, but its used in `generate_text` like a regular function.
+
+$code_generate_english_german
+
+$demo_generate_english_german
+
+## How to control which function in the app to use
+
+If the app you are loading defines more than one function, you can specify which function to use
+with the `fn_index` and `api_name` parameters.
+
+In the code for our english to german demo, you'll see the following line:
+
+```python
+translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")
+```
+
+The `api_name` gives this function a unique name in our app. You can use this name to tell gradio which
+function in the upstream space you want to use:
+
+```python
+english_generator(text, api_name="translate-to-german")[0]["generated_text"]
+```
+
+You can also use the `fn_index` parameter.
+Imagine my app also defined an english to spanish translation function.
+In order to use it in our text generation app, we would use the following code:
+
+```python
+english_generator(text, fn_index=1)[0]["generated_text"]
+```
+
+Functions in gradio spaces are zero-indexed, so since the spanish translator would be the second function in my space,
+you would use index 1.
+
+## Parting Remarks
+
+We showed how treating a Blocks app like a regular python helps you compose functionality across different apps.
+Any Blocks app can be treated like a function, but a powerful pattern is to `load` an app hosted on
+[Hugging Face Spaces](https://huggingface.co/spaces) prior to treating it like a function in your own app.
+You can also load models hosted on the [Hugging Face Model Hub](https://huggingface.co/models) - see the [Using Hugging Face Integrations](/using_hugging_face_integrations) guide for an example.
+
+### Happy building! ⚒️
diff --git a/guides/04_chatbots/01_creating-a-chatbot-fast.md b/guides/04_chatbots/01_creating-a-chatbot-fast.md
new file mode 100644
index 0000000000000000000000000000000000000000..5dd0d15b60f4537ee035a44236f24fe235b995d3
--- /dev/null
+++ b/guides/04_chatbots/01_creating-a-chatbot-fast.md
@@ -0,0 +1,285 @@
+# How to Create a Chatbot with Gradio
+
+Tags: NLP, TEXT, CHAT
+
+## Introduction
+
+Chatbots are a popular application of large language models. Using `gradio`, you can easily build a demo of your chatbot model and share that with your users, or try it yourself using an intuitive chatbot UI.
+
+This tutorial uses `gr.ChatInterface()`, which is a high-level abstraction that allows you to create your chatbot UI fast, often with a single line of code. The chatbot interface that we create will look something like this:
+
+$demo_chatinterface_streaming_echo
+
+We'll start with a couple of simple examples, and then show how to use `gr.ChatInterface()` with real language models from several popular APIs and libraries, including `langchain`, `openai`, and Hugging Face.
+
+**Prerequisites**: please make sure you are using the **latest version** version of Gradio:
+
+```bash
+$ pip install --upgrade gradio
+```
+
+## Defining a chat function
+
+When working with `gr.ChatInterface()`, the first thing you should do is define your chat function. Your chat function should take two arguments: `message` and then `history` (the arguments can be named anything, but must be in this order).
+
+- `message`: a `str` representing the user's input.
+- `history`: a `list` of `list` representing the conversations up until that point. Each inner list consists of two `str` representing a pair: `[user input, bot response]`.
+
+Your function should return a single string response, which is the bot's response to the particular user input `message`. Your function can take into account the `history` of messages, as well as the current message.
+
+Let's take a look at a few examples.
+
+## Example: a chatbot that responds yes or no
+
+Let's write a chat function that responds `Yes` or `No` randomly.
+
+Here's our chat function:
+
+```python
+import random
+
+def random_response(message, history):
+ return random.choice(["Yes", "No"])
+```
+
+Now, we can plug this into `gr.ChatInterface()` and call the `.launch()` method to create the web interface:
+
+```python
+import gradio as gr
+
+gr.ChatInterface(random_response).launch()
+```
+
+That's it! Here's our running demo, try it out:
+
+$demo_chatinterface_random_response
+
+## Another example using the user's input and history
+
+Of course, the previous example was very simplistic, it didn't even take user input or the previous history into account! Here's another simple example showing how to incorporate a user's input as well as the history.
+
+```python
+import random
+import gradio as gr
+
+def alternatingly_agree(message, history):
+ if len(history) % 2 == 0:
+ return f"Yes, I do think that '{message}'"
+ else:
+ return "I don't think so"
+
+gr.ChatInterface(alternatingly_agree).launch()
+```
+
+## Streaming chatbots
+
+If in your chat function, you use `yield` to generate a sequence of responses, you'll end up with a streaming chatbot. It's that simple!
+
+```python
+import time
+import gradio as gr
+
+def slow_echo(message, history):
+ for i in range(len(message)):
+ time.sleep(0.3)
+ yield "You typed: " + message[: i+1]
+
+gr.ChatInterface(slow_echo).launch()
+```
+
+Notice that we've [enabled queuing](/guides/key-features#queuing), which is required to use generator functions. While the response is streaming, the "Submit" button turns into a "Stop" button that can be used to stop the generator function. You can customize the appearance and behavior of the "Stop" button using the `stop_btn` parameter.
+
+## Customizing your chatbot
+
+If you're familiar with Gradio's `Interface` class, the `gr.ChatInterface` includes many of the same arguments that you can use to customize the look and feel of your Chatbot. For example, you can:
+
+- add a title and description above your chatbot using `title` and `description` arguments.
+- add a theme or custom css using `theme` and `css` arguments respectively.
+- add `examples` and even enable `cache_examples`, which make it easier for users to try it out .
+- You can change the text or disable each of the buttons that appear in the chatbot interface: `submit_btn`, `retry_btn`, `undo_btn`, `clear_btn`.
+
+If you want to customize the `gr.Chatbot` or `gr.Textbox` that compose the `ChatInterface`, then you can pass in your own chatbot or textbox as well. Here's an example of how we can use these parameters:
+
+```python
+import gradio as gr
+
+def yes_man(message, history):
+ if message.endswith("?"):
+ return "Yes"
+ else:
+ return "Ask me anything!"
+
+gr.ChatInterface(
+ yes_man,
+ chatbot=gr.Chatbot(height=300),
+ textbox=gr.Textbox(placeholder="Ask me a yes or no question", container=False, scale=7),
+ title="Yes Man",
+ description="Ask Yes Man any question",
+ theme="soft",
+ examples=["Hello", "Am I cool?", "Are tomatoes vegetables?"],
+ cache_examples=True,
+ retry_btn=None,
+ undo_btn="Delete Previous",
+ clear_btn="Clear",
+).launch()
+```
+
+## Additional Inputs
+
+You may want to add additional parameters to your chatbot and expose them to your users through the Chatbot UI. For example, suppose you want to add a textbox for a system prompt, or a slider that sets the number of tokens in the chatbot's response. The `ChatInterface` class supports an `additional_inputs` parameter which can be used to add additional input components.
+
+The `additional_inputs` parameters accepts a component or a list of components. You can pass the component instances directly, or use their string shortcuts (e.g. `"textbox"` instead of `gr.Textbox()`). If you pass in component instances, and they have _not_ already been rendered, then the components will appear underneath the chatbot (and any examples) within a `gr.Accordion()`. You can set the label of this accordion using the `additional_inputs_accordion_name` parameter.
+
+Here's a complete example:
+
+$code_chatinterface_system_prompt
+
+If the components you pass into the `additional_inputs` have already been rendered in a parent `gr.Blocks()`, then they will _not_ be re-rendered in the accordion. This provides flexibility in deciding where to lay out the input components. In the example below, we position the `gr.Textbox()` on top of the Chatbot UI, while keeping the slider underneath.
+
+```python
+import gradio as gr
+import time
+
+def echo(message, history, system_prompt, tokens):
+ response = f"System prompt: {system_prompt}\n Message: {message}."
+ for i in range(min(len(response), int(tokens))):
+ time.sleep(0.05)
+ yield response[: i+1]
+
+with gr.Blocks() as demo:
+ system_prompt = gr.Textbox("You are helpful AI.", label="System Prompt")
+ slider = gr.Slider(10, 100, render=False)
+
+ gr.ChatInterface(
+ echo, additional_inputs=[system_prompt, slider]
+ )
+
+demo.launch()
+```
+
+If you need to create something even more custom, then its best to construct the chatbot UI using the low-level `gr.Blocks()` API. We have [a dedicated guide for that here](/guides/creating-a-custom-chatbot-with-blocks).
+
+## Using your chatbot via an API
+
+Once you've built your Gradio chatbot and are hosting it on [Hugging Face Spaces](https://hf.space) or somewhere else, then you can query it with a simple API at the `/chat` endpoint. The endpoint just expects the user's message (and potentially additional inputs if you have set any using the `additional_inputs` parameter), and will return the response, internally keeping track of the messages sent so far.
+
+[](https://github.com/gradio-app/gradio/assets/1778297/7b10d6db-6476-4e2e-bebd-ecda802c3b8f)
+
+To use the endpoint, you should use either the [Gradio Python Client](/guides/getting-started-with-the-python-client) or the [Gradio JS client](/guides/getting-started-with-the-js-client).
+
+## A `langchain` example
+
+Now, let's actually use the `gr.ChatInterface` with some real large language models. We'll start by using `langchain` on top of `openai` to build a general-purpose streaming chatbot application in 19 lines of code. You'll need to have an OpenAI key for this example (keep reading for the free, open-source equivalent!)
+
+```python
+from langchain.chat_models import ChatOpenAI
+from langchain.schema import AIMessage, HumanMessage
+import openai
+import gradio as gr
+
+os.environ["OPENAI_API_KEY"] = "sk-..." # Replace with your key
+
+llm = ChatOpenAI(temperature=1.0, model='gpt-3.5-turbo-0613')
+
+def predict(message, history):
+ history_langchain_format = []
+ for human, ai in history:
+ history_langchain_format.append(HumanMessage(content=human))
+ history_langchain_format.append(AIMessage(content=ai))
+ history_langchain_format.append(HumanMessage(content=message))
+ gpt_response = llm(history_langchain_format)
+ return gpt_response.content
+
+gr.ChatInterface(predict).launch()
+```
+
+## A streaming example using `openai`
+
+Of course, we could also use the `openai` library directy. Here a similar example, but this time with streaming results as well:
+
+```python
+import openai
+import gradio as gr
+
+openai.api_key = "sk-..." # Replace with your key
+
+def predict(message, history):
+ history_openai_format = []
+ for human, assistant in history:
+ history_openai_format.append({"role": "user", "content": human })
+ history_openai_format.append({"role": "assistant", "content":assistant})
+ history_openai_format.append({"role": "user", "content": message})
+
+ response = openai.ChatCompletion.create(
+ model='gpt-3.5-turbo',
+ messages= history_openai_format,
+ temperature=1.0,
+ stream=True
+ )
+
+ partial_message = ""
+ for chunk in response:
+ if len(chunk['choices'][0]['delta']) != 0:
+ partial_message = partial_message + chunk['choices'][0]['delta']['content']
+ yield partial_message
+
+gr.ChatInterface(predict).launch()
+```
+
+## Example using a local, open-source LLM with Hugging Face
+
+Of course, in many cases you want to run a chatbot locally. Here's the equivalent example using Together's RedePajama model, from Hugging Face (this requires you to have a GPU with CUDA).
+
+```python
+import gradio as gr
+import torch
+from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList, TextIteratorStreamer
+from threading import Thread
+
+tokenizer = AutoTokenizer.from_pretrained("togethercomputer/RedPajama-INCITE-Chat-3B-v1")
+model = AutoModelForCausalLM.from_pretrained("togethercomputer/RedPajama-INCITE-Chat-3B-v1", torch_dtype=torch.float16)
+model = model.to('cuda:0')
+
+class StopOnTokens(StoppingCriteria):
+ def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
+ stop_ids = [29, 0]
+ for stop_id in stop_ids:
+ if input_ids[0][-1] == stop_id:
+ return True
+ return False
+
+def predict(message, history):
+
+ history_transformer_format = history + [[message, ""]]
+ stop = StopOnTokens()
+
+ messages = "".join(["".join(["\n:"+item[0], "\n:"+item[1]]) #curr_system_message +
+ for item in history_transformer_format])
+
+ model_inputs = tokenizer([messages], return_tensors="pt").to("cuda")
+ streamer = TextIteratorStreamer(tokenizer, timeout=10., skip_prompt=True, skip_special_tokens=True)
+ generate_kwargs = dict(
+ model_inputs,
+ streamer=streamer,
+ max_new_tokens=1024,
+ do_sample=True,
+ top_p=0.95,
+ top_k=1000,
+ temperature=1.0,
+ num_beams=1,
+ stopping_criteria=StoppingCriteriaList([stop])
+ )
+ t = Thread(target=model.generate, kwargs=generate_kwargs)
+ t.start()
+
+ partial_message = ""
+ for new_token in streamer:
+ if new_token != '<':
+ partial_message += new_token
+ yield partial_message
+
+
+gr.ChatInterface(predict).launch()
+```
+
+With those examples, you should be all set to create your own Gradio Chatbot demos soon! For building even more custom Chatbot applications, check out [a dedicated guide](/guides/creating-a-custom-chatbot-with-blocks) using the low-level `gr.Blocks()` API.
diff --git a/guides/04_chatbots/02_creating-a-custom-chatbot-with-blocks.md b/guides/04_chatbots/02_creating-a-custom-chatbot-with-blocks.md
new file mode 100644
index 0000000000000000000000000000000000000000..1669b36318c45ac68a681cff9e64fe2adab59718
--- /dev/null
+++ b/guides/04_chatbots/02_creating-a-custom-chatbot-with-blocks.md
@@ -0,0 +1,110 @@
+# How to Create a Custom Chatbot with Gradio Blocks
+
+Tags: NLP, TEXT, CHAT
+Related spaces: https://huggingface.co/spaces/gradio/chatbot_streaming, https://huggingface.co/spaces/project-baize/Baize-7B,
+
+## Introduction
+
+**Important Note**: if you are getting started, we recommend using the `gr.ChatInterface` to create chatbots -- its a high-level abstraction that makes it possible to create beautiful chatbot applications fast, often with a single line of code. [Read more about it here](/guides/creating-a-chatbot-fast).
+
+This tutorial will show how to make chatbot UIs from scratch with Gradio's low-level Blocks API. This will give you full control over your Chatbot UI. You'll start by first creating a a simple chatbot to display text, a second one to stream text responses, and finally a chatbot that can handle media files as well. The chatbot interface that we create will look something like this:
+
+$demo_chatbot_streaming
+
+**Prerequisite**: We'll be using the `gradio.Blocks` class to build our Chatbot demo.
+You can [read the Guide to Blocks first](https://gradio.app/blocks-and-event-listeners) if you are not already familiar with it. Also please make sure you are using the **latest version** version of Gradio: `pip install --upgrade gradio`.
+
+## A Simple Chatbot Demo
+
+Let's start with recreating the simple demo above. As you may have noticed, our bot simply randomly responds "How are you?", "I love you", or "I'm very hungry" to any input. Here's the code to create this with Gradio:
+
+$code_chatbot_simple
+
+There are three Gradio components here:
+
+- A `Chatbot`, whose value stores the entire history of the conversation, as a list of response pairs between the user and bot.
+- A `Textbox` where the user can type their message, and then hit enter/submit to trigger the chatbot response
+- A `ClearButton` button to clear the Textbox and entire Chatbot history
+
+We have a single function, `respond()`, which takes in the entire history of the chatbot, appends a random message, waits 1 second, and then returns the updated chat history. The `respond()` function also clears the textbox when it returns.
+
+Of course, in practice, you would replace `respond()` with your own more complex function, which might call a pretrained model or an API, to generate a response.
+
+$demo_chatbot_simple
+
+## Add Streaming to your Chatbot
+
+There are several ways we can improve the user experience of the chatbot above. First, we can stream responses so the user doesn't have to wait as long for a message to be generated. Second, we can have the user message appear immediately in the chat history, while the chatbot's response is being generated. Here's the code to achieve that:
+
+$code_chatbot_streaming
+
+You'll notice that when a user submits their message, we now _chain_ three event events with `.then()`:
+
+1. The first method `user()` updates the chatbot with the user message and clears the input field. This method also makes the input field non interactive so that the user can't send another message while the chatbot is responding. Because we want this to happen instantly, we set `queue=False`, which would skip any queue had it been enabled. The chatbot's history is appended with `(user_message, None)`, the `None` signifying that the bot has not responded.
+
+2. The second method, `bot()` updates the chatbot history with the bot's response. Instead of creating a new message, we just replace the previously-created `None` message with the bot's response. Finally, we construct the message character by character and `yield` the intermediate outputs as they are being constructed. Gradio automatically turns any function with the `yield` keyword [into a streaming output interface](/guides/key-features/#iterative-outputs).
+
+3. The third method makes the input field interactive again so that users can send another message to the bot.
+
+Of course, in practice, you would replace `bot()` with your own more complex function, which might call a pretrained model or an API, to generate a response.
+
+Finally, we enable queuing by running `demo.queue()`, which is required for streaming intermediate outputs. You can try the improved chatbot by scrolling to the demo at the top of this page.
+
+## Liking / Disliking Chat Messages
+
+Once you've created your `gr.Chatbot`, you can add the ability for users to like or dislike messages. This can be useful if you would like users to vote on a bot's responses or flag inappropriate results.
+
+To add this functionality to your Chatbot, simply attach a `.like()` event to your Chatbot. A chatbot that has the `.like()` event will automatically feature a thumbs-up icon and a thumbs-down icon next to every bot message.
+
+The `.like()` method requires you to pass in a function that is called when a user clicks on these icons. In your function, you should have an argument whose type is `gr.LikeData`. Gradio will automatically supply the parameter to this argument with an object that contains information about the liked or disliked message. Here's a simplistic example of how you can have users like or dislike chat messages:
+
+```py
+import gradio as gr
+
+def greet(history, input):
+ return history + [(input, "Hello, " + input)]
+
+def vote(data: gr.LikeData):
+ if data.liked:
+ print("You upvoted this response: " + data.value)
+ else:
+ print("You downvoted this response: " + data.value)
+
+
+with gr.Blocks() as demo:
+ chatbot = gr.Chatbot()
+ textbox = gr.Textbox()
+ textbox.submit(greet, [chatbot, textbox], [chatbot])
+ chatbot.like(vote, None, None) # Adding this line causes the like/dislike icons to appear in your chatbot
+
+demo.launch()
+```
+
+## Adding Markdown, Images, Audio, or Videos
+
+The `gr.Chatbot` component supports a subset of markdown including bold, italics, and code. For example, we could write a function that responds to a user's message, with a bold **That's cool!**, like this:
+
+```py
+def bot(history):
+ response = "**That's cool!**"
+ history[-1][1] = response
+ return history
+```
+
+In addition, it can handle media files, such as images, audio, and video. To pass in a media file, we must pass in the file as a tuple of two strings, like this: `(filepath, alt_text)`. The `alt_text` is optional, so you can also just pass in a tuple with a single element `(filepath,)`, like this:
+
+```python
+def add_file(history, file):
+ history = history + [((file.name,), None)]
+ return history
+```
+
+Putting this together, we can create a _multimodal_ chatbot with a textbox for a user to submit text and an file upload button to submit images / audio / video files. The rest of the code looks pretty much the same as before:
+
+$code_chatbot_multimodal
+$demo_chatbot_multimodal
+
+And you're done! That's all the code you need to build an interface for your chatbot model. Finally, we'll end our Guide with some links to Chatbots that are running on Spaces so that you can get an idea of what else is possible:
+
+- [project-baize/Baize-7B](https://huggingface.co/spaces/project-baize/Baize-7B): A stylized chatbot that allows you to stop generation as well as regenerate responses.
+- [MAGAer13/mPLUG-Owl](https://huggingface.co/spaces/MAGAer13/mPLUG-Owl): A multimodal chatbot that allows you to upvote and downvote responses.
diff --git a/guides/04_chatbots/03_creating-a-discord-bot-from-a-gradio-app.md b/guides/04_chatbots/03_creating-a-discord-bot-from-a-gradio-app.md
new file mode 100644
index 0000000000000000000000000000000000000000..3a0569e19471a1a9a1db04b7987fa0ad9fb6da0b
--- /dev/null
+++ b/guides/04_chatbots/03_creating-a-discord-bot-from-a-gradio-app.md
@@ -0,0 +1,137 @@
+# 🚀 Creating Discord Bots from Gradio Apps 🚀
+
+Tags: NLP, TEXT, CHAT
+
+We're excited to announce that Gradio can now automatically create a discord bot from a deployed app! 🤖
+
+Discord is a popular communication platform that allows users to chat and interact with each other in real-time. By turning your Gradio app into a Discord bot, you can bring cutting edge AI to your discord server and give your community a whole new way to interact.
+
+## 💻 How does it work? 💻
+
+With `gradio_client` version `0.3.0`, any gradio `ChatInterface` app on the internet can automatically be deployed as a discord bot via the `deploy_discord` method of the `Client` class.
+
+Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. In this guide, we will focus on `gr.ChatInterface` as those apps naturally lend themselves to discord's chat functionality.
+
+## 🛠️ Requirements 🛠️
+
+Make sure you have the latest `gradio_client` and `gradio` versions installed.
+
+```bash
+pip install gradio_client>=0.3.0 gradio>=3.38.0
+```
+
+Also, make sure you have a [Hugging Face account](https://huggingface.co/) and a [write access token](https://huggingface.co/docs/hub/security-tokens).
+
+⚠️ Tip ⚠️: Make sure you login to the Hugging Face Hub by running `huggingface-cli login`. This will let you skip passing your token in all subsequent commands in this guide.
+
+## 🏃♀️ Quickstart 🏃♀️
+
+### Step 1: Implementing our chatbot
+
+Let's build a very simple Chatbot using `ChatInterface` that simply repeats the user message. Write the following code into an `app.py`
+
+```python
+import gradio as gr
+
+def slow_echo(message, history):
+ return message
+
+demo = gr.ChatInterface(slow_echo).queue().launch()
+```
+
+### Step 2: Deploying our App
+
+In order to create a discord bot for our app, it must be accessible over the internet. In this guide, we will use the `gradio deploy` command to deploy our chatbot to Hugging Face spaces from the command line. Run the following command.
+
+```bash
+gradio deploy --title echo-chatbot --app-file app.py
+```
+
+This command will ask you some questions, e.g. requested hardware, requirements, but the default values will suffice for this guide.
+Note the URL of the space that was created. Mine is https://huggingface.co/spaces/freddyaboulton/echo-chatbot
+
+### Step 3: Creating a Discord Bot
+
+Turning our space into a discord bot is also a one-liner thanks to the `gradio deploy-discord`. Run the following command:
+
+```bash
+gradio deploy-discord --src freddyaboulton/echo-chatbot
+```
+
+❗️ Advanced ❗️: If you already have a discord bot token you can pass it to the `deploy-discord` command. Don't worry, if you don't have one yet!
+
+```bash
+gradio deploy-discord --src freddyaboulton/echo-chatbot --discord-bot-token
+```
+
+Note the URL that gets printed out to the console. Mine is https://huggingface.co/spaces/freddyaboulton/echo-chatbot-gradio-discord-bot
+
+### Step 4: Getting a Discord Bot Token
+
+If you didn't have a discord bot token for step 3, go to the URL that got printed in the console and follow the instructions there.
+Once you obtain a token, run the command again but this time pass in the token:
+
+```bash
+gradio deploy-discord --src freddyaboulton/echo-chatbot --discord-bot-token
+```
+
+### Step 5: Add the bot to your server
+
+Visit the space of your discord bot. You should see "Add this bot to your server by clicking this link:" followed by a URL. Go to that URL and add the bot to your server!
+
+### Step 6: Use your bot!
+
+By default the bot can be called by starting a message with `/chat`, e.g. `/chat `.
+
+⚠️ Tip ⚠️: If either of the deployed spaces goes to sleep, the bot will stop working. By default, spaces go to sleep after 48 hours of inactivity. You can upgrade the hardware of your space to prevent it from going to sleep. See this [guide](https://huggingface.co/docs/hub/spaces-gpus#using-gpu-spaces) for more information.
+
+
+
+### Using the `gradio_client.Client` Class
+
+You can also create a discord bot from a deployed gradio app with python.
+
+```python
+import gradio_client as grc
+grc.Client("freddyaboulton/echo-chatbot").deploy_discord()
+```
+
+## 🦾 Using State of The Art LLMs 🦾
+
+We have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) containing several template spaces that explain how to deploy state of the art LLMs powered by gradio as discord bots.
+
+The easiest way to get started is by deploying Meta's Llama 2 LLM with 70 billion parameter. Simply go to this [space](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) and follow the instructions.
+
+The deployment can be done in one line! 🤯
+
+```python
+import gradio_client as grc
+grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
+```
+
+## 🦜 Additional LLMs 🦜
+
+In addition to Meta's 70 billion Llama 2 model, we have prepared template spaces for the following LLMs and deployment options:
+
+- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Required OpenAI key.
+- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
+- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
+
+To deploy any of these models to discord, simply follow the instructions in the linked space for that model.
+
+## Deploying non-chat gradio apps to discord
+
+As mentioned above, you don't need a `gr.ChatInterface` if you want to deploy your gradio app to discord. All that's needed is an api route that takes in a single string and outputs a single string.
+
+The following code will deploy a space that translates english to german as a discord bot.
+
+```python
+import gradio_client as grc
+client = grc.Client("freddyaboulton/english-to-german")
+client.deploy_discord(api_names=['german'])
+```
+
+## Conclusion
+
+That's it for this guide! We're really excited about this feature. Tag [@Gradio](https://twitter.com/Gradio) on twitter and show us how your discord community interacts with your discord bots.
diff --git a/guides/05_custom-components/01_custom-components-in-five-minutes.md b/guides/05_custom-components/01_custom-components-in-five-minutes.md
new file mode 100644
index 0000000000000000000000000000000000000000..013572d7d7b84989bf375c3240dc57a7f0f43b65
--- /dev/null
+++ b/guides/05_custom-components/01_custom-components-in-five-minutes.md
@@ -0,0 +1,123 @@
+# Custom Components in 5 minutes
+
+Gradio 4.0 introduces Custom Components -- the ability for developers to create their own custom components and use them in Gradio apps.
+You can publish your components as Python packages so that other users can use them as well.
+Users will be able to use all of Gradio's existing functions, such as `gr.Blocks`, `gr.Interface`, API usage, themes, etc. with Custom Components.
+This guide will cover how to get started making custom components.
+
+## Installation
+
+You will need to have:
+
+* Python 3.8+ (install here )
+* Node.js v16.14+ (install here )
+* npm 9+ (install here )
+* Gradio 4.0+ (`pip install --upgrade gradio`)
+
+## The Workflow
+
+The Custom Components workflow consists of 4 steps: create, dev, build, and publish.
+
+1. create: creates a template for you to start developing a custom component.
+2. dev: launches a development server with a sample app & hot reloading allowing you to easily develop your custom component
+3. build: builds a python package containing to your custom component's Python and JavaScript code -- this makes things official!
+4. publish: uploads your package to [PyPi](https://pypi.org/) and/or a sample app to [HuggingFace Spaces](https://hf.co/spaces).
+
+Each of these steps is done via the Custom Component CLI. You can invoke it with `gradio cc` or `gradio component`
+
+Tip: Run `gradio cc --help` to get a help menu of all available commands. You can also append `--help` to any command name to bring up a help page for that command, e.g. `gradio cc create --help`.
+
+## 1. create
+
+Bootstrap a new template by running the following in any working directory:
+
+```bash
+gradio cc create MyComponent --template SimpleTextbox
+```
+
+Instead of `MyComponent`, give your component any name.
+
+Instead of `SimpleTextbox`, you can use any Gradio component as a template. `SimpleTextbox` is actually a special component that a stripped-down version of the `Textbox` component that makes it particularly useful when creating your first custom component.
+Some other components that are good if you are starting out: `SimpleDropdown` or `File`.
+
+Tip: Run `gradio cc show` to get a list of available component templates.
+
+The `create` command will:
+
+1. Create a directory with your component's name in lowercase with the following structure:
+```directory
+- backend/ <- The python code for your custom component
+- frontend/ <- The javascript code for your custom component
+- demo/ <- A sample app using your custom component. Modify this to develop your component!
+- pyproject.toml <- Used to build the package and specify package metadata.
+```
+
+2. Install the component in development mode
+
+Each of the directories will have the code you need to get started developing!
+
+## 2. dev
+
+Once you have created your new component, you can start a development server by `entering the directory` and running
+
+```bash
+gradio cc dev
+```
+
+You'll see several lines that are printed to the console.
+The most important one is the one that says:
+
+> Frontend Server (Go here): http://localhost:7861/
+
+The port number might be different for you.
+Click on that link to launch the demo app in hot reload mode.
+Now, you can start making changes to the backend and frontend you'll see the results reflected live in the sample app!
+We'll go through a real example in a later guide.
+
+Tip: You don't have to run dev mode from your custom component directory. The first argument to `dev` mode is the path to the directory. By default it uses the current directory.
+
+## 3. build
+
+Once you are satisfied with your custom component's implementation, you can `build` it to use it outside of the development server.
+
+From your component directory, run:
+
+```bash
+gradio cc build
+```
+
+This will create a `tar.gz` and `.whl` file in a `dist/` subdirectory.
+If you or anyone installs that `.whl` file (`pip install `) they will be able to use your custom component in any gradio app!
+
+The `build` command will also generate documentation for your custom component. This takes the form of an interactive space and a static `README.md`. You can disable this by passing `--no-generate-docs`. You can read more about the documentation generator in [the dedicated guide](./documenting-custom-components).
+
+## 4. publish
+
+Right now, your package is only available on a `.whl` file on your computer.
+You can share that file with the world with the `publish` command!
+
+Simply run the following command from your component directory:
+
+```bash
+gradio cc publish
+```
+
+This will guide you through the following process:
+
+1. Upload your distribution files to PyPi. This is optional. If you decide to upload to PyPi, you will need a PyPI username and password. You can get one [here](https://pypi.org/account/register/).
+2. Upload a demo of your component to hugging face spaces. This is also optional.
+
+
+Here is an example of what publishing looks like:
+
+
+
+
+
+
+## Conclusion
+
+Now that you know the high-level workflow of creating custom components, you can go in depth in the next guides!
+After reading the guides, check out this [collection](https://huggingface.co/collections/gradio/custom-components-65497a761c5192d981710b12) of custom components on the HuggingFace Hub so you can learn from other's code.
+
+
diff --git a/guides/05_custom-components/02_key-component-concepts.md b/guides/05_custom-components/02_key-component-concepts.md
new file mode 100644
index 0000000000000000000000000000000000000000..098b6ea30dcf04aa9bed3161473634a798830c0d
--- /dev/null
+++ b/guides/05_custom-components/02_key-component-concepts.md
@@ -0,0 +1,124 @@
+# Gradio Components: The Key Concepts
+
+In this section, we discuss a few important concepts when it comes to components in Gradio.
+It's important to understand these concepts when developing your own component.
+Otherwise, your component may behave very different to other Gradio components!
+
+Tip: You can skip this section if you are familiar with the internals of the Gradio library, such as each component's preprocess and postprocess methods.
+
+## Interactive vs Static
+
+Every component in Gradio comes in a `static` variant, and most come in an `interactive` version as well.
+The `static` version is used when a component is displaying a value, and the user can **NOT** change that value by interacting with it.
+The `interactive` version is used when the user is able to change the value by interacting with the Gradio UI.
+
+Let's see some examples:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Textbox(value="Hello", interactive=True)
+ gr.Textbox(value="Hello", interactive=False)
+
+demo.launch()
+
+```
+This will display two textboxes.
+The only difference: you'll be able to edit the value of the Gradio component on top, and you won't be able to edit the variant on the bottom (i.e. the textbox will be disabled).
+
+Perhaps a more interesting example is with the `Image` component:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Image(interactive=True)
+ gr.Image(interactive=False)
+
+demo.launch()
+```
+
+The interactive version of the component is much more complex -- you can upload images or snap a picture from your webcam -- while the static version can only be used to display images.
+
+Not every component has a distinct interactive version. For example, the `gr.AnnotatedImage` only appears as a static version since there's no way to interactively change the value of the annotations or the image.
+
+### What you need to remember
+
+* Gradio will use the interactive version (if available) of a component if that component is used as the **input** to any event; otherwise, the static version will be used.
+
+* When you design custom components, you **must** accept the boolean interactive keyword in the constructor of your Python class. In the frontend, you **may** accept the `interactive` property, a `bool` which represents whether the component should be static or interactive. If you do not use this property in the frontend, the component will appear the same in interactive or static mode.
+
+## The value and how it is preprocessed/postprocessed
+
+The most important attribute of a component is its `value`.
+Every component has a `value`.
+The value that is typically set by the user in the frontend (if the component is interactive) or displayed to the user (if it is static).
+It is also this value that is sent to the backend function when a user triggers an event, or returned by the user's function e.g. at the end of a prediction.
+
+So this value is passed around quite a bit, but sometimes the format of the value needs to change between the frontend and backend.
+Take a look at this example:
+
+```python
+import numpy as np
+import gradio as gr
+
+def sepia(input_img):
+ sepia_filter = np.array([
+ [0.393, 0.769, 0.189],
+ [0.349, 0.686, 0.168],
+ [0.272, 0.534, 0.131]
+ ])
+ sepia_img = input_img.dot(sepia_filter.T)
+ sepia_img /= sepia_img.max()
+ return sepia_img
+
+demo = gr.Interface(sepia, gr.Image(shape=(200, 200)), "image")
+demo.launch()
+```
+
+This will create a Gradio app which has an `Image` component as the input and the output.
+In the frontend, the Image component will actually **upload** the file to the server and send the **filepath** but this is converted to a `numpy` array before it is sent to a user's function.
+Conversely, when the user returns a `numpy` array from their function, the numpy array is converted to a file so that it can be sent to the frontend and displayed by the `Image` component.
+
+Tip: By default, the `Image` component sends numpy arrays to the python function because it is a common choice for machine learning engineers, though the Image component also supports other formats using the `type` parameter. Read the `Image` docs [here](https://www.gradio.app/docs/image) to learn more.
+
+Each component does two conversions:
+
+1. `preprocess`: Converts the `value` from the format sent by the frontend to the format expected by the python function. This usually involves going from a web-friendly **JSON** structure to a **python-native** data structure, like a `numpy` array or `PIL` image. The `Audio`, `Image` components are good examples of `preprocess` methods.
+
+2. `postprocess`: Converts the value returned by the python function to the format expected by the frontend. This usually involves going from a **python-native** data-structure, like a `PIL` image to a **JSON** structure.
+
+### What you need to remember
+
+* Every component must implement `preprocess` and `postprocess` methods. In the rare event that no conversion needs to happen, simply return the value as-is. `Textbox` and `Number` are examples of this.
+
+* As a component author, **YOU** control the format of the data displayed in the frontend as well as the format of the data someone using your component will receive. Think of an ergonomic data-structure a **python** developer will find intuitive, and control the conversion from a **Web-friendly JSON** data structure (and vice-versa) with `preprocess` and `postprocess.`
+
+## The "Example Version" of a Component
+
+Gradio apps support providing example inputs -- and these are very useful in helping users get started using your Gradio app.
+In `gr.Interface`, you can provide examples using the `examples` keyword, and in `Blocks`, you can provide examples using the special `gr.Examples` component.
+
+At the bottom of this screenshot, we show a miniature example image of a cheetah that, when clicked, will populate the same image in the input Image component:
+
+![img](https://user-images.githubusercontent.com/1778297/277548211-a3cb2133-2ffc-4cdf-9a83-3e8363b57ea6.png)
+
+
+To enable the example view, you must have the following two files in the top of the `frontend` directory:
+
+* `Example.svelte`: this corresponds to the "example version" of your component
+* `Index.svelte`: this corresponds to the "regular version"
+
+In the backend, you typically don't need to do anything. The user-provided example `value` is processed using the same `.postprocess()` method described earlier. If you'd like to do process the data differently (for example, if the `.postprocess()` method is computationally expensive), then you can write your own `.process_example()` method for your custom component, which will be used instead.
+
+The `Example.svelte` file and `process_example()` method will be covered in greater depth in the dedicated [frontend](./frontend) and [backend](./backend) guides respectively.
+
+### What you need to remember
+
+* If you expect your component to be used as input, it is important to define an "Example" view.
+* If you don't, Gradio will use a default one but it won't be as informative as it can be!
+
+## Conclusion
+
+Now that you know the most important pieces to remember about Gradio components, you can start to design and build your own!
\ No newline at end of file
diff --git a/guides/05_custom-components/03_configuration.md b/guides/05_custom-components/03_configuration.md
new file mode 100644
index 0000000000000000000000000000000000000000..234cae328fb25bb3d369d5dbde6435aba66ed3b0
--- /dev/null
+++ b/guides/05_custom-components/03_configuration.md
@@ -0,0 +1,100 @@
+# Configuring Your Custom Component
+
+The custom components workflow focuses on [convention over configuration](https://en.wikipedia.org/wiki/Convention_over_configuration) to reduce the number of decisions you as a developer need to make when developing your custom component.
+That being said, you can still configure some aspects of the custom component package and directory.
+This guide will cover how.
+
+## The Package Name
+
+By default, all custom component packages are called `gradio_` where `component-name` is the name of the component's python class in lowercase.
+
+As an example, let's walkthrough changing the name of a component from `gradio_mytextbox` to `supertextbox`.
+
+1. Modify the `name` in the `pyproject.toml` file.
+
+```bash
+[project]
+name = "supertextbox"
+```
+
+2. Change all occurrences of `gradio_` in `pyproject.toml` to ``
+
+```bash
+[tool.hatch.build]
+artifacts = ["/backend/supertextbox/templates", "*.pyi"]
+
+[tool.hatch.build.targets.wheel]
+packages = ["/backend/supertextbox"]
+```
+
+3. Rename the `gradio_` directory in `backend/` to ``
+
+```bash
+mv backend/gradio_mytextbox backend/supertextbox
+```
+
+
+Tip: Remember to change the import statement in `demo/app.py`!
+
+## Top Level Python Exports
+
+By default, only the custom component python class is a top level export.
+This means that when users type `from gradio_ import ...`, the only class that will be available is the custom component class.
+To add more classes as top level exports, modify the `__all__` property in `__init__.py`
+
+```python
+from .mytextbox import MyTextbox
+from .mytextbox import AdditionalClass, additional_function
+
+__all__ = ['MyTextbox', 'AdditionalClass', 'additional_function']
+```
+
+## Python Dependencies
+
+You can add python dependencies by modifying the `dependencies` key in `pyproject.toml`
+
+```bash
+dependencies = ["gradio", "numpy", "PIL"]
+```
+
+
+Tip: Remember to run `gradio cc install` when you add dependencies!
+
+## Javascript Dependencies
+
+You can add JavaScript dependencies by modifying the `"dependencies"` key in `frontend/package.json`
+
+```json
+"dependencies": {
+ "@gradio/atoms": "0.2.0-beta.4",
+ "@gradio/statustracker": "0.3.0-beta.6",
+ "@gradio/utils": "0.2.0-beta.4",
+ "your-npm-package": ""
+}
+```
+
+## Directory Structure
+
+By default, the CLI will place the Python code in `backend` and the JavaScript code in `frontend`.
+It is not recommended to change this structure since it makes it easy for a potential contributor to look at your source code and know where everything is.
+However, if you did want to this is what you would have to do:
+
+1. Place the Python code in the subdirectory of your choosing. Remember to modify the `[tool.hatch.build]` `[tool.hatch.build.targets.wheel]` in the `pyproject.toml` to match!
+
+2. Place the JavaScript code in the subdirectory of your choosing.
+
+2. Add the `FRONTEND_DIR` property on the component python class. It must be the relative path from the file where the class is defined to the location of the JavaScript directory.
+
+```python
+class SuperTextbox(Component):
+ FRONTEND_DIR = "../../frontend/"
+```
+
+The JavaScript and Python directories must be under the same common directory!
+
+## Conclusion
+
+
+Sticking to the defaults will make it easy for others to understand and contribute to your custom component.
+After all, the beauty of open source is that anyone can help improve your code!
+But if you ever need to deviate from the defaults, you know how!
\ No newline at end of file
diff --git a/guides/05_custom-components/04_backend.md b/guides/05_custom-components/04_backend.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a61ab86984678f06172194f458103f583401d09
--- /dev/null
+++ b/guides/05_custom-components/04_backend.md
@@ -0,0 +1,226 @@
+# The Backend 🐍
+
+This guide will cover everything you need to know to implement your custom component's backend processing.
+
+## Which Class to Inherit From
+
+All components inherit from one of three classes `Component`, `FormComponent`, or `BlockContext`.
+You need to inherit from one so that your component behaves like all other gradio components.
+When you start from a template with `gradio cc create --template`, you don't need to worry about which one to choose since the template uses the correct one.
+For completeness, and in the event that you need to make your own component from scratch, we explain what each class is for.
+
+* `FormComponent`: Use this when you want your component to be grouped together in the same `Form` layout with other `FormComponents`. The `Slider`, `Textbox`, and `Number` components are all `FormComponents`.
+* `BlockContext`: Use this when you want to place other components "inside" your component. This enabled `with MyComponent() as component:` syntax.
+* `Component`: Use this for all other cases.
+
+Tip: If your component supports streaming output, inherit from the `StreamingOutput` class.
+
+Tip: If you inherit from `BlockContext`, you also need to set the metaclass to be `ComponentMeta`. See example below.
+
+```python
+from gradio.blocks import BlockContext
+from gradio.component_meta import ComponentMeta
+
+set_documentation_group("layout")
+
+
+@document()
+class Row(BlockContext, metaclass=ComponentMeta):
+ pass
+```
+
+## The methods you need to implement
+
+When you inherit from any of these classes, the following methods must be implemented.
+Otherwise the Python interpreter will raise an error when you instantiate your component!
+
+### `preprocess` and `postprocess`
+
+Explained in the [Key Concepts](./key-component-concepts#the-value-and-how-it-is-preprocessed-postprocessed) guide.
+They handle the conversion from the data sent by the frontend to the format expected by the python function.
+
+```python
+ @abstractmethod
+ def preprocess(self, x: Any) -> Any:
+ """
+ Convert from the web-friendly (typically JSON) value in the frontend to the format expected by the python function.
+ """
+ return x
+
+ @abstractmethod
+ def postprocess(self, y):
+ """
+ Convert from the data returned by the python function to the web-friendly (typically JSON) value expected by the frontend.
+ """
+ return y
+```
+
+### `process_example`
+
+Takes in the original Python value and returns the modified value that should be displayed in the examples preview in the app.
+If not provided, the `.postprocess()` method is used instead. Let's look at the following example from the `SimpleDropdown` component.
+
+```python
+def process_example(self, input_data):
+ return next((c[0] for c in self.choices if c[1] == input_data), None)
+```
+
+Since `self.choices` is a list of tuples corresponding to (`display_name`, `value`), this converts the value that a user provides to the display value (or if the value is not present in `self.choices`, it is converted to `None`).
+
+```python
+@abstractmethod
+def process_example(self, y):
+ pass
+```
+
+### `api_info`
+
+A JSON-schema representation of the value that the `preprocess` expects.
+This powers api usage via the gradio clients.
+You do **not** need to implement this yourself if you components specifies a `data_model`.
+The `data_model` in the following section.
+
+```python
+@abstractmethod
+def api_info(self) -> dict[str, list[str]]:
+ """
+ A JSON-schema representation of the value that the `preprocess` expects and the `postprocess` returns.
+ """
+ pass
+```
+
+### `example_inputs`
+
+The example inputs for this component displayed in the `View API` page.
+Must be JSON-serializable.
+If your component expects a file, it is best to use a publicly accessible URL.
+
+```python
+@abstractmethod
+def example_inputs(self) -> Any:
+ """
+ The example inputs for this component for API usage. Must be JSON-serializable.
+ """
+ pass
+```
+
+### `flag`
+
+Write the component's value to a format that can be stored in the `csv` or `json` file used for flagging.
+You do **not** need to implement this yourself if you components specifies a `data_model`.
+The `data_model` in the following section.
+
+```python
+@abstractmethod
+def flag(self, x: Any | GradioDataModel, flag_dir: str | Path = "") -> str:
+ pass
+```
+
+### `read_from_flag`
+Convert from the format stored in the `csv` or `json` file used for flagging to the component's python `value`.
+You do **not** need to implement this yourself if you components specifies a `data_model`.
+The `data_model` in the following section.
+
+```python
+@abstractmethod
+def read_from_flag(
+ self,
+ x: Any,
+ flag_dir: str | Path | None = None,
+) -> GradioDataModel | Any:
+ """
+ Convert the data from the csv or jsonl file into the component state.
+ """
+ return x
+```
+
+## The `data_model`
+
+The `data_model` is how you define the expected data format your component's value will be stored in the frontend.
+It specifies the data format your `preprocess` method expects and the format the `postprocess` method returns.
+It is not necessary to define a `data_model` for your component but it greatly simplifies the process of creating a custom component.
+If you define a custom component you only need to implement three methods - `preprocess`, `postprocess`, and `example_inputs`!
+
+You define a `data_model` by defining a [pydantic model](https://docs.pydantic.dev/latest/concepts/models/#basic-model-usage) that inherits from either `GradioModel` or `GradioRootModel`.
+
+This is best explained with an example. Let's look at the core `Video` component, which stores the video data as a JSON object with two keys `video` and `subtitles` which point to separate files.
+
+```python
+from gradio.data_classes import FileData, GradioModel
+
+class VideoData(GradioModel):
+ video: FileData
+ subtitles: Optional[FileData] = None
+
+class Video(Component):
+ data_model = VideoData
+```
+
+By adding these four lines of code, your component automatically implements the methods needed for API usage, the flagging methods, and example caching methods!
+It also has the added benefit of self-documenting your code.
+Anyone who reads your component code will know exactly the data it expects.
+
+Tip: If your component expects files to be uploaded from the frontend, your must use the `FileData` model! It will be explained in the following section.
+
+Tip: Read the pydantic docs [here](https://docs.pydantic.dev/latest/concepts/models/#basic-model-usage).
+
+The difference between a `GradioModel` and a `GradioRootModel` is that the `RootModel` will not serialize the data to a dictionary.
+For example, the `Names` model will serialize the data to `{'names': ['freddy', 'pete']}` whereas the `NamesRoot` model will serialize it to `['freddy', 'pete']`.
+
+```python
+from typing import List
+
+class Names(GradioModel):
+ names: List[str]
+
+class NamesRoot(GradioRootModel):
+ root: List[str]
+```
+
+Even if your component does not expect a "complex" JSON data structure it can be beneficial to define a `GradioRootModel` so that you don't have to worry about implementing the API and flagging methods.
+
+Tip: Use classes from the Python typing library to type your models. e.g. `List` instead of `list`.
+
+## Handling Files
+
+If your component expects uploaded files as input, or returns saved files to the frontend, you **MUST** use the `FileData` to type the files in your `data_model`.
+
+When you use the `FileData`:
+
+* Gradio knows that it should allow serving this file to the frontend. Gradio automatically blocks requests to serve arbitrary files in the computer running the server.
+
+* Gradio will automatically place the file in a cache so that duplicate copies of the file don't get saved.
+
+* The client libraries will automatically know that they should upload input files prior to sending the request. They will also automatically download files.
+
+If you do not use the `FileData`, your component will not work as expected!
+
+
+## Adding Event Triggers To Your Component
+
+The events triggers for your component are defined in the `EVENTS` class attribute.
+This is a list that contains the string names of the events.
+Adding an event to this list will automatically add a method with that same name to your component!
+
+You can import the `Events` enum from `gradio.events` to access commonly used events in the core gradio components.
+
+For example, the following code will define `text_submit`, `file_upload` and `change` methods in the `MyComponent` class.
+
+```python
+from gradio.events import Events
+from gradio.components import FormComponent
+
+class MyComponent(FormComponent):
+
+ EVENTS = [
+ "text_submit",
+ "file_upload",
+ Events.change
+ ]
+```
+
+
+Tip: Don't forget to also handle these events in the JavaScript code!
+
+## Conclusion
+
diff --git a/guides/05_custom-components/05_frontend.md b/guides/05_custom-components/05_frontend.md
new file mode 100644
index 0000000000000000000000000000000000000000..b0a469a673e1575a322f72125af0a2eb958dbb33
--- /dev/null
+++ b/guides/05_custom-components/05_frontend.md
@@ -0,0 +1,274 @@
+# The Frontend 🌐⭐️
+
+This guide will cover everything you need to know to implement your custom component's frontend.
+
+Tip: Gradio components use Svelte. Writing Svelte is fun! If you're not familiar with it, we recommend checking out their interactive [guide](https://learn.svelte.dev/tutorial/welcome-to-svelte).
+
+## The directory structure
+
+The frontend code should have, at minimum, three files:
+
+* `Index.svelte`: This is the main export and where your component's layout and logic should live.
+* `Example.svelte`: This is where the example view of the component is defined.
+
+Feel free to add additional files and subdirectories.
+If you want to export any additional modules, remember to modify the `package.json` file
+
+```json
+"exports": {
+ ".": "./Index.svelte",
+ "./example": "./Example.svelte",
+ "./package.json": "./package.json"
+},
+```
+
+## The Index.svelte file
+
+Your component should expose the following props that will be passed down from the parent Gradio application.
+
+```typescript
+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` and `elem_classes` allow Gradio app developers to target your component with custom CSS and JavaScript from the Python `Blocks` class.
+
+* `scale` and `min_width` allow Gradio app developers to control how much space your component takes up in the UI.
+
+* `loading_status` is used to display a loading status over the component when it is the output of an event.
+
+* `mode` is how the parent Gradio app tells your component whether the `interactive` or `static` version should be displayed.
+
+* `gradio`: The `gradio` object is created by the parent Gradio app. It stores some application-level configuration that will be useful in your component, like internationalization. You must use it to dispatch events from your component.
+
+A minimal `Index.svelte` file would look like:
+
+```typescript
+
+
+
+ {#if loading_status}
+
+ {/if}
+ {value}
+
+```
+
+## The Example.svelte file
+
+The `Example.svelte` file should expose the following props:
+
+```typescript
+ export let value: string;
+ export let type: "gallery" | "table";
+ export let selected = false;
+ export let samples_dir: string;
+ export let index: number;
+```
+
+* `value`: The example value that should be displayed.
+
+* `type`: This is a variable that can be either `"gallery"` or `"table"` depending on how the examples are displayed. The `"gallery"` form is used when the examples correspond to a single input component, while the `"table"` form is used when a user has multiple input components, and the examples need to populate all of them.
+
+* `selected`: You can also adjust how the examples are displayed if a user "selects" a particular example by using the selected variable.
+
+* `samples_dir`: A URL to prepend to `value` if your example is fetching a file from the server
+
+* `index`: The current index of the selected value.
+
+* Any additional props your "non-example" component takes!
+
+This is the `Example.svelte` file for the code `Radio` component:
+
+```typescript
+
+
+
+ {value}
+
+
+
+```
+
+## Handling Files
+
+If your component deals with files, these files **should** be uploaded to the backend server.
+The `@gradio/client` npm package provides the `upload`, `prepare_files`, and `normalise_file` utility functions to help you do this.
+
+The `prepare_files` function will convert the browser's `File` datatype to gradio's internal `FileData` type.
+You should use the `FileData` data in your component to keep track of uploaded files.
+
+The `upload` function will upload an array of `FileData` values to the server.
+
+The `normalise_file` function will generate the correct URL for your component to fetch the file from and set it to the `data` property of the `FileData.`
+
+
+Tip: Be sure you call `normalise_file` whenever your files are updated!
+
+
+Here's an example of loading files from an ` ` element when its value changes.
+
+
+```typescript
+
+
+
+```
+
+The component exposes a prop named `root`.
+This is passed down by the parent gradio app and it represents the base url that the files will be uploaded to and fetched from.
+
+For WASM support, you should get the upload function from the `Context` and pass that as the third parameter of the `upload` function.
+
+```typescript
+
+```
+
+## Leveraging Existing Gradio Components
+
+Most of Gradio's frontend components are published on [npm](https://www.npmjs.com/), the javascript package repository.
+This means that you can use them to save yourself time while incorporating common patterns in your component, like uploading files.
+For example, the `@gradio/upload` package has `Upload` and `ModifyUpload` components for properly uploading files to the Gradio server.
+Here is how you can use them to create a user interface to upload and display PDF files.
+
+```typescript
+
+
+
+{#if value === null && interactive}
+
+
+
+{:else if value !== null}
+ {#if interactive}
+
+ {/if}
+
+{:else}
+
+{/if}
+```
+
+You can also combine existing Gradio components to create entirely unique experiences.
+Like rendering a gallery of chatbot conversations.
+The possibilities are endless, please read the documentation on our javascript packages [here](https://gradio.app/main/docs/js).
+We'll be adding more packages and documentation over the coming weeks!
+
+## Matching Gradio Core's Design System
+
+You can explore our component library via Storybook. You'll be able to interact with our components and see them in their various states.
+
+For those interested in design customization, we provide the CSS variables consisting of our color palette, radii, spacing, and the icons we use - so you can easily match up your custom component with the style of our core components. This Storybook will be regularly updated with any new additions or changes.
+
+[Storybook Link](https://gradio.app/main/docs/js/storybook)
+
+
+## Conclusion
+
+You now how to create delightful frontends for your components!
+
diff --git a/guides/05_custom-components/06_frequently-asked-questions.md b/guides/05_custom-components/06_frequently-asked-questions.md
new file mode 100644
index 0000000000000000000000000000000000000000..d7b6c5d43bcfa93a7de70f8c027ac01a28430d36
--- /dev/null
+++ b/guides/05_custom-components/06_frequently-asked-questions.md
@@ -0,0 +1,50 @@
+# Frequently Asked Questions
+
+## What do I need to install before using Custom Components?
+Before using Custom Components, make sure you have Python 3.8+, Node.js v16.14+, npm 9+, and Gradio 4.0+ installed.
+
+## What templates can I use to create my custom component?
+Run `gradio cc show` to see the list of built-in templates.
+You can also start off from other's custom components!
+Simply `git clone` their repository and make your modifications.
+
+## What is the development server?
+When you run `gradio cc dev`, a development server will load and run a Gradio app of your choosing.
+This is like when you run `python .py`, however the `gradio` command will hot reload so you can instantly see your changes.
+
+## The development server didn't work for me
+Make sure you have your package installed along with any dependencies you have added by running `gradio cc install`.
+Make sure there aren't any syntax or import errors in the Python or JavaScript code.
+
+## Do I need to host my custom component on HuggingFace Spaces?
+You can develop and build your custom component without hosting or connecting to HuggingFace.
+If you would like to share your component with the gradio community, it is recommended to publish your package to PyPi and host a demo on HuggingFace so that anyone can install it or try it out.
+
+## What methods are mandatory for implementing a custom component in Gradio?
+
+You must implement the `preprocess`, `postprocess`, `api_info`, `example_inputs`, `flag`, and `read_from_flag` methods. Read more in the [backend guide](./backend).
+
+## What is the purpose of a `data_model` in Gradio custom components?
+
+A `data_model` defines the expected data format for your component, simplifying the component development process and self-documenting your code. It streamlines API usage and example caching.
+
+## Why is it important to use `FileData` for components dealing with file uploads?
+
+Utilizing `FileData` is crucial for components that expect file uploads. It ensures secure file handling, automatic caching, and streamlined client library functionality.
+
+## How can I add event triggers to my custom Gradio component?
+
+You can define event triggers in the `EVENTS` class attribute by listing the desired event names, which automatically adds corresponding methods to your component.
+
+## Can I implement a custom Gradio component without defining a `data_model`?
+
+Yes, it is possible to create custom components without a `data_model`, but you are going to have to manually implement `api_info`, `example_inputs`, `flag`, and `read_from_flag` methods.
+
+## Are there sample custom components I can learn from?
+
+We have prepared this [collection](https://huggingface.co/collections/gradio/custom-components-65497a761c5192d981710b12) of custom components on the HuggingFace Hub that you can use to get started!
+
+## How can I find custom components created by the Gradio community?
+
+We're working on creating a gallery to make it really easy to discover new custom components.
+In the meantime, you can search for HuggingFace Spaces that are tagged as a `gradio-custom-component` [here](https://huggingface.co/search/full-text?q=gradio-custom-component&type=space)
\ No newline at end of file
diff --git a/guides/05_custom-components/07_pdf-component-example.md b/guides/05_custom-components/07_pdf-component-example.md
new file mode 100644
index 0000000000000000000000000000000000000000..31b7fe63e7acb1ce2eada8da667736b9ac01f56e
--- /dev/null
+++ b/guides/05_custom-components/07_pdf-component-example.md
@@ -0,0 +1,692 @@
+# Case Study: A Component to Display PDFs
+
+Let's work through an example of building a custom gradio component for displaying PDF files.
+This component will come in handy for showcasing [document question answering](https://huggingface.co/models?pipeline_tag=document-question-answering&sort=trending) models, which typically work on PDF input.
+This is a sneak preview of what our finished component will look like:
+
+![demo](https://gradio-builds.s3.amazonaws.com/assets/PDFDisplay.png)
+
+## Step 0: Prerequisites
+Make sure you have gradio 4.0 installed as well as node 18+.
+As of the time of publication, the latest release is 4.1.1.
+Also, please read the [Five Minute Tour](./custom-components-in-five-minutes) of custom components and the [Key Concepts](./key-component-concepts) guide before starting.
+
+
+## Step 1: Creating the custom component
+
+Navigate to a directory of your choosing and run the following command:
+
+```bash
+gradio cc create PDF
+```
+
+
+Tip: You should change the name of the component.
+Some of the screenshots assume the component is callled `PDF` but the concepts are the same!
+
+This will create a subdirectory called `pdf` in your current working directory.
+There are three main subdirectories in `pdf`: `frontend`, `backend`, and `demo`.
+If you open `pdf` in your code editor, it will look like this:
+
+![directory structure](https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/CodeStructure.png)
+
+Tip: For this demo we are not templating off a current gradio component. But you can see the list of available templates with `gradio cc show` and then pass the template name to the `--template` option, e.g. `gradio cc create --template `
+
+## Step 2: Frontend - modify javascript dependencies
+
+We're going to use the [pdfjs](https://mozilla.github.io/pdf.js/) javascript library to display the pdfs in the frontend.
+Let's start off by adding it to our frontend project's dependencies, as well as adding a couple of other projects we'll need.
+
+From within the `frontend` directory, run `npm install @gradio/client @gradio/upload @gradio/icons @gradio/button` and `npm install --save-dev pdfjs-dist@3.11.174`.
+Also, let's uninstall the `@zerodevx/svelte-json-view` dependency by running `npm uninstall @zerodevx/svelte-json-view`.
+
+The complete `package.json` should look like this:
+
+```json
+{
+ "name": "gradio_pdf",
+ "version": "0.2.0",
+ "description": "Gradio component for displaying PDFs",
+ "type": "module",
+ "author": "",
+ "license": "ISC",
+ "private": false,
+ "main_changeset": true,
+ "exports": {
+ ".": "./Index.svelte",
+ "./example": "./Example.svelte",
+ "./package.json": "./package.json"
+ },
+ "devDependencies": {
+ "pdfjs-dist": "3.11.174"
+ },
+ "dependencies": {
+ "@gradio/atoms": "0.2.0",
+ "@gradio/statustracker": "0.3.0",
+ "@gradio/utils": "0.2.0",
+ "@gradio/client": "0.7.1",
+ "@gradio/upload": "0.3.2",
+ "@gradio/icons": "0.2.0",
+ "@gradio/button": "0.2.3",
+ "pdfjs-dist": "3.11.174"
+ }
+}
+```
+
+
+Tip: Running `npm install` will install the latest version of the package available. You can install a specific version with `npm install package@`. You can find all of the gradio javascript package documentation [here](https://www.gradio.app/main/docs/js). It is recommended you use the same versions as me as the API can change.
+
+Navigate to `Index.svelte` and delete mentions of `JSONView`
+
+```ts
+import { JsonView } from "@zerodevx/svelte-json-view";
+```
+
+```ts
+
+```
+
+## Step 3: Frontend - Launching the Dev Server
+
+Run the `dev` command to launch the development server.
+This will open the demo in `demo/app.py` in an environment where changes to the `frontend` and `backend` directories will reflect instantaneously in the launched app.
+
+After launching the dev server, you should see a link printed to your console that says `Frontend Server (Go here): ... `.
+
+![](https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/dev_server_terminal.png)
+
+You should see the following:
+
+![](https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/frontend_start.png)
+
+
+Its not impressive yet but we're ready to start coding!
+
+## Step 4: Frontend - The basic skeleton
+
+We're going to start off by first writing the skeleton of our frontend and then adding the pdf rendering logic.
+Add the following imports and expose the following properties to the top of your file in the `` tag, delete all the current code and add the following:
+
+```ts
+
+ {#if loading_status}
+
+ {/if}
+
+ {#if _value}
+
+ {:else}
+
+ Upload your PDF
+
+ {/if}
+
+```
+
+You should see the following when you navigate to your app after saving your current changes:
+
+![](https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/frontend_1.png)
+
+## Step 5: Frontend - Nicer Upload Text
+
+The `Upload your PDF` text looks a bit small and barebones.
+Lets customize it!
+
+Create a new file called `PdfUploadText.svelte` and copy the following code.
+Its creating a new div to display our "upload text" with some custom styling.
+
+Tip: Notice that we're leveraging Gradio core's existing css variables here: `var(--size-60)` and `var(--body-text-color-subdued)`. This allows our component to work nicely in light mode and dark mode, as well as with Gradio's built-in themes.
+
+
+```ts
+
+
+
+
+ Drop PDF
+ - or -
+ Click to Upload
+
+
+
+```
+
+Now import `PdfUploadText.svelte` in your `
+
+
+
+
+
+
+```
+
+
+Tip: Exercise for the reader - reduce the code duplication between `Index.svelte` and `Example.svelte` 😊
+
+
+You will not be able to render examples until we make some changes to the backend code in the next step!
+
+## Step 9: The backend
+
+The backend changes needed are smaller.
+We're almost done!
+
+What we're going to do is:
+* Add `change` and `upload` events to our component.
+* Add a `height` property to let users control the height of the PDF.
+* Set the `data_model` of our component to be `FileData`. This is so that Gradio can automatically cache and safely serve any files that are processed by our component.
+* Modify the `preprocess` method to return a string corresponding to the path of our uploaded PDF.
+* Modify the `postprocess` to turn a path to a PDF created in an event handler to a `FileData`.
+
+When all is said an done, your component's backend code should look like this:
+
+```python
+from __future__ import annotations
+from typing import Any, Callable
+
+from gradio.components.base import Component
+from gradio.data_classes import FileData
+from gradio import processing_utils
+
+class PDF(Component):
+
+ EVENTS = ["change", "upload"]
+
+ data_model = FileData
+
+ def __init__(self, value: Any = None, *,
+ height: int | None = None,
+ label: str | None = None, info: str | None = None,
+ show_label: bool | None = None,
+ container: bool = True,
+ scale: int | None = None,
+ min_width: int | None = None,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: list[str] | str | None = None,
+ render: bool = True,
+ load_fn: Callable[..., Any] | None = None,
+ every: float | None = None):
+ super().__init__(value, label=label, info=info,
+ show_label=show_label, container=container,
+ scale=scale, min_width=min_width,
+ interactive=interactive, visible=visible,
+ elem_id=elem_id, elem_classes=elem_classes,
+ render=render, load_fn=load_fn, every=every)
+ self.height = height
+
+ def preprocess(self, payload: FileData) -> str:
+ return payload.path
+
+ def postprocess(self, value: str | None) -> FileData:
+ if not value:
+ return None
+ return FileData(path=value)
+
+ def example_inputs(self):
+ return "https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/fw9.pdf"
+
+ def as_example(self, input_data: str | None) -> str | None:
+ if input_data is None:
+ return None
+ return processing_utils.move_resource_to_block_cache(input_data, self)
+```
+
+## Step 10: Add a demo and publish!
+
+To test our backend code, let's add a more complex demo that performs Document Question and Answering with huggingface transformers.
+
+In our `demo` directory, create a `requirements.txt` file with the following packages
+
+```
+torch
+transformers
+pdf2image
+pytesseract
+```
+
+
+Tip: Remember to install these yourself and restart the dev server! You may need to install extra non-python dependencies for `pdf2image`. See [here](https://pypi.org/project/pdf2image/). Feel free to write your own demo if you have trouble.
+
+
+```python
+import gradio as gr
+from gradio_pdf import PDF
+from pdf2image import convert_from_path
+from transformers import pipeline
+from pathlib import Path
+
+dir_ = Path(__file__).parent
+
+p = pipeline(
+ "document-question-answering",
+ model="impira/layoutlm-document-qa",
+)
+
+def qa(question: str, doc: str) -> str:
+ img = convert_from_path(doc)[0]
+ output = p(img, question)
+ return sorted(output, key=lambda x: x["score"], reverse=True)[0]['answer']
+
+
+demo = gr.Interface(
+ qa,
+ [gr.Textbox(label="Question"), PDF(label="Document")],
+ gr.Textbox(),
+)
+
+demo.launch()
+```
+
+See our demo in action below!
+
+
+
+
+
+Finally lets build our component with `gradio cc build` and publish it with the `gradio cc publish` command!
+This will guide you through the process of uploading your component to [PyPi](https://pypi.org/) and [HuggingFace Spaces](https://huggingface.co/spaces).
+
+
+Tip: You may need to add the following lines to the `Dockerfile` of your HuggingFace Space.
+
+```Dockerfile
+RUN mkdir -p /tmp/cache/
+RUN chmod a+rwx -R /tmp/cache/
+RUN apt-get update && apt-get install -y poppler-utils tesseract-ocr
+
+ENV TRANSFORMERS_CACHE=/tmp/cache/
+```
+
+## Conclusion
+
+In order to use our new component in **any** gradio 4.0 app, simply install it with pip, e.g. `pip install gradio-pdf`. Then you can use it like the built-in `gr.File()` component (except that it will only accept and display PDF files).
+
+Here is a simple demo with the Blocks api:
+
+```python
+import gradio as gr
+from gradio_pdf import PDF
+
+with gr.Blocks() as demo:
+ pdf = PDF(label="Upload a PDF", interactive=True)
+ name = gr.Textbox()
+ pdf.upload(lambda f: f, pdf, name)
+
+demo.launch()
+```
+
+
+I hope you enjoyed this tutorial!
+The complete source code for our component is [here](https://huggingface.co/spaces/freddyaboulton/gradio_pdf/tree/main/src).
+Please don't hesitate to reach out to the gradio community on the [HuggingFace Discord](https://discord.gg/hugging-face-879548962464493619) if you get stuck.
\ No newline at end of file
diff --git a/guides/05_custom-components/08_multimodal-chatbot-part1.md b/guides/05_custom-components/08_multimodal-chatbot-part1.md
new file mode 100644
index 0000000000000000000000000000000000000000..6fc435b142e711e22e55135fd5c7adc8f6d85689
--- /dev/null
+++ b/guides/05_custom-components/08_multimodal-chatbot-part1.md
@@ -0,0 +1,355 @@
+# Build a Custom Multimodal Chatbot - Part 1
+
+This is the first in a two part series where we build a custom Multimodal Chatbot component.
+In part 1, we will modify the Gradio Chatbot component to display text and media files (video, audio, image) in the same message.
+In part 2, we will build a custom Textbox component that will be able to send multimodal messages (text and media files) to the chatbot.
+
+You can follow along with the author of this post as he implements the chatbot component in the following YouTube video!
+
+VIDEO
+
+Here's a preview of what our multimodal chatbot component will look like:
+
+![MultiModal Chatbot](https://gradio-builds.s3.amazonaws.com/assets/MultimodalChatbot.png)
+
+
+## Part 1 - Creating our project
+
+For this demo we will be tweaking the existing Gradio `Chatbot` component to display text and media files in the same message.
+Let's create a new custom component directory by templating off of the `Chatbot` component source code.
+
+```bash
+gradio cc create MultimodalChatbot --template Chatbot
+```
+
+And we're ready to go!
+
+Tip: Make sure to modify the `Author` key in the `pyproject.toml` file.
+
+## Part 2a - The backend data_model
+
+Open up the `multimodalchatbot.py` file in your favorite code editor and let's get started modifying the backend of our component.
+
+The first thing we will do is create the `data_model` of our component.
+The `data_model` is the data format that your python component will receive and send to the javascript client running the UI.
+You can read more about the `data_model` in the [backend guide](./backend).
+
+For our component, each chatbot message will consist of two keys: a `text` key that displays the text message and an optional list of media files that can be displayed underneath the text.
+
+Import the `FileData` and `GradioModel` classes from `gradio.data_classes` and modify the existing `ChatbotData` class to look like the following:
+
+```python
+class FileMessage(GradioModel):
+ file: FileData
+ alt_text: Optional[str] = None
+
+
+class MultimodalMessage(GradioModel):
+ text: Optional[str] = None
+ files: Optional[List[FileMessage]] = None
+
+
+class ChatbotData(GradioRootModel):
+ root: List[Tuple[Optional[MultimodalMessage], Optional[MultimodalMessage]]]
+
+
+class MultimodalChatbot(Component):
+ ...
+ data_model = ChatbotData
+```
+
+
+Tip: The `data_model`s are implemented using `Pydantic V2`. Read the documentation [here](https://docs.pydantic.dev/latest/).
+
+We've done the hardest part already!
+
+## Part 2b - The pre and postprocess methods
+
+For the `preprocess` method, we will keep it simple and pass a list of `MultimodalMessage`s to the python functions that use this component as input.
+This will let users of our component access the chatbot data with `.text` and `.files` attributes.
+This is a design choice that you can modify in your implementation!
+We can return the list of messages with the `root` property of the `ChatbotData` like so:
+
+```python
+def preprocess(
+ self,
+ payload: ChatbotData | None,
+) -> List[MultimodalMessage] | None:
+ if payload is None:
+ return payload
+ return payload.root
+```
+
+
+Tip: Learn about the reasoning behind the `preprocess` and `postprocess` methods in the [key concepts guide](./key-component-concepts)
+
+In the `postprocess` method we will coerce each message returned by the python function to be a `MultimodalMessage` class.
+We will also clean up any indentation in the `text` field so that it can be properly displayed as markdown in the frontend.
+
+We can leave the `postprocess` method as is and modify the `_postprocess_chat_messages`
+
+```python
+def _postprocess_chat_messages(
+ self, chat_message: MultimodalMessage | dict | None
+) -> MultimodalMessage | None:
+ if chat_message is None:
+ return None
+ if isinstance(chat_message, dict):
+ chat_message = MultimodalMessage(**chat_message)
+ chat_message.text = inspect.cleandoc(chat_message.text or "")
+ for file_ in chat_message.files:
+ file_.file.mime_type = client_utils.get_mimetype(file_.file.path)
+ return chat_message
+```
+
+Before we wrap up with the backend code, let's modify the `example_inputs` method to return a valid dictionary representation of the `ChatbotData`:
+
+```python
+def example_inputs(self) -> Any:
+ return [[{"text": "Hello!", "files": []}, None]]
+```
+
+Congrats - the backend is complete!
+
+## Part 3a - The Index.svelte file
+
+The frontend for the `Chatbot` component is divided into two parts - the `Index.svelte` file and the `shared/Chatbot.svelte` file.
+The `Index.svelte` file applies some processing to the data received from the server and then delegates the rendering of the conversation to the `shared/Chatbot.svelte` file.
+First we will modify the `Index.svelte` file to apply processing to the new data type the backend will return.
+
+Let's begin by porting our custom types from our python `data_model` to typescript.
+Open `frontend/shared/utils.ts` and add the following type definitions at the top of the file:
+
+```ts
+export type FileMessage = {
+ file: FileData;
+ alt_text?: string;
+};
+
+
+export type MultimodalMessage = {
+ text: string;
+ files?: FileMessage[];
+}
+```
+
+Now let's import them in `Index.svelte` and modify the type annotations for `value` and `_value`.
+
+```ts
+import type { FileMessage, MultimodalMessage } from "./shared/utils";
+
+export let value: [
+ MultimodalMessage | null,
+ MultimodalMessage | null
+][] = [];
+
+let _value: [
+ MultimodalMessage | null,
+ MultimodalMessage | null
+][];
+```
+
+We need to normalize each message to make sure each file has a proper URL to fetch its contents from.
+We also need to format any embedded file links in the `text` key.
+Let's add a `process_message` utility function and apply it whenever the `value` changes.
+
+```ts
+function process_message(msg: MultimodalMessage | null): MultimodalMessage | null {
+ if (msg === null) {
+ return msg;
+ }
+ msg.text = redirect_src_url(msg.text);
+ msg.files = msg.files.map(normalize_messages);
+ return msg;
+}
+
+$: _value = value
+ ? value.map(([user_msg, bot_msg]) => [
+ process_message(user_msg),
+ process_message(bot_msg)
+ ])
+ : [];
+```
+
+## Part 3b - the Chatbot.svelte file
+
+Let's begin similarly to the `Index.svelte` file and let's first modify the type annotations.
+Import `Mulimodal` message at the top of the `
+
+
+
+```
+
+Note that you should generally use the latest version of `@gradio/lite` that is available. You can see the [versions available here](https://www.jsdelivr.com/package/npm/@gradio/lite?tab=files).
+
+### 2. Create the `` tags
+
+Somewhere in the body of your HTML page (wherever you'd like the Gradio app to be rendered), create opening and closing `` tags.
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+Note: you can add the `theme` attribute to the `` tag to force the theme to be dark or light (by default, it respects the system theme). E.g.
+
+```html
+
+...
+
+```
+
+### 3. Write your Gradio app inside of the tags
+
+Now, write your Gradio app as you would normally, in Python! Keep in mind that since this is Python, whitespace and indentations matter.
+
+```html
+
+
+
+
+
+
+
+ import gradio as gr
+
+ def greet(name):
+ return "Hello, " + name + "!"
+
+ gr.Interface(greet, "textbox", "textbox").launch()
+
+
+
+```
+
+And that's it! You should now be able to open your HTML page in the browser and see the Gradio app rendered! Note that it may take a little while for the Gradio app to load initially since Pyodide can take a while to install in your browser.
+
+**Note on debugging**: to see any errors in your Gradio-lite application, open the inspector in your web browser. All errors (including Python errors) will be printed there.
+
+## More Examples: Adding Additional Files and Requirements
+
+What if you want to create a Gradio app that spans multiple files? Or that has custom Python requirements? Both are possible with `@gradio/lite`!
+
+### Multiple Files
+
+Adding multiple files within a `@gradio/lite` app is very straightrward: use the `` tag. You can have as many `` tags as you want, but each one needs to have a `name` attribute and the entry point to your Gradio app should have the `entrypoint` attribute.
+
+Here's an example:
+
+```html
+
+
+
+import gradio as gr
+from utils import add
+
+demo = gr.Interface(fn=add, inputs=["number", "number"], outputs="number")
+
+demo.launch()
+
+
+
+def add(a, b):
+ return a + b
+
+
+
+
+```
+
+### Additional Requirements
+
+If your Gradio app has additional requirements, it is usually possible to [install them in the browser using micropip](https://pyodide.org/en/stable/usage/loading-packages.html#loading-packages). We've created a wrapper to make this paticularly convenient: simply list your requirements in the same syntax as a `requirements.txt` and enclose them with `` tags.
+
+Here, we install `transformers_js_py` to run a text classification model directly in the browser!
+
+```html
+
+
+
+transformers_js_py
+
+
+
+from transformers_js import import_transformers_js
+import gradio as gr
+
+transformers = await import_transformers_js()
+pipeline = transformers.pipeline
+pipe = await pipeline('sentiment-analysis')
+
+async def classify(text):
+ return await pipe(text)
+
+demo = gr.Interface(classify, "textbox", "json")
+demo.launch()
+
+
+
+
+```
+
+**Try it out**: You can see this example running in [this Hugging Face Static Space](https://huggingface.co/spaces/abidlabs/gradio-lite-classify), which lets you host static (serverless) web applications for free. Visit the page and you'll be able to run a machine learning model without internet access!
+
+## Benefits of Using `@gradio/lite`
+
+### 1. Serverless Deployment
+The primary advantage of @gradio/lite is that it eliminates the need for server infrastructure. This simplifies deployment, reduces server-related costs, and makes it easier to share your Gradio applications with others.
+
+### 2. Low Latency
+By running in the browser, @gradio/lite offers low-latency interactions for users. There's no need for data to travel to and from a server, resulting in faster responses and a smoother user experience.
+
+### 3. Privacy and Security
+Since all processing occurs within the user's browser, `@gradio/lite` enhances privacy and security. User data remains on their device, providing peace of mind regarding data handling.
+
+### Limitations
+
+* Currently, the biggest limitation in using `@gradio/lite` is that your Gradio apps will generally take more time (usually 5-15 seconds) to load initially in the browser. This is because the browser needs to load the Pyodide runtime before it can render Python code.
+
+* Not every Python package is supported by Pyodide. While `gradio` and many other popular packages (including `numpy`, `scikit-learn`, and `transformers-js`) can be installed in Pyodide, if your app has many dependencies, its worth checking whether whether the dependencies are included in Pyodide, or can be [installed with `micropip`](https://micropip.pyodide.org/en/v0.2.2/project/api.html#micropip.install).
+
+## Try it out!
+
+You can immediately try out `@gradio/lite` by copying and pasting this code in a local `index.html` file and opening it with your browser:
+
+```html
+
+
+
+
+
+
+
+ import gradio as gr
+
+ def greet(name):
+ return "Hello, " + name + "!"
+
+ gr.Interface(greet, "textbox", "textbox").launch()
+
+
+
+```
+
+
+We've also created a playground on the Gradio website that allows you to interactively edit code and see the results immediately!
+
+Playground: https://www.gradio.app/playground
+
+
diff --git a/guides/09_other-tutorials/create-your-own-friends-with-a-gan.md b/guides/09_other-tutorials/create-your-own-friends-with-a-gan.md
new file mode 100644
index 0000000000000000000000000000000000000000..127ea5c4ebcfbaeadac1c68319ac6cbd8dbcb08d
--- /dev/null
+++ b/guides/09_other-tutorials/create-your-own-friends-with-a-gan.md
@@ -0,0 +1,219 @@
+# Create Your Own Friends with a GAN
+
+Related spaces: https://huggingface.co/spaces/NimaBoscarino/cryptopunks, https://huggingface.co/spaces/nateraw/cryptopunks-generator
+Tags: GAN, IMAGE, HUB
+
+Contributed by Nima Boscarino and Nate Raw
+
+## Introduction
+
+It seems that cryptocurrencies, [NFTs](https://www.nytimes.com/interactive/2022/03/18/technology/nft-guide.html), and the web3 movement are all the rage these days! Digital assets are being listed on marketplaces for astounding amounts of money, and just about every celebrity is debuting their own NFT collection. While your crypto assets [may be taxable, such as in Canada](https://www.canada.ca/en/revenue-agency/programs/about-canada-revenue-agency-cra/compliance/digital-currency/cryptocurrency-guide.html), today we'll explore some fun and tax-free ways to generate your own assortment of procedurally generated [CryptoPunks](https://www.larvalabs.com/cryptopunks).
+
+Generative Adversarial Networks, often known just as _GANs_, are a specific class of deep-learning models that are designed to learn from an input dataset to create (_generate!_) new material that is convincingly similar to elements of the original training set. Famously, the website [thispersondoesnotexist.com](https://thispersondoesnotexist.com/) went viral with lifelike, yet synthetic, images of people generated with a model called StyleGAN2. GANs have gained traction in the machine learning world, and are now being used to generate all sorts of images, text, and even [music](https://salu133445.github.io/musegan/)!
+
+Today we'll briefly look at the high-level intuition behind GANs, and then we'll build a small demo around a pre-trained GAN to see what all the fuss is about. Here's a [peek](https://nimaboscarino-cryptopunks.hf.space) at what we're going to be putting together.
+
+### Prerequisites
+
+Make sure you have the `gradio` Python package already [installed](/getting_started). To use the pretrained model, also install `torch` and `torchvision`.
+
+## GANs: a very brief introduction
+
+Originally proposed in [Goodfellow et al. 2014](https://arxiv.org/abs/1406.2661), GANs are made up of neural networks which compete with the intention of outsmarting each other. One network, known as the _generator_, is responsible for generating images. The other network, the _discriminator_, receives an image at a time from the generator along with a **real** image from the training data set. The discriminator then has to guess: which image is the fake?
+
+The generator is constantly training to create images which are trickier for the discriminator to identify, while the discriminator raises the bar for the generator every time it correctly detects a fake. As the networks engage in this competitive (_adversarial!_) relationship, the images that get generated improve to the point where they become indistinguishable to human eyes!
+
+For a more in-depth look at GANs, you can take a look at [this excellent post on Analytics Vidhya](https://www.analyticsvidhya.com/blog/2021/06/a-detailed-explanation-of-gan-with-implementation-using-tensorflow-and-keras/) or this [PyTorch tutorial](https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html). For now, though, we'll dive into a demo!
+
+## Step 1 — Create the Generator model
+
+To generate new images with a GAN, you only need the generator model. There are many different architectures that the generator could use, but for this demo we'll use a pretrained GAN generator model with the following architecture:
+
+```python
+from torch import nn
+
+class Generator(nn.Module):
+ # Refer to the link below for explanations about nc, nz, and ngf
+ # https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#inputs
+ def __init__(self, nc=4, nz=100, ngf=64):
+ super(Generator, self).__init__()
+ self.network = nn.Sequential(
+ nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False),
+ nn.BatchNorm2d(ngf * 4),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False),
+ nn.BatchNorm2d(ngf * 2),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False),
+ nn.BatchNorm2d(ngf),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),
+ nn.Tanh(),
+ )
+
+ def forward(self, input):
+ output = self.network(input)
+ return output
+```
+
+We're taking the generator from [this repo by @teddykoker](https://github.com/teddykoker/cryptopunks-gan/blob/main/train.py#L90), where you can also see the original discriminator model structure.
+
+After instantiating the model, we'll load in the weights from the Hugging Face Hub, stored at [nateraw/cryptopunks-gan](https://huggingface.co/nateraw/cryptopunks-gan):
+
+```python
+from huggingface_hub import hf_hub_download
+import torch
+
+model = Generator()
+weights_path = hf_hub_download('nateraw/cryptopunks-gan', 'generator.pth')
+model.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu'))) # Use 'cuda' if you have a GPU available
+```
+
+## Step 2 — Defining a `predict` function
+
+The `predict` function is the key to making Gradio work! Whatever inputs we choose through the Gradio interface will get passed through our `predict` function, which should operate on the inputs and generate outputs that we can display with Gradio output components. For GANs it's common to pass random noise into our model as the input, so we'll generate a tensor of random numbers and pass that through the model. We can then use `torchvision`'s `save_image` function to save the output of the model as a `png` file, and return the file name:
+
+```python
+from torchvision.utils import save_image
+
+def predict(seed):
+ num_punks = 4
+ torch.manual_seed(seed)
+ z = torch.randn(num_punks, 100, 1, 1)
+ punks = model(z)
+ save_image(punks, "punks.png", normalize=True)
+ return 'punks.png'
+```
+
+We're giving our `predict` function a `seed` parameter, so that we can fix the random tensor generation with a seed. We'll then be able to reproduce punks if we want to see them again by passing in the same seed.
+
+_Note!_ Our model needs an input tensor of dimensions 100x1x1 to do a single inference, or (BatchSize)x100x1x1 for generating a batch of images. In this demo we'll start by generating 4 punks at a time.
+
+## Step 3 — Creating a Gradio interface
+
+At this point you can even run the code you have with `predict()`, and you'll find your freshly generated punks in your file system at `./punks.png`. To make a truly interactive demo, though, we'll build out a simple interface with Gradio. Our goals here are to:
+
+- Set a slider input so users can choose the "seed" value
+- Use an image component for our output to showcase the generated punks
+- Use our `predict()` to take the seed and generate the images
+
+With `gr.Interface()`, we can define all of that with a single function call:
+
+```python
+import gradio as gr
+
+gr.Interface(
+ predict,
+ inputs=[
+ gr.Slider(0, 1000, label='Seed', default=42),
+ ],
+ outputs="image",
+).launch()
+```
+
+
+## Step 4 — Even more punks!
+
+Generating 4 punks at a time is a good start, but maybe we'd like to control how many we want to make each time. Adding more inputs to our Gradio interface is as simple as adding another item to the `inputs` list that we pass to `gr.Interface`:
+
+```python
+gr.Interface(
+ predict,
+ inputs=[
+ gr.Slider(0, 1000, label='Seed', default=42),
+ gr.Slider(4, 64, label='Number of Punks', step=1, default=10), # Adding another slider!
+ ],
+ outputs="image",
+).launch()
+```
+
+The new input will be passed to our `predict()` function, so we have to make some changes to that function to accept a new parameter:
+
+```python
+def predict(seed, num_punks):
+ torch.manual_seed(seed)
+ z = torch.randn(num_punks, 100, 1, 1)
+ punks = model(z)
+ save_image(punks, "punks.png", normalize=True)
+ return 'punks.png'
+```
+
+When you relaunch your interface, you should see a second slider that'll let you control the number of punks!
+
+## Step 5 - Polishing it up
+
+Your Gradio app is pretty much good to go, but you can add a few extra things to really make it ready for the spotlight ✨
+
+We can add some examples that users can easily try out by adding this to the `gr.Interface`:
+
+```python
+gr.Interface(
+ # ...
+ # keep everything as it is, and then add
+ examples=[[123, 15], [42, 29], [456, 8], [1337, 35]],
+).launch(cache_examples=True) # cache_examples is optional
+```
+
+The `examples` parameter takes a list of lists, where each item in the sublists is ordered in the same order that we've listed the `inputs`. So in our case, `[seed, num_punks]`. Give it a try!
+
+You can also try adding a `title`, `description`, and `article` to the `gr.Interface`. Each of those parameters accepts a string, so try it out and see what happens 👀 `article` will also accept HTML, as [explored in a previous guide](/guides/key-features/#descriptive-content)!
+
+When you're all done, you may end up with something like [this](https://nimaboscarino-cryptopunks.hf.space).
+
+For reference, here is our full code:
+
+```python
+import torch
+from torch import nn
+from huggingface_hub import hf_hub_download
+from torchvision.utils import save_image
+import gradio as gr
+
+class Generator(nn.Module):
+ # Refer to the link below for explanations about nc, nz, and ngf
+ # https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#inputs
+ def __init__(self, nc=4, nz=100, ngf=64):
+ super(Generator, self).__init__()
+ self.network = nn.Sequential(
+ nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False),
+ nn.BatchNorm2d(ngf * 4),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False),
+ nn.BatchNorm2d(ngf * 2),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False),
+ nn.BatchNorm2d(ngf),
+ nn.ReLU(True),
+ nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),
+ nn.Tanh(),
+ )
+
+ def forward(self, input):
+ output = self.network(input)
+ return output
+
+model = Generator()
+weights_path = hf_hub_download('nateraw/cryptopunks-gan', 'generator.pth')
+model.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu'))) # Use 'cuda' if you have a GPU available
+
+def predict(seed, num_punks):
+ torch.manual_seed(seed)
+ z = torch.randn(num_punks, 100, 1, 1)
+ punks = model(z)
+ save_image(punks, "punks.png", normalize=True)
+ return 'punks.png'
+
+gr.Interface(
+ predict,
+ inputs=[
+ gr.Slider(0, 1000, label='Seed', default=42),
+ gr.Slider(4, 64, label='Number of Punks', step=1, default=10),
+ ],
+ outputs="image",
+ examples=[[123, 15], [42, 29], [456, 8], [1337, 35]],
+).launch(cache_examples=True)
+```
+
+---
+
+Congratulations! You've built out your very own GAN-powered CryptoPunks generator, with a fancy Gradio interface that makes it easy for anyone to use. Now you can [scour the Hub for more GANs](https://huggingface.co/models?other=gan) (or train your own) and continue making even more awesome demos 🤗
diff --git a/guides/09_other-tutorials/developing-faster-with-reload-mode.md b/guides/09_other-tutorials/developing-faster-with-reload-mode.md
new file mode 100644
index 0000000000000000000000000000000000000000..7cf5db3bb67b210cf3f5854e17308dc4c5d65c38
--- /dev/null
+++ b/guides/09_other-tutorials/developing-faster-with-reload-mode.md
@@ -0,0 +1,147 @@
+# Developing Faster with Auto-Reloading
+
+**Prerequisite**: This Guide requires you to know about Blocks. Make sure to [read the Guide to Blocks first](https://gradio.app/blocks-and-event-listeners).
+
+This guide covers auto reloading, reloading in a Python IDE, and using gradio with Jupyter Notebooks.
+
+## Why Auto-Reloading?
+
+When you are building a Gradio demo, particularly out of Blocks, you may find it cumbersome to keep re-running your code to test your changes.
+
+To make it faster and more convenient to write your code, we've made it easier to "reload" your Gradio apps instantly when you are developing in a **Python IDE** (like VS Code, Sublime Text, PyCharm, or so on) or generally running your Python code from the terminal. We've also developed an analogous "magic command" that allows you to re-run cells faster if you use **Jupyter Notebooks** (or any similar environment like Colab).
+
+This short Guide will cover both of these methods, so no matter how you write Python, you'll leave knowing how to build Gradio apps faster.
+
+## Python IDE Reload 🔥
+
+If you are building Gradio Blocks using a Python IDE, your file of code (let's name it `run.py`) might look something like this:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Markdown("# Greetings from Gradio!")
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+
+ inp.change(fn=lambda x: f"Welcome, {x}!",
+ inputs=inp,
+ outputs=out)
+
+if __name__ == "__main__":
+ demo.launch()
+```
+
+The problem is that anytime that you want to make a change to your layout, events, or components, you have to close and rerun your app by writing `python run.py`.
+
+Instead of doing this, you can run your code in **reload mode** by changing 1 word: `python` to `gradio`:
+
+In the terminal, run `gradio run.py`. That's it!
+
+Now, you'll see that after you'll see something like this:
+
+```bash
+Watching: '/Users/freddy/sources/gradio/gradio', '/Users/freddy/sources/gradio/demo/'
+
+Running on local URL: http://127.0.0.1:7860
+```
+
+The important part here is the line that says `Watching...` What's happening here is that Gradio will be observing the directory where `run.py` file lives, and if the file changes, it will automatically rerun the file for you. So you can focus on writing your code, and your Gradio demo will refresh automatically 🥳
+
+⚠️ Warning: the `gradio` command does not detect the parameters passed to the `launch()` methods because the `launch()` method is never called in reload mode. For example, setting `auth`, or `show_error` in `launch()` will not be reflected in the app.
+
+There is one important thing to keep in mind when using the reload mode: Gradio specifically looks for a Gradio Blocks/Interface demo called `demo` in your code. If you have named your demo something else, you will need to pass in the name of your demo as the 2nd parameter in your code. So if your `run.py` file looked like this:
+
+```python
+import gradio as gr
+
+with gr.Blocks() as my_demo:
+ gr.Markdown("# Greetings from Gradio!")
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+
+ inp.change(fn=lambda x: f"Welcome, {x}!",
+ inputs=inp,
+ outputs=out)
+
+if __name__ == "__main__":
+ my_demo.launch()
+```
+
+Then you would launch it in reload mode like this: `gradio run.py my_demo`.
+
+By default, the Gradio use UTF-8 encoding for scripts. **For reload mode**, If you are using encoding formats other than UTF-8 (such as cp1252), make sure you've done like this:
+
+1. Configure encoding declaration of python script, for example: `# -*- coding: cp1252 -*-`
+2. Confirm that your code editor has identified that encoding format.
+3. Run like this: `gradio run.py --encoding cp1252`
+
+🔥 If your application accepts command line arguments, you can pass them in as well. Here's an example:
+
+```python
+import gradio as gr
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--name", type=str, default="User")
+args, unknown = parser.parse_known_args()
+
+with gr.Blocks() as demo:
+ gr.Markdown(f"# Greetings {args.name}!")
+ inp = gr.Textbox()
+ out = gr.Textbox()
+
+ inp.change(fn=lambda x: x, inputs=inp, outputs=out)
+
+if __name__ == "__main__":
+ demo.launch()
+```
+
+Which you could run like this: `gradio run.py --name Gretel`
+
+As a small aside, this auto-reloading happens if you change your `run.py` source code or the Gradio source code. Meaning that this can be useful if you decide to [contribute to Gradio itself](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) ✅
+
+## Jupyter Notebook Magic 🔮
+
+What about if you use Jupyter Notebooks (or Colab Notebooks, etc.) to develop code? We got something for you too!
+
+We've developed a **magic command** that will create and run a Blocks demo for you. To use this, load the gradio extension at the top of your notebook:
+
+`%load_ext gradio`
+
+Then, in the cell that you are developing your Gradio demo, simply write the magic command **`%%blocks`** at the top, and then write the layout and components like you would normally:
+
+```py
+%%blocks
+
+import gradio as gr
+
+with gr.Blocks() as demo:
+ gr.Markdown(f"# Greetings {args.name}!")
+ inp = gr.Textbox()
+ out = gr.Textbox()
+
+ inp.change(fn=lambda x: x, inputs=inp, outputs=out)
+```
+
+Notice that:
+
+- You do not need to launch your demo — Gradio does that for you automatically!
+
+- Every time you rerun the cell, Gradio will re-render your app on the same port and using the same underlying web server. This means you'll see your changes _much, much faster_ than if you were rerunning the cell normally.
+
+Here's what it looks like in a jupyter notebook:
+
+![](https://gradio-builds.s3.amazonaws.com/demo-files/jupyter_reload.gif)
+
+🪄 This works in colab notebooks too! [Here's a colab notebook](https://colab.research.google.com/drive/1zAuWoiTIb3O2oitbtVb2_ekv1K6ggtC1?usp=sharing) where you can see the Blocks magic in action. Try making some changes and re-running the cell with the Gradio code!
+
+The Notebook Magic is now the author's preferred way of building Gradio demos. Regardless of how you write Python code, we hope either of these methods will give you a much better development experience using Gradio.
+
+---
+
+## Next Steps
+
+Now that you know how to develop quickly using Gradio, start building your own!
+
+If you are looking for inspiration, try exploring demos other people have built with Gradio, [browse public Hugging Face Spaces](http://hf.space/) 🤗
diff --git a/guides/09_other-tutorials/how-to-use-3D-model-component.md b/guides/09_other-tutorials/how-to-use-3D-model-component.md
new file mode 100644
index 0000000000000000000000000000000000000000..3e14ee763ba2a38e3cf5ce738c8502cb0c819036
--- /dev/null
+++ b/guides/09_other-tutorials/how-to-use-3D-model-component.md
@@ -0,0 +1,72 @@
+# How to Use the 3D Model Component
+
+Related spaces: https://huggingface.co/spaces/gradio/Model3D, https://huggingface.co/spaces/gradio/PIFu-Clothed-Human-Digitization, https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj
+Tags: VISION, IMAGE
+
+## Introduction
+
+3D models are becoming more popular in machine learning and make for some of the most fun demos to experiment with. Using `gradio`, you can easily build a demo of your 3D image model and share it with anyone. The Gradio 3D Model component accepts 3 file types including: _.obj_, _.glb_, & _.gltf_.
+
+This guide will show you how to build a demo for your 3D image model in a few lines of code; like the one below. Play around with 3D object by clicking around, dragging and zooming:
+
+
+
+### Prerequisites
+
+Make sure you have the `gradio` Python package already [installed](https://gradio.app/guides/quickstart).
+
+## Taking a Look at the Code
+
+Let's take a look at how to create the minimal interface above. The prediction function in this case will just return the original 3D model mesh, but you can change this function to run inference on your machine learning model. We'll take a look at more complex examples below.
+
+```python
+import gradio as gr
+import os
+
+
+def load_mesh(mesh_file_name):
+ return mesh_file_name
+
+
+demo = gr.Interface(
+ fn=load_mesh,
+ inputs=gr.Model3D(),
+ outputs=gr.Model3D(
+ clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model"),
+ examples=[
+ [os.path.join(os.path.dirname(__file__), "files/Bunny.obj")],
+ [os.path.join(os.path.dirname(__file__), "files/Duck.glb")],
+ [os.path.join(os.path.dirname(__file__), "files/Fox.gltf")],
+ [os.path.join(os.path.dirname(__file__), "files/face.obj")],
+ ],
+)
+
+if __name__ == "__main__":
+ demo.launch()
+```
+
+Let's break down the code above:
+
+`load_mesh`: This is our 'prediction' function and for simplicity, this function will take in the 3D model mesh and return it.
+
+Creating the Interface:
+
+- `fn`: the prediction function that is used when the user clicks submit. In our case this is the `load_mesh` function.
+- `inputs`: create a model3D input component. The input expects an uploaded file as a {str} filepath.
+- `outputs`: create a model3D output component. The output component also expects a file as a {str} filepath.
+ - `clear_color`: this is the background color of the 3D model canvas. Expects RGBa values.
+ - `label`: the label that appears on the top left of the component.
+- `examples`: list of 3D model files. The 3D model component can accept _.obj_, _.glb_, & _.gltf_ file types.
+- `cache_examples`: saves the predicted output for the examples, to save time on inference.
+
+## Exploring a more complex Model3D Demo:
+
+Below is a demo that uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object. Take a look at the [app.py](https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj/blob/main/app.py) file for a peek into the code and the model prediction function.
+
+
+---
+
+And you're done! That's all the code you need to build an interface for your Model3D model. Here are some references that you may find useful:
+
+- Gradio's ["Getting Started" guide](https://gradio.app/getting_started/)
+- The first [3D Model Demo](https://huggingface.co/spaces/gradio/Model3D) and [complete code](https://huggingface.co/spaces/gradio/Model3D/tree/main) (on Hugging Face Spaces)
diff --git a/guides/09_other-tutorials/installing-gradio-in-a-virtual-environment.md b/guides/09_other-tutorials/installing-gradio-in-a-virtual-environment.md
new file mode 100644
index 0000000000000000000000000000000000000000..6487db8204c2b1c35cc18f3568cf3af5e95e619e
--- /dev/null
+++ b/guides/09_other-tutorials/installing-gradio-in-a-virtual-environment.md
@@ -0,0 +1,100 @@
+# Installing Gradio in a Virtual Environment
+
+Tags: INSTALLATION
+
+In this guide, we will describe step-by-step how to install `gradio` within a virtual environment. This guide will cover both Windows and MacOS/Linux systems.
+
+## Virtual Environments
+
+A virtual environment in Python is a self-contained directory that holds a Python installation for a particular version of Python, along with a number of additional packages. This environment is isolated from the main Python installation and other virtual environments. Each environment can have its own independent set of installed Python packages, which allows you to maintain different versions of libraries for different projects without conflicts.
+
+
+Using virtual environments ensures that you can work on multiple Python projects on the same machine without any conflicts. This is particularly useful when different projects require different versions of the same library. It also simplifies dependency management and enhances reproducibility, as you can easily share the requirements of your project with others.
+
+
+## Installing Gradio on Windows
+
+To install Gradio on a Windows system in a virtual environment, follow these steps:
+
+1. **Install Python**: Ensure you have Python 3.8 or higher installed. You can download it from [python.org](https://www.python.org/). You can verify the installation by running `python --version` or `python3 --version` in Command Prompt.
+
+
+2. **Create a Virtual Environment**:
+ Open Command Prompt and navigate to your project directory. Then create a virtual environment using the following command:
+
+ ```bash
+ python -m venv gradio-env
+ ```
+
+ This command creates a new directory `gradio-env` in your project folder, containing a fresh Python installation.
+
+3. **Activate the Virtual Environment**:
+ To activate the virtual environment, run:
+
+ ```bash
+ .\gradio-env\Scripts\activate
+ ```
+
+ Your command prompt should now indicate that you are working inside `gradio-env`. Note: you can choose a different name than `gradio-env` for your virtual environment in this step.
+
+
+4. **Install Gradio**:
+ Now, you can install Gradio using pip:
+
+ ```bash
+ pip install gradio
+ ```
+
+5. **Verification**:
+ To verify the installation, run `python` and then type:
+
+ ```python
+ import gradio as gr
+ print(gr.__version__)
+ ```
+
+ This will display the installed version of Gradio.
+
+## Installing Gradio on MacOS/Linux
+
+The installation steps on MacOS and Linux are similar to Windows but with some differences in commands.
+
+1. **Install Python**:
+ Python usually comes pre-installed on MacOS and most Linux distributions. You can verify the installation by running `python --version` in the terminal (note that depending on how Python is installed, you might have to use `python3` instead of `python` throughout these steps).
+
+ Ensure you have Python 3.8 or higher installed. If you do not have it installed, you can download it from [python.org](https://www.python.org/).
+
+2. **Create a Virtual Environment**:
+ Open Terminal and navigate to your project directory. Then create a virtual environment using:
+
+ ```bash
+ python -m venv gradio-env
+ ```
+
+ Note: you can choose a different name than `gradio-env` for your virtual environment in this step.
+
+3. **Activate the Virtual Environment**:
+ To activate the virtual environment on MacOS/Linux, use:
+
+ ```bash
+ source gradio-env/bin/activate
+ ```
+
+4. **Install Gradio**:
+ With the virtual environment activated, install Gradio using pip:
+
+ ```bash
+ pip install gradio
+ ```
+
+5. **Verification**:
+ To verify the installation, run `python` and then type:
+
+ ```python
+ import gradio as gr
+ print(gr.__version__)
+ ```
+
+ This will display the installed version of Gradio.
+
+By following these steps, you can successfully install Gradio in a virtual environment on your operating system, ensuring a clean and managed workspace for your Python projects.
\ No newline at end of file
diff --git a/guides/09_other-tutorials/named-entity-recognition.md b/guides/09_other-tutorials/named-entity-recognition.md
new file mode 100644
index 0000000000000000000000000000000000000000..35108d0c66aa76fa223afb3cdfcf3ab3044dd0e8
--- /dev/null
+++ b/guides/09_other-tutorials/named-entity-recognition.md
@@ -0,0 +1,80 @@
+# Named-Entity Recognition
+
+Related spaces: https://huggingface.co/spaces/rajistics/biobert_ner_demo, https://huggingface.co/spaces/abidlabs/ner, https://huggingface.co/spaces/rajistics/Financial_Analyst_AI
+Tags: NER, TEXT, HIGHLIGHT
+
+## Introduction
+
+Named-entity recognition (NER), also known as token classification or text tagging, is the task of taking a sentence and classifying every word (or "token") into different categories, such as names of people or names of locations, or different parts of speech.
+
+For example, given the sentence:
+
+> Does Chicago have any Pakistani restaurants?
+
+A named-entity recognition algorithm may identify:
+
+- "Chicago" as a **location**
+- "Pakistani" as an **ethnicity**
+
+and so on.
+
+Using `gradio` (specifically the `HighlightedText` component), you can easily build a web demo of your NER model and share that with the rest of your team.
+
+Here is an example of a demo that you'll be able to build:
+
+$demo_ner_pipeline
+
+This tutorial will show how to take a pretrained NER model and deploy it with a Gradio interface. We will show two different ways to use the `HighlightedText` component -- depending on your NER model, either of these two ways may be easier to learn!
+
+### Prerequisites
+
+Make sure you have the `gradio` Python package already [installed](/getting_started). You will also need a pretrained named-entity recognition model. You can use your own, while in this tutorial, we will use one from the `transformers` library.
+
+### Approach 1: List of Entity Dictionaries
+
+Many named-entity recognition models output a list of dictionaries. Each dictionary consists of an _entity_, a "start" index, and an "end" index. This is, for example, how NER models in the `transformers` library operate:
+
+```py
+from transformers import pipeline
+ner_pipeline = pipeline("ner")
+ner_pipeline("Does Chicago have any Pakistani restaurants")
+```
+
+Output:
+
+```bash
+[{'entity': 'I-LOC',
+ 'score': 0.9988978,
+ 'index': 2,
+ 'word': 'Chicago',
+ 'start': 5,
+ 'end': 12},
+ {'entity': 'I-MISC',
+ 'score': 0.9958592,
+ 'index': 5,
+ 'word': 'Pakistani',
+ 'start': 22,
+ 'end': 31}]
+```
+
+If you have such a model, it is very easy to hook it up to Gradio's `HighlightedText` component. All you need to do is pass in this **list of entities**, along with the **original text** to the model, together as dictionary, with the keys being `"entities"` and `"text"` respectively.
+
+Here is a complete example:
+
+$code_ner_pipeline
+$demo_ner_pipeline
+
+### Approach 2: List of Tuples
+
+An alternative way to pass data into the `HighlightedText` component is a list of tuples. The first element of each tuple should be the word or words that are being classified into a particular entity. The second element should be the entity label (or `None` if they should be unlabeled). The `HighlightedText` component automatically strings together the words and labels to display the entities.
+
+In some cases, this can be easier than the first approach. Here is a demo showing this approach using Spacy's parts-of-speech tagger:
+
+$code_text_analysis
+$demo_text_analysis
+
+---
+
+And you're done! That's all you need to know to build a web-based GUI for your NER model.
+
+Fun tip: you can share your NER demo instantly with others simply by setting `share=True` in `launch()`.
diff --git a/guides/09_other-tutorials/real-time-speech-recognition.md b/guides/09_other-tutorials/real-time-speech-recognition.md
new file mode 100644
index 0000000000000000000000000000000000000000..c84cfbb23f3259a547d9be40a7ae50bff58be13a
--- /dev/null
+++ b/guides/09_other-tutorials/real-time-speech-recognition.md
@@ -0,0 +1,70 @@
+# Real Time Speech Recognition
+
+Tags: ASR, SPEECH, STREAMING
+
+## Introduction
+
+Automatic speech recognition (ASR), the conversion of spoken speech to text, is a very important and thriving area of machine learning. ASR algorithms run on practically every smartphone, and are becoming increasingly embedded in professional workflows, such as digital assistants for nurses and doctors. Because ASR algorithms are designed to be used directly by customers and end users, it is important to validate that they are behaving as expected when confronted with a wide variety of speech patterns (different accents, pitches, and background audio conditions).
+
+Using `gradio`, you can easily build a demo of your ASR model and share that with a testing team, or test it yourself by speaking through the microphone on your device.
+
+This tutorial will show how to take a pretrained speech-to-text model and deploy it with a Gradio interface. We will start with a **_full-context_** model, in which the user speaks the entire audio before the prediction runs. Then we will adapt the demo to make it **_streaming_**, meaning that the audio model will convert speech as you speak.
+
+### Prerequisites
+
+Make sure you have the `gradio` Python package already [installed](/getting_started). You will also need a pretrained speech recognition model. In this tutorial, we will build demos from 2 ASR libraries:
+
+- Transformers (for this, `pip install transformers` and `pip install torch`)
+
+Make sure you have at least one of these installed so that you can follow along the tutorial. You will also need `ffmpeg` [installed on your system](https://www.ffmpeg.org/download.html), if you do not already have it, to process files from the microphone.
+
+Here's how to build a real time speech recognition (ASR) app:
+
+1. [Set up the Transformers ASR Model](#1-set-up-the-transformers-asr-model)
+2. [Create a Full-Context ASR Demo with Transformers](#2-create-a-full-context-asr-demo-with-transformers)
+3. [Create a Streaming ASR Demo with Transformers](#3-create-a-streaming-asr-demo-with-transformers)
+
+## 1. Set up the Transformers ASR Model
+
+First, you will need to have an ASR model that you have either trained yourself or you will need to download a pretrained model. In this tutorial, we will start by using a pretrained ASR model from the model, `whisper`.
+
+Here is the code to load `whisper` from Hugging Face `transformers`.
+
+```python
+from transformers import pipeline
+
+p = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")
+```
+
+That's it!
+
+## 2. Create a Full-Context ASR Demo with Transformers
+
+We will start by creating a _full-context_ ASR demo, in which the user speaks the full audio before using the ASR model to run inference. This is very easy with Gradio -- we simply create a function around the `pipeline` object above.
+
+We will use `gradio`'s built in `Audio` component, configured to take input from the user's microphone and return a filepath for the recorded audio. The output component will be a plain `Textbox`.
+
+$code_asr
+$demo_asr
+
+The `transcribe` function takes a single parameter, `audio`, which is a numpy array of the audio the user recorded. The `pipeline` object expects this in float32 format, so we convert it first to float32, and then extract the transcribed text.
+
+## 3. Create a Streaming ASR Demo with Transformers
+
+To make this a *streaming* demo, we need to make these changes:
+
+1. Set `streaming=True` in the `Audio` component
+2. Set `live=True` in the `Interface`
+3. Add a `state` to the interface to store the recorded audio of a user
+
+Take a look below.
+
+$code_stream_asr
+
+Notice now we have a state variable now, because we need to track all the audio history. `transcribe` gets called whenever there is a new small chunk of audio, but we also need to keep track of all the audio that has been spoken so far in state.
+As the interface runs, the `transcribe` function gets called, with a record of all the previously spoken audio in `stream`, as well as the new chunk of audio as `new_chunk`. We return the new full audio so that can be stored back in state, and we also return the transcription.
+Here we naively append the audio together and simply call the `transcriber` object on the entire audio. You can imagine more efficient ways of handling this, such as re-processing only the last 5 seconds of audio whenever a new chunk of audio received.
+
+$demo_stream_asr
+
+Now the ASR model will run inference as you speak!
\ No newline at end of file
diff --git a/guides/09_other-tutorials/running-background-tasks.md b/guides/09_other-tutorials/running-background-tasks.md
new file mode 100644
index 0000000000000000000000000000000000000000..d4d4ff19f405e9214b159808104e8754f050dcf4
--- /dev/null
+++ b/guides/09_other-tutorials/running-background-tasks.md
@@ -0,0 +1,163 @@
+# Running Background Tasks
+
+Related spaces: https://huggingface.co/spaces/freddyaboulton/gradio-google-forms
+Tags: TASKS, SCHEDULED, TABULAR, DATA
+
+## Introduction
+
+This guide explains how you can run background tasks from your gradio app.
+Background tasks are operations that you'd like to perform outside the request-response
+lifecycle of your app either once or on a periodic schedule.
+Examples of background tasks include periodically synchronizing data to an external database or
+sending a report of model predictions via email.
+
+## Overview
+
+We will be creating a simple "Google-forms-style" application to gather feedback from users of the gradio library.
+We will use a local sqlite database to store our data, but we will periodically synchronize the state of the database
+with a [HuggingFace Dataset](https://huggingface.co/datasets) so that our user reviews are always backed up.
+The synchronization will happen in a background task running every 60 seconds.
+
+At the end of the demo, you'll have a fully working application like this one:
+
+
+
+## Step 1 - Write your database logic 💾
+
+Our application will store the name of the reviewer, their rating of gradio on a scale of 1 to 5, as well as
+any comments they want to share about the library. Let's write some code that creates a database table to
+store this data. We'll also write some functions to insert a review into that table and fetch the latest 10 reviews.
+
+We're going to use the `sqlite3` library to connect to our sqlite database but gradio will work with any library.
+
+The code will look like this:
+
+```python
+DB_FILE = "./reviews.db"
+db = sqlite3.connect(DB_FILE)
+
+# Create table if it doesn't already exist
+try:
+ db.execute("SELECT * FROM reviews").fetchall()
+ db.close()
+except sqlite3.OperationalError:
+ db.execute(
+ '''
+ CREATE TABLE reviews (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
+ name TEXT, review INTEGER, comments TEXT)
+ ''')
+ db.commit()
+ db.close()
+
+def get_latest_reviews(db: sqlite3.Connection):
+ reviews = db.execute("SELECT * FROM reviews ORDER BY id DESC limit 10").fetchall()
+ total_reviews = db.execute("Select COUNT(id) from reviews").fetchone()[0]
+ reviews = pd.DataFrame(reviews, columns=["id", "date_created", "name", "review", "comments"])
+ return reviews, total_reviews
+
+
+def add_review(name: str, review: int, comments: str):
+ db = sqlite3.connect(DB_FILE)
+ cursor = db.cursor()
+ cursor.execute("INSERT INTO reviews(name, review, comments) VALUES(?,?,?)", [name, review, comments])
+ db.commit()
+ reviews, total_reviews = get_latest_reviews(db)
+ db.close()
+ return reviews, total_reviews
+```
+
+Let's also write a function to load the latest reviews when the gradio application loads:
+
+```python
+def load_data():
+ db = sqlite3.connect(DB_FILE)
+ reviews, total_reviews = get_latest_reviews(db)
+ db.close()
+ return reviews, total_reviews
+```
+
+## Step 2 - Create a gradio app ⚡
+
+Now that we have our database logic defined, we can use gradio create a dynamic web page to ask our users for feedback!
+
+```python
+with gr.Blocks() as demo:
+ with gr.Row():
+ with gr.Column():
+ name = gr.Textbox(label="Name", placeholder="What is your name?")
+ review = gr.Radio(label="How satisfied are you with using gradio?", choices=[1, 2, 3, 4, 5])
+ comments = gr.Textbox(label="Comments", lines=10, placeholder="Do you have any feedback on gradio?")
+ submit = gr.Button(value="Submit Feedback")
+ with gr.Column():
+ data = gr.Dataframe(label="Most recently created 10 rows")
+ count = gr.Number(label="Total number of reviews")
+ submit.click(add_review, [name, review, comments], [data, count])
+ demo.load(load_data, None, [data, count])
+```
+
+## Step 3 - Synchronize with HuggingFace Datasets 🤗
+
+We could call `demo.launch()` after step 2 and have a fully functioning application. However,
+our data would be stored locally on our machine. If the sqlite file were accidentally deleted, we'd lose all of our reviews!
+Let's back up our data to a dataset on the HuggingFace hub.
+
+Create a dataset [here](https://huggingface.co/datasets) before proceeding.
+
+Now at the **top** of our script, we'll use the [huggingface hub client library](https://huggingface.co/docs/huggingface_hub/index)
+to connect to our dataset and pull the latest backup.
+
+```python
+TOKEN = os.environ.get('HUB_TOKEN')
+repo = huggingface_hub.Repository(
+ local_dir="data",
+ repo_type="dataset",
+ clone_from="",
+ use_auth_token=TOKEN
+)
+repo.git_pull()
+
+shutil.copyfile("./data/reviews.db", DB_FILE)
+```
+
+Note that you'll have to get an access token from the "Settings" tab of your HuggingFace for the above code to work.
+In the script, the token is securely accessed via an environment variable.
+
+![access_token](https://github.com/gradio-app/gradio/blob/main/guides/assets/access_token.png?raw=true)
+
+Now we will create a background task to synch our local database to the dataset hub every 60 seconds.
+We will use the [AdvancedPythonScheduler](https://apscheduler.readthedocs.io/en/3.x/) to handle the scheduling.
+However, this is not the only task scheduling library available. Feel free to use whatever you are comfortable with.
+
+The function to back up our data will look like this:
+
+```python
+from apscheduler.schedulers.background import BackgroundScheduler
+
+def backup_db():
+ shutil.copyfile(DB_FILE, "./data/reviews.db")
+ db = sqlite3.connect(DB_FILE)
+ reviews = db.execute("SELECT * FROM reviews").fetchall()
+ pd.DataFrame(reviews).to_csv("./data/reviews.csv", index=False)
+ print("updating db")
+ repo.push_to_hub(blocking=False, commit_message=f"Updating data at {datetime.datetime.now()}")
+
+
+scheduler = BackgroundScheduler()
+scheduler.add_job(func=backup_db, trigger="interval", seconds=60)
+scheduler.start()
+```
+
+## Step 4 (Bonus) - Deployment to HuggingFace Spaces
+
+You can use the HuggingFace [Spaces](https://huggingface.co/spaces) platform to deploy this application for free ✨
+
+If you haven't used Spaces before, follow the previous guide [here](/using_hugging_face_integrations).
+You will have to use the `HUB_TOKEN` environment variable as a secret in the Guides.
+
+## Conclusion
+
+Congratulations! You know how to run background tasks from your gradio app on a schedule ⏲️.
+
+Checkout the application running on Spaces [here](https://huggingface.co/spaces/freddyaboulton/gradio-google-forms).
+The complete code is [here](https://huggingface.co/spaces/freddyaboulton/gradio-google-forms/blob/main/app.py)
diff --git a/guides/09_other-tutorials/running-gradio-on-your-web-server-with-nginx.md b/guides/09_other-tutorials/running-gradio-on-your-web-server-with-nginx.md
new file mode 100644
index 0000000000000000000000000000000000000000..72c8a4c7cafd9f98e6581697af3e02348d937efa
--- /dev/null
+++ b/guides/09_other-tutorials/running-gradio-on-your-web-server-with-nginx.md
@@ -0,0 +1,78 @@
+# Running a Gradio App on your Web Server with Nginx
+
+Tags: DEPLOYMENT, WEB SERVER, NGINX
+
+## Introduction
+
+Gradio is a Python library that allows you to quickly create customizable web apps for your machine learning models and data processing pipelines. Gradio apps can be deployed on [Hugging Face Spaces](https://hf.space) for free.
+
+In some cases though, you might want to deploy a Gradio app on your own web server. You might already be using [Nginx](https://www.nginx.com/), a highly performant web server, to serve your website (say `https://www.example.com`), and you want to attach Gradio to a specific subpath on your website (e.g. `https://www.example.com/gradio-demo`).
+
+In this Guide, we will guide you through the process of running a Gradio app behind Nginx on your own web server to achieve this.
+
+**Prerequisites**
+
+1. A Linux web server with [Nginx installed](https://www.nginx.com/blog/setting-up-nginx/) and [Gradio installed](/quickstart)
+2. A working Gradio app saved as a python file on your web server
+
+## Editing your Nginx configuration file
+
+1. Start by editing the Nginx configuration file on your web server. By default, this is located at: `/etc/nginx/nginx.conf`
+
+In the `http` block, add the following line to include server block configurations from a separate file:
+
+```bash
+include /etc/nginx/sites-enabled/*;
+```
+
+2. Create a new file in the `/etc/nginx/sites-available` directory (create the directory if it does not already exist), using a filename that represents your app, for example: `sudo nano /etc/nginx/sites-available/my_gradio_app`
+
+3. Paste the following into your file editor:
+
+```bash
+server {
+ listen 80;
+ server_name example.com www.example.com; # Change this to your domain name
+
+ location /gradio-demo/ { # Change this if you'd like to server your Gradio app on a different path
+ proxy_pass http://127.0.0.1:7860/; # Change this if your Gradio app will be running on a different port
+ proxy_buffering off;
+ proxy_redirect off;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $host;
+ }
+}
+```
+
+## Run your Gradio app on your web server
+
+1. Before you launch your Gradio app, you'll need to set the `root_path` to be the same as the subpath that you specified in your nginx configuration. This is necessary for Gradio to run on any subpath besides the root of the domain.
+
+Here's a simple example of a Gradio app with a custom `root_path`:
+
+```python
+import gradio as gr
+import time
+
+def test(x):
+time.sleep(4)
+return x
+
+gr.Interface(test, "textbox", "textbox").queue().launch(root_path="/gradio-demo")
+```
+
+2. Start a `tmux` session by typing `tmux` and pressing enter (optional)
+
+It's recommended that you run your Gradio app in a `tmux` session so that you can keep it running in the background easily
+
+3. Then, start your Gradio app. Simply type in `python` followed by the name of your Gradio python file. By default, your app will run on `localhost:7860`, but if it starts on a different port, you will need to update the nginx configuration file above.
+
+## Restart Nginx
+
+1. If you are in a tmux session, exit by typing CTRL+B (or CMD+B), followed by the "D" key.
+
+2. Finally, restart nginx by running `sudo systemctl restart nginx`.
+
+And that's it! If you visit `https://example.com/gradio-demo` on your browser, you should see your Gradio app running there
diff --git a/guides/09_other-tutorials/setting-up-a-demo-for-maximum-performance.md b/guides/09_other-tutorials/setting-up-a-demo-for-maximum-performance.md
new file mode 100644
index 0000000000000000000000000000000000000000..0a11da603e94f4dbbc0c258e29911406e8a52371
--- /dev/null
+++ b/guides/09_other-tutorials/setting-up-a-demo-for-maximum-performance.md
@@ -0,0 +1,129 @@
+# Setting Up a Demo for Maximum Performance
+
+Tags: CONCURRENCY, LATENCY, PERFORMANCE
+
+Let's say that your Gradio demo goes _viral_ on social media -- you have lots of users trying it out simultaneously, and you want to provide your users with the best possible experience or, in other words, minimize the amount of time that each user has to wait in the queue to see their prediction.
+
+How can you configure your Gradio demo to handle the most traffic? In this Guide, we dive into some of the parameters of Gradio's `.queue()` method as well as some other related parameters, and discuss how to set these parameters in a way that allows you to serve lots of users simultaneously with minimal latency.
+
+This is an advanced guide, so make sure you know the basics of Gradio already, such as [how to create and launch a Gradio Interface](https://gradio.app/guides/quickstart/). Most of the information in this Guide is relevant whether you are hosting your demo on [Hugging Face Spaces](https://hf.space) or on your own server.
+
+## Overview of Gradio's Queueing System
+
+By default, every Gradio demo includes a built-in queuing system that scales to thousands of requests. When a user of your app submits a request (i.e. submits an input to your function), Gradio adds the request to the queue, and requests are processed in order, generally speaking (this is not exactly true, as discussed below). When the user's request has finished processing, the Gradio server returns the result back to the user using server-side events (SSE). The SSE protocol has several advantages over simply using HTTP POST requests:
+
+(1) They do not time out -- most browsers raise a timeout error if they do not get a response to a POST request after a short period of time (e.g. 1 min). This can be a problem if your inference function takes longer than 1 minute to run or if many people are trying out your demo at the same time, resulting in increased latency.
+
+(2) They allow the server to send multiple updates to the frontend. This means, for example, that the server can send a real-time ETA of how long your prediction will take to complete.
+
+To configure the queue, simply call the `.queue()` method before launching an `Interface`, `TabbedInterface`, `ChatInterface` or any `Blocks`. Here's an example:
+
+```py
+import gradio as gr
+
+app = gr.Interface(lambda x:x, "image", "image")
+app.queue() # <-- Sets up a queue with default parameters
+app.launch()
+```
+
+**How Requests are Processed from the Queue**
+
+When a Gradio server is launched, a pool of threads is used to execute requests from the queue. By default, the maximum size of this thread pool is `40` (which is the default inherited from FastAPI, on which the Gradio server is based). However, this does *not* mean that 40 requests are always processed in parallel from the queue.
+
+Instead, Gradio uses a **single-function-single-worker** model by default. This means that each worker thread is only assigned a single function from among all of the functions that could be part of your Gradio app. This ensures that you do not see, for example, out-of-memory errors, due to multiple workers calling a machine learning model at the same time. Suppose you have 3 functions in your Gradio app: A, B, and C. And you see the following sequence of 7 requests come in from users using your app:
+
+```
+1 2 3 4 5 6 7
+-------------
+A B A A C B A
+```
+
+Initially, 3 workers will get dispatched to handle requests 1, 2, and 5 (corresponding to functions: A, B, C). As soon as any of these workers finish, they will start processing the next function in the queue of the same function type, e.g. the worker that finished processing request 1 will start processing request 3, and so on.
+
+If you want to change this behavior, there are several parameters that can be used to configure the queue and help reduce latency. Let's go through them one-by-one.
+
+
+### The `default_concurrency_limit` parameter in `queue()`
+
+The first parameter we will explore is the `default_concurrency_limit` parameter in `queue()`. This controls how many workers can execute the same event. By default, this is set to `1`, but you can set it to a higher integer: `2`, `10`, or even `None` (in the last case, there is no limit besides the total number of available workers).
+
+This is useful, for example, if your Gradio app does not call any resource-intensive functions. If your app only queries external APIs, then you can set the `default_concurrency_limit` much higher. Increasing this parameter can **linearly multiply the capacity of your server to handle requests**.
+
+So why not set this parameter much higher all the time? Keep in mind that since requests are processed in parallel, each request will consume memory to store the data and weights for processing. This means that you might get out-of-memory errors if you increase the `default_concurrency_limit` too high. You may also start to get diminishing returns if the `default_concurrency_limit` is too high because of costs of switching between different worker threads.
+
+**Recommendation**: Increase the `default_concurrency_limit` parameter as high as you can while you continue to see performance gains or until you hit memory limits on your machine. You can [read about Hugging Face Spaces machine specs here](https://huggingface.co/docs/hub/spaces-overview).
+
+
+### The `concurrency_limit` parameter in events
+
+You can also set the number of requests that can be processed in parallel for each event individually. These take priority over the `default_concurrency_limit` parameter described previously.
+
+To do this, set the `concurrency_limit` parameter of any event listener, e.g. `btn.click(..., concurrency_limit=20)` or in the `Interface` or `ChatInterface` classes: e.g. `gr.Interface(..., concurrency_limit=20)`. By default, this parameter is set to the global `default_concurrency_limit`.
+
+### The `max_workers` parameter in `launch()`
+
+
+If you have maxed out the `concurrency_count` and you'd like to further increase the number of requests that should be processed in parallel, you can increase the number of threads that can process requests from the queue.
+
+You do this by setting the `max_workers` parameter in the `launch()` method. (The default value is 40.)
+
+
+### The `max_size` parameter in `queue()`
+
+A more blunt way to reduce the wait times is simply to prevent too many people from joining the queue in the first place. You can set the maximum number of requests that the queue processes using the `max_size` parameter of `queue()`. If a request arrives when the queue is already of the maximum size, it will not be allowed to join the queue and instead, the user will receive an error saying that the queue is full and to try again. By default, `max_size=None`, meaning that there is no limit to the number of users that can join the queue.
+
+Paradoxically, setting a `max_size` can often improve user experience because it prevents users from being dissuaded by very long queue wait times. Users who are more interested and invested in your demo will keep trying to join the queue, and will be able to get their results faster.
+
+**Recommendation**: For a better user experience, set a `max_size` that is reasonable given your expectations of how long users might be willing to wait for a prediction.
+
+### The `max_batch_size` parameter in events
+
+Another way to increase the parallelism of your Gradio demo is to write your function so that it can accept **batches** of inputs. Most deep learning models can process batches of samples more efficiently than processing individual samples.
+
+If you write your function to process a batch of samples, Gradio will automatically batch incoming requests together and pass them into your function as a batch of samples. You need to set `batch` to `True` (by default it is `False`) and set a `max_batch_size` (by default it is `4`) based on the maximum number of samples your function is able to handle. These two parameters can be passed into `gr.Interface()` or to an event in Blocks such as `.click()`.
+
+While setting a batch is conceptually similar to having workers process requests in parallel, it is often _faster_ than setting the `concurrency_count` for deep learning models. The downside is that you might need to adapt your function a little bit to accept batches of samples instead of individual samples.
+
+Here's an example of a function that does _not_ accept a batch of inputs -- it processes a single input at a time:
+
+```py
+import time
+
+def trim_words(word, length):
+ return word[:int(length)]
+
+```
+
+Here's the same function rewritten to take in a batch of samples:
+
+```py
+import time
+
+def trim_words(words, lengths):
+ trimmed_words = []
+ for w, l in zip(words, lengths):
+ trimmed_words.append(w[:int(l)])
+ return [trimmed_words]
+
+```
+
+The second function can be used with `batch=True` and an appropriate `max_batch_size` parameter.
+
+**Recommendation**: If possible, write your function to accept batches of samples, and then set `batch` to `True` and the `max_batch_size` as high as possible based on your machine's memory limits.
+
+## Upgrading your Hardware (GPUs, TPUs, etc.)
+
+If you have done everything above, and your demo is still not fast enough, you can upgrade the hardware that your model is running on. Changing the model from running on CPUs to running on GPUs will usually provide a 10x-50x increase in inference time for deep learning models.
+
+It is particularly straightforward to upgrade your Hardware on Hugging Face Spaces. Simply click on the "Settings" tab in your Space and choose the Space Hardware you'd like.
+
+![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/spaces-gpu-settings.png)
+
+While you might need to adapt portions of your machine learning inference code to run on a GPU (here's a [handy guide](https://cnvrg.io/pytorch-cuda/) if you are using PyTorch), Gradio is completely agnostic to the choice of hardware and will work completely fine if you use it with CPUs, GPUs, TPUs, or any other hardware!
+
+Note: your GPU memory is different than your CPU memory, so if you upgrade your hardware,
+you might need to adjust the value of the `default_concurrency_limit` parameter described above.
+
+## Conclusion
+
+Congratulations! You know how to set up a Gradio demo for maximum performance. Good luck on your next viral demo!
diff --git a/guides/09_other-tutorials/theming-guide.md b/guides/09_other-tutorials/theming-guide.md
new file mode 100644
index 0000000000000000000000000000000000000000..43b2775a1a0e6ec73e3d37e1aaba2252a81c0007
--- /dev/null
+++ b/guides/09_other-tutorials/theming-guide.md
@@ -0,0 +1,427 @@
+# Theming
+
+Tags: THEMES
+
+## Introduction
+
+Gradio features a built-in theming engine that lets you customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Blocks` or `Interface` constructor. For example:
+
+```python
+with gr.Blocks(theme=gr.themes.Soft()) as demo:
+ ...
+```
+
+
+
+
+
+Gradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. These are:
+
+- `gr.themes.Base()`
+- `gr.themes.Default()`
+- `gr.themes.Glass()`
+- `gr.themes.Monochrome()`
+- `gr.themes.Soft()`
+
+Each of these themes set values for hundreds of CSS variables. You can use prebuilt themes as a starting point for your own custom themes, or you can create your own themes from scratch. Let's take a look at each approach.
+
+## Using the Theme Builder
+
+The easiest way to build a theme is using the Theme Builder. To launch the Theme Builder locally, run the following code:
+
+```python
+import gradio as gr
+
+gr.themes.builder()
+```
+
+$demo_theme_builder
+
+You can use the Theme Builder running on Spaces above, though it runs much faster when you launch it locally via `gr.themes.builder()`.
+
+As you edit the values in the Theme Builder, the app will preview updates in real time. You can download the code to generate the theme you've created so you can use it in any Gradio app.
+
+In the rest of the guide, we will cover building themes programmatically.
+
+## Extending Themes via the Constructor
+
+Although each theme has hundreds of CSS variables, the values for most these variables are drawn from 8 core variables which can be set through the constructor of each prebuilt theme. Modifying these 8 arguments allows you to quickly change the look and feel of your app.
+
+### Core Colors
+
+The first 3 constructor arguments set the colors of the theme and are `gradio.themes.Color` objects. Internally, these Color objects hold brightness values for the palette of a single hue, ranging from 50, 100, 200..., 800, 900, 950. Other CSS variables are derived from these 3 colors.
+
+The 3 color constructor arguments are:
+
+- `primary_hue`: This is the color draws attention in your theme. In the default theme, this is set to `gradio.themes.colors.orange`.
+- `secondary_hue`: This is the color that is used for secondary elements in your theme. In the default theme, this is set to `gradio.themes.colors.blue`.
+- `neutral_hue`: This is the color that is used for text and other neutral elements in your theme. In the default theme, this is set to `gradio.themes.colors.gray`.
+
+You could modify these values using their string shortcuts, such as
+
+```python
+with gr.Blocks(theme=gr.themes.Default(primary_hue="red", secondary_hue="pink")) as demo:
+ ...
+```
+
+or you could use the `Color` objects directly, like this:
+
+```python
+with gr.Blocks(theme=gr.themes.Default(primary_hue=gr.themes.colors.red, secondary_hue=gr.themes.colors.pink)) as demo:
+ ...
+```
+
+
+
+
+
+Predefined colors are:
+
+- `slate`
+- `gray`
+- `zinc`
+- `neutral`
+- `stone`
+- `red`
+- `orange`
+- `amber`
+- `yellow`
+- `lime`
+- `green`
+- `emerald`
+- `teal`
+- `cyan`
+- `sky`
+- `blue`
+- `indigo`
+- `violet`
+- `purple`
+- `fuchsia`
+- `pink`
+- `rose`
+
+You could also create your own custom `Color` objects and pass them in.
+
+### Core Sizing
+
+The next 3 constructor arguments set the sizing of the theme and are `gradio.themes.Size` objects. Internally, these Size objects hold pixel size values that range from `xxs` to `xxl`. Other CSS variables are derived from these 3 sizes.
+
+- `spacing_size`: This sets the padding within and spacing between elements. In the default theme, this is set to `gradio.themes.sizes.spacing_md`.
+- `radius_size`: This sets the roundedness of corners of elements. In the default theme, this is set to `gradio.themes.sizes.radius_md`.
+- `text_size`: This sets the font size of text. In the default theme, this is set to `gradio.themes.sizes.text_md`.
+
+You could modify these values using their string shortcuts, such as
+
+```python
+with gr.Blocks(theme=gr.themes.Default(spacing_size="sm", radius_size="none")) as demo:
+ ...
+```
+
+or you could use the `Size` objects directly, like this:
+
+```python
+with gr.Blocks(theme=gr.themes.Default(spacing_size=gr.themes.sizes.spacing_sm, radius_size=gr.themes.sizes.radius_none)) as demo:
+ ...
+```
+
+
+
+
+
+The predefined size objects are:
+
+- `radius_none`
+- `radius_sm`
+- `radius_md`
+- `radius_lg`
+- `spacing_sm`
+- `spacing_md`
+- `spacing_lg`
+- `text_sm`
+- `text_md`
+- `text_lg`
+
+You could also create your own custom `Size` objects and pass them in.
+
+### Core Fonts
+
+The final 2 constructor arguments set the fonts of the theme. You can pass a list of fonts to each of these arguments to specify fallbacks. If you provide a string, it will be loaded as a system font. If you provide a `gradio.themes.GoogleFont`, the font will be loaded from Google Fonts.
+
+- `font`: This sets the primary font of the theme. In the default theme, this is set to `gradio.themes.GoogleFont("Source Sans Pro")`.
+- `font_mono`: This sets the monospace font of the theme. In the default theme, this is set to `gradio.themes.GoogleFont("IBM Plex Mono")`.
+
+You could modify these values such as the following:
+
+```python
+with gr.Blocks(theme=gr.themes.Default(font=[gr.themes.GoogleFont("Inconsolata"), "Arial", "sans-serif"])) as demo:
+ ...
+```
+
+
+
+
+
+## Extending Themes via `.set()`
+
+You can also modify the values of CSS variables after the theme has been loaded. To do so, use the `.set()` method of the theme object to get access to the CSS variables. For example:
+
+```python
+theme = gr.themes.Default(primary_hue="blue").set(
+ loader_color="#FF0000",
+ slider_color="#FF0000",
+)
+
+with gr.Blocks(theme=theme) as demo:
+ ...
+```
+
+In the example above, we've set the `loader_color` and `slider_color` variables to `#FF0000`, despite the overall `primary_color` using the blue color palette. You can set any CSS variable that is defined in the theme in this manner.
+
+Your IDE type hinting should help you navigate these variables. Since there are so many CSS variables, let's take a look at how these variables are named and organized.
+
+### CSS Variable Naming Conventions
+
+CSS variable names can get quite long, like `button_primary_background_fill_hover_dark`! However they follow a common naming convention that makes it easy to understand what they do and to find the variable you're looking for. Separated by underscores, the variable name is made up of:
+
+1. The target element, such as `button`, `slider`, or `block`.
+2. The target element type or sub-element, such as `button_primary`, or `block_label`.
+3. The property, such as `button_primary_background_fill`, or `block_label_border_width`.
+4. Any relevant state, such as `button_primary_background_fill_hover`.
+5. If the value is different in dark mode, the suffix `_dark`. For example, `input_border_color_focus_dark`.
+
+Of course, many CSS variable names are shorter than this, such as `table_border_color`, or `input_shadow`.
+
+### CSS Variable Organization
+
+Though there are hundreds of CSS variables, they do not all have to have individual values. They draw their values by referencing a set of core variables and referencing each other. This allows us to only have to modify a few variables to change the look and feel of the entire theme, while also getting finer control of individual elements that we may want to modify.
+
+#### Referencing Core Variables
+
+To reference one of the core constructor variables, precede the variable name with an asterisk. To reference a core color, use the `*primary_`, `*secondary_`, or `*neutral_` prefix, followed by the brightness value. For example:
+
+```python
+theme = gr.themes.Default(primary_hue="blue").set(
+ button_primary_background_fill="*primary_200",
+ button_primary_background_fill_hover="*primary_300",
+)
+```
+
+In the example above, we've set the `button_primary_background_fill` and `button_primary_background_fill_hover` variables to `*primary_200` and `*primary_300`. These variables will be set to the 200 and 300 brightness values of the blue primary color palette, respectively.
+
+Similarly, to reference a core size, use the `*spacing_`, `*radius_`, or `*text_` prefix, followed by the size value. For example:
+
+```python
+theme = gr.themes.Default(radius_size="md").set(
+ button_primary_border_radius="*radius_xl",
+)
+```
+
+In the example above, we've set the `button_primary_border_radius` variable to `*radius_xl`. This variable will be set to the `xl` setting of the medium radius size range.
+
+#### Referencing Other Variables
+
+Variables can also reference each other. For example, look at the example below:
+
+```python
+theme = gr.themes.Default().set(
+ button_primary_background_fill="#FF0000",
+ button_primary_background_fill_hover="#FF0000",
+ button_primary_border="#FF0000",
+)
+```
+
+Having to set these values to a common color is a bit tedious. Instead, we can reference the `button_primary_background_fill` variable in the `button_primary_background_fill_hover` and `button_primary_border` variables, using a `*` prefix.
+
+```python
+theme = gr.themes.Default().set(
+ button_primary_background_fill="#FF0000",
+ button_primary_background_fill_hover="*button_primary_background_fill",
+ button_primary_border="*button_primary_background_fill",
+)
+```
+
+Now, if we change the `button_primary_background_fill` variable, the `button_primary_background_fill_hover` and `button_primary_border` variables will automatically update as well.
+
+This is particularly useful if you intend to share your theme - it makes it easy to modify the theme without having to change every variable.
+
+Note that dark mode variables automatically reference each other. For example:
+
+```python
+theme = gr.themes.Default().set(
+ button_primary_background_fill="#FF0000",
+ button_primary_background_fill_dark="#AAAAAA",
+ button_primary_border="*button_primary_background_fill",
+ button_primary_border_dark="*button_primary_background_fill_dark",
+)
+```
+
+`button_primary_border_dark` will draw its value from `button_primary_background_fill_dark`, because dark mode always draw from the dark version of the variable.
+
+## Creating a Full Theme
+
+Let's say you want to create a theme from scratch! We'll go through it step by step - you can also see the source of prebuilt themes in the gradio source repo for reference - [here's the source](https://github.com/gradio-app/gradio/blob/main/gradio/themes/monochrome.py) for the Monochrome theme.
+
+Our new theme class will inherit from `gradio.themes.Base`, a theme that sets a lot of convenient defaults. Let's make a simple demo that creates a dummy theme called Seafoam, and make a simple app that uses it.
+
+$code_theme_new_step_1
+
+
+
+
+
+The Base theme is very barebones, and uses `gr.themes.Blue` as it primary color - you'll note the primary button and the loading animation are both blue as a result. Let's change the defaults core arguments of our app. We'll overwrite the constructor and pass new defaults for the core constructor arguments.
+
+We'll use `gr.themes.Emerald` as our primary color, and set secondary and neutral hues to `gr.themes.Blue`. We'll make our text larger using `text_lg`. We'll use `Quicksand` as our default font, loaded from Google Fonts.
+
+$code_theme_new_step_2
+
+
+
+
+
+See how the primary button and the loading animation are now green? These CSS variables are tied to the `primary_hue` variable.
+
+Let's modify the theme a bit more directly. We'll call the `set()` method to overwrite CSS variable values explicitly. We can use any CSS logic, and reference our core constructor arguments using the `*` prefix.
+
+$code_theme_new_step_3
+
+
+
+
+
+Look how fun our theme looks now! With just a few variable changes, our theme looks completely different.
+
+You may find it helpful to explore the [source code of the other prebuilt themes](https://github.com/gradio-app/gradio/blob/main/gradio/themes) to see how they modified the base theme. You can also find your browser's Inspector useful to select elements from the UI and see what CSS variables are being used in the styles panel.
+
+## Sharing Themes
+
+Once you have created a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it!
+
+### Uploading a Theme
+
+There are two ways to upload a theme, via the theme class instance or the command line. We will cover both of them with the previously created `seafoam` theme.
+
+- Via the class instance
+
+Each theme instance has a method called `push_to_hub` we can use to upload a theme to the HuggingFace hub.
+
+```python
+seafoam.push_to_hub(repo_name="seafoam",
+ version="0.0.1",
+ hf_token="")
+```
+
+- Via the command line
+
+First save the theme to disk
+
+```python
+seafoam.dump(filename="seafoam.json")
+```
+
+Then use the `upload_theme` command:
+
+```bash
+upload_theme\
+"seafoam.json"\
+"seafoam"\
+--version "0.0.1"\
+--hf_token ""
+```
+
+In order to upload a theme, you must have a HuggingFace account and pass your [Access Token](https://huggingface.co/docs/huggingface_hub/quick-start#login)
+as the `hf_token` argument. However, if you log in via the [HuggingFace command line](https://huggingface.co/docs/huggingface_hub/quick-start#login) (which comes installed with `gradio`),
+you can omit the `hf_token` argument.
+
+The `version` argument lets you specify a valid [semantic version](https://www.geeksforgeeks.org/introduction-semantic-versioning/) string for your theme.
+That way your users are able to specify which version of your theme they want to use in their apps. This also lets you publish updates to your theme without worrying
+about changing how previously created apps look. The `version` argument is optional. If omitted, the next patch version is automatically applied.
+
+### Theme Previews
+
+By calling `push_to_hub` or `upload_theme`, the theme assets will be stored in a [HuggingFace space](https://huggingface.co/docs/hub/spaces-overview).
+
+The theme preview for our seafoam theme is here: [seafoam preview](https://huggingface.co/spaces/gradio/seafoam).
+
+
+
+
+
+### Discovering Themes
+
+The [Theme Gallery](https://huggingface.co/spaces/gradio/theme-gallery) shows all the public gradio themes. After publishing your theme,
+it will automatically show up in the theme gallery after a couple of minutes.
+
+You can sort the themes by the number of likes on the space and from most to least recently created as well as toggling themes between light and dark mode.
+
+
+
+
+
+### Downloading
+
+To use a theme from the hub, use the `from_hub` method on the `ThemeClass` and pass it to your app:
+
+```python
+my_theme = gr.Theme.from_hub("gradio/seafoam")
+
+with gr.Blocks(theme=my_theme) as demo:
+ ....
+```
+
+You can also pass the theme string directly to `Blocks` or `Interface` (`gr.Blocks(theme="gradio/seafoam")`)
+
+You can pin your app to an upstream theme version by using semantic versioning expressions.
+
+For example, the following would ensure the theme we load from the `seafoam` repo was between versions `0.0.1` and `0.1.0`:
+
+```python
+with gr.Blocks(theme="gradio/seafoam@>=0.0.1,<0.1.0") as demo:
+ ....
+```
+
+Enjoy creating your own themes! If you make one you're proud of, please share it with the world by uploading it to the hub!
+If you tag us on [Twitter](https://twitter.com/gradio) we can give your theme a shout out!
+
+
diff --git a/guides/09_other-tutorials/using-flagging.md b/guides/09_other-tutorials/using-flagging.md
new file mode 100644
index 0000000000000000000000000000000000000000..d97b4533ba2bd7eec5bbdcfa43d8988ebb5161a0
--- /dev/null
+++ b/guides/09_other-tutorials/using-flagging.md
@@ -0,0 +1,197 @@
+# Using Flagging
+
+Related spaces: https://huggingface.co/spaces/gradio/calculator-flagging-crowdsourced, https://huggingface.co/spaces/gradio/calculator-flagging-options, https://huggingface.co/spaces/gradio/calculator-flag-basic
+Tags: FLAGGING, DATA
+
+## Introduction
+
+When you demo a machine learning model, you might want to collect data from users who try the model, particularly data points in which the model is not behaving as expected. Capturing these "hard" data points is valuable because it allows you to improve your machine learning model and make it more reliable and robust.
+
+Gradio simplifies the collection of this data by including a **Flag** button with every `Interface`. This allows a user or tester to easily send data back to the machine where the demo is running. In this Guide, we discuss more about how to use the flagging feature, both with `gradio.Interface` as well as with `gradio.Blocks`.
+
+## The **Flag** button in `gradio.Interface`
+
+Flagging with Gradio's `Interface` is especially easy. By default, underneath the output components, there is a button marked **Flag**. When a user testing your model sees input with interesting output, they can click the flag button to send the input and output data back to the machine where the demo is running. The sample is saved to a CSV log file (by default). If the demo involves images, audio, video, or other types of files, these are saved separately in a parallel directory and the paths to these files are saved in the CSV file.
+
+There are [four parameters](https://gradio.app/docs/interface#initialization) in `gradio.Interface` that control how flagging works. We will go over them in greater detail.
+
+- `allow_flagging`: this parameter can be set to either `"manual"` (default), `"auto"`, or `"never"`.
+ - `manual`: users will see a button to flag, and samples are only flagged when the button is clicked.
+ - `auto`: users will not see a button to flag, but every sample will be flagged automatically.
+ - `never`: users will not see a button to flag, and no sample will be flagged.
+- `flagging_options`: this parameter can be either `None` (default) or a list of strings.
+ - If `None`, then the user simply clicks on the **Flag** button and no additional options are shown.
+ - If a list of strings are provided, then the user sees several buttons, corresponding to each of the strings that are provided. For example, if the value of this parameter is `["Incorrect", "Ambiguous"]`, then buttons labeled **Flag as Incorrect** and **Flag as Ambiguous** appear. This only applies if `allow_flagging` is `"manual"`.
+ - The chosen option is then logged along with the input and output.
+- `flagging_dir`: this parameter takes a string.
+ - It represents what to name the directory where flagged data is stored.
+- `flagging_callback`: this parameter takes an instance of a subclass of the `FlaggingCallback` class
+ - Using this parameter allows you to write custom code that gets run when the flag button is clicked
+ - By default, this is set to an instance of `gr.CSVLogger`
+ - One example is setting it to an instance of `gr.HuggingFaceDatasetSaver` which can allow you to pipe any flagged data into a HuggingFace Dataset. (See more below.)
+
+## What happens to flagged data?
+
+Within the directory provided by the `flagging_dir` argument, a CSV file will log the flagged data.
+
+Here's an example: The code below creates the calculator interface embedded below it:
+
+```python
+import gradio as gr
+
+
+def calculator(num1, operation, num2):
+ if operation == "add":
+ return num1 + num2
+ elif operation == "subtract":
+ return num1 - num2
+ elif operation == "multiply":
+ return num1 * num2
+ elif operation == "divide":
+ return num1 / num2
+
+
+iface = gr.Interface(
+ calculator,
+ ["number", gr.Radio(["add", "subtract", "multiply", "divide"]), "number"],
+ "number",
+ allow_flagging="manual"
+)
+
+iface.launch()
+```
+
+
+
+When you click the flag button above, the directory where the interface was launched will include a new flagged subfolder, with a csv file inside it. This csv file includes all the data that was flagged.
+
+```directory
++-- flagged/
+| +-- logs.csv
+```
+
+_flagged/logs.csv_
+
+```csv
+num1,operation,num2,Output,timestamp
+5,add,7,12,2022-01-31 11:40:51.093412
+6,subtract,1.5,4.5,2022-01-31 03:25:32.023542
+```
+
+If the interface involves file data, such as for Image and Audio components, folders will be created to store those flagged data as well. For example an `image` input to `image` output interface will create the following structure.
+
+```directory
++-- flagged/
+| +-- logs.csv
+| +-- image/
+| | +-- 0.png
+| | +-- 1.png
+| +-- Output/
+| | +-- 0.png
+| | +-- 1.png
+```
+
+_flagged/logs.csv_
+
+```csv
+im,Output timestamp
+im/0.png,Output/0.png,2022-02-04 19:49:58.026963
+im/1.png,Output/1.png,2022-02-02 10:40:51.093412
+```
+
+If you wish for the user to provide a reason for flagging, you can pass a list of strings to the `flagging_options` argument of Interface. Users will have to select one of these choices when flagging, and the option will be saved as an additional column to the CSV.
+
+If we go back to the calculator example, the following code will create the interface embedded below it.
+
+```python
+iface = gr.Interface(
+ calculator,
+ ["number", gr.Radio(["add", "subtract", "multiply", "divide"]), "number"],
+ "number",
+ allow_flagging="manual",
+ flagging_options=["wrong sign", "off by one", "other"]
+)
+
+iface.launch()
+```
+
+
+
+When users click the flag button, the csv file will now include a column indicating the selected option.
+
+_flagged/logs.csv_
+
+```csv
+num1,operation,num2,Output,flag,timestamp
+5,add,7,-12,wrong sign,2022-02-04 11:40:51.093412
+6,subtract,1.5,3.5,off by one,2022-02-04 11:42:32.062512
+```
+
+## The HuggingFaceDatasetSaver Callback
+
+Sometimes, saving the data to a local CSV file doesn't make sense. For example, on Hugging Face
+Spaces, developers typically don't have access to the underlying ephemeral machine hosting the Gradio
+demo. That's why, by default, flagging is turned off in Hugging Face Space. However,
+you may want to do something else with the flagged data.
+
+We've made this super easy with the `flagging_callback` parameter.
+
+For example, below we're going to pipe flagged data from our calculator example into a Hugging Face Dataset, e.g. so that we can build a "crowd-sourced" dataset:
+
+```python
+import os
+
+HF_TOKEN = os.getenv('HF_TOKEN')
+hf_writer = gr.HuggingFaceDatasetSaver(HF_TOKEN, "crowdsourced-calculator-demo")
+
+iface = gr.Interface(
+ calculator,
+ ["number", gr.Radio(["add", "subtract", "multiply", "divide"]), "number"],
+ "number",
+ description="Check out the crowd-sourced dataset at: [https://huggingface.co/datasets/aliabd/crowdsourced-calculator-demo](https://huggingface.co/datasets/aliabd/crowdsourced-calculator-demo)",
+ allow_flagging="manual",
+ flagging_options=["wrong sign", "off by one", "other"],
+ flagging_callback=hf_writer
+)
+
+iface.launch()
+```
+
+Notice that we define our own
+instance of `gradio.HuggingFaceDatasetSaver` using our Hugging Face token and
+the name of a dataset we'd like to save samples to. In addition, we also set `allow_flagging="manual"`
+because on Hugging Face Spaces, `allow_flagging` is set to `"never"` by default. Here's our demo:
+
+
+
+You can now see all the examples flagged above in this [public Hugging Face dataset](https://huggingface.co/datasets/aliabd/crowdsourced-calculator-demo).
+
+![flagging callback hf](https://github.com/gradio-app/gradio/blob/main/guides/assets/flagging-callback-hf.png?raw=true)
+
+We created the `gradio.HuggingFaceDatasetSaver` class, but you can pass your own custom class as long as it inherits from `FLaggingCallback` defined in [this file](https://github.com/gradio-app/gradio/blob/master/gradio/flagging.py). If you create a cool callback, contribute it to the repo!
+
+## Flagging with Blocks
+
+What about if you are using `gradio.Blocks`? On one hand, you have even more flexibility
+with Blocks -- you can write whatever Python code you want to run when a button is clicked,
+and assign that using the built-in events in Blocks.
+
+At the same time, you might want to use an existing `FlaggingCallback` to avoid writing extra code.
+This requires two steps:
+
+1. You have to run your callback's `.setup()` somewhere in the code prior to the
+ first time you flag data
+2. When the flagging button is clicked, then you trigger the callback's `.flag()` method,
+ making sure to collect the arguments correctly and disabling the typical preprocessing.
+
+Here is an example with an image sepia filter Blocks demo that lets you flag
+data using the default `CSVLogger`:
+
+$code_blocks_flag
+$demo_blocks_flag
+
+## Privacy
+
+Important Note: please make sure your users understand when the data they submit is being saved, and what you plan on doing with it. This is especially important when you use `allow_flagging=auto` (when all of the data submitted through the demo is being flagged)
+
+### That's all! Happy building :)
diff --git a/guides/CONTRIBUTING.md b/guides/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..d43e06dbbf7cc172ac23b41c98b8a7be0f241349
--- /dev/null
+++ b/guides/CONTRIBUTING.md
@@ -0,0 +1,30 @@
+# Contributing a Guide
+
+Want to help teach Gradio? Consider contributing a Guide! 🤗
+
+Broadly speaking, there are two types of guides:
+
+- **Use cases**: guides that cover step-by-step how to build a particular type of machine learning demo or app using Gradio. Here's an example: [_Creating a Chatbot_](https://github.com/gradio-app/gradio/blob/master/guides/creating_a_chatbot.md)
+- **Feature explanation**: guides that describe in detail a particular feature of Gradio. Here's an example: [_Using Flagging_](https://github.com/gradio-app/gradio/blob/master/guides/using_flagging.md)
+
+We encourage you to submit either type of Guide! (Looking for ideas? We may also have open [issues](https://github.com/gradio-app/gradio/issues?q=is%3Aopen+is%3Aissue+label%3Aguides) where users have asked for guides on particular topics)
+
+## Guide Structure
+
+As you can see with the previous examples, Guides are standard markdown documents. They usually:
+
+- start with an Introduction section describing the topic
+- include subheadings to make articles easy to navigate
+- include real code snippets that make it easy to follow along and implement the Guide
+- include embedded Gradio demos to make them more interactive and provide immediate demonstrations of the topic being discussed. These Gradio demos are hosted on [Hugging Face Spaces](https://huggingface.co/spaces) and are embedded using the standard \