From 00d18463ffeb49d882003f1e4c8bb72f8f7fb596 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Mon, 30 Sep 2024 08:22:19 -0700 Subject: [PATCH 01/24] fix exports in `main` (#9478) * fix exports * add changeset * format --------- Co-authored-by: gradio-pr-bot --- .changeset/free-years-hide.md | 5 +++++ js/preview/package.json | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .changeset/free-years-hide.md diff --git a/.changeset/free-years-hide.md b/.changeset/free-years-hide.md new file mode 100644 index 0000000000000..55b7622ebfe71 --- /dev/null +++ b/.changeset/free-years-hide.md @@ -0,0 +1,5 @@ +--- +"@gradio/preview": patch +--- + +feat:fix exports in `main` diff --git a/js/preview/package.json b/js/preview/package.json index 248ea5c3de08a..44f251f7ebc67 100644 --- a/js/preview/package.json +++ b/js/preview/package.json @@ -43,6 +43,8 @@ }, "exports": { ".": { + "default": "./dist/index.js", + "import": "./dist/index.js", "gradio": "./src/index.ts", "svelte": "./dist/src/index.js", "types": "./dist/index.d.ts" From 7894e159197b62122064218f22ad0d78dbac917f Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Mon, 30 Sep 2024 08:31:59 -0700 Subject: [PATCH 02/24] changesets (#9479) --- .changeset/metal-nights-march.md | 2 +- .changeset/public-webs-melt.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/metal-nights-march.md b/.changeset/metal-nights-march.md index f0dfd1de44af9..a1f6ccf9291c3 100644 --- a/.changeset/metal-nights-march.md +++ b/.changeset/metal-nights-march.md @@ -1,5 +1,5 @@ --- -"gradio": minor +"gradio": patch --- feat:chore: fix docs style diff --git a/.changeset/public-webs-melt.md b/.changeset/public-webs-melt.md index b300262cf7992..7de1209128c91 100644 --- a/.changeset/public-webs-melt.md +++ b/.changeset/public-webs-melt.md @@ -1,5 +1,5 @@ --- -"website": minor +"website": patch --- feat:Testing CI From a381c35785b9705eb82aedce08041460b06b1e80 Mon Sep 17 00:00:00 2001 From: Gradio PR Bot <121576822+gradio-pr-bot@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:44:55 -0400 Subject: [PATCH 03/24] chore: update versions (#9380) Co-authored-by: github-actions[bot] --- .changeset/free-years-hide.md | 5 ----- .changeset/metal-nights-march.md | 5 ----- .changeset/public-webs-melt.md | 5 ----- CHANGELOG.md | 6 ++++++ gradio/CHANGELOG.md | 6 ++++++ gradio/package.json | 2 +- js/_website/CHANGELOG.md | 11 +++++++++++ js/_website/package.json | 2 +- js/core/CHANGELOG.md | 7 +++++++ js/preview/CHANGELOG.md | 6 ++++++ js/preview/package.json | 2 +- 11 files changed, 39 insertions(+), 18 deletions(-) delete mode 100644 .changeset/free-years-hide.md delete mode 100644 .changeset/metal-nights-march.md delete mode 100644 .changeset/public-webs-melt.md diff --git a/.changeset/free-years-hide.md b/.changeset/free-years-hide.md deleted file mode 100644 index 55b7622ebfe71..0000000000000 --- a/.changeset/free-years-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@gradio/preview": patch ---- - -feat:fix exports in `main` diff --git a/.changeset/metal-nights-march.md b/.changeset/metal-nights-march.md deleted file mode 100644 index a1f6ccf9291c3..0000000000000 --- a/.changeset/metal-nights-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"gradio": patch ---- - -feat:chore: fix docs style diff --git a/.changeset/public-webs-melt.md b/.changeset/public-webs-melt.md deleted file mode 100644 index 7de1209128c91..0000000000000 --- a/.changeset/public-webs-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"website": patch ---- - -feat:Testing CI diff --git a/CHANGELOG.md b/CHANGELOG.md index acaab6dc91c29..1973f9fdc6daa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # gradio +## 4.44.1 + +### Features + +- [#9320](https://github.com/gradio-app/gradio/pull/9320) [`98cbcae`](https://github.com/gradio-app/gradio/commit/98cbcaef827de7267462ccba180c7b2ffb1e825d) - chore: fix docs style. Thanks @imba-tjd! + ## 4.44.0 ### Features diff --git a/gradio/CHANGELOG.md b/gradio/CHANGELOG.md index acaab6dc91c29..1973f9fdc6daa 100644 --- a/gradio/CHANGELOG.md +++ b/gradio/CHANGELOG.md @@ -1,5 +1,11 @@ # gradio +## 4.44.1 + +### Features + +- [#9320](https://github.com/gradio-app/gradio/pull/9320) [`98cbcae`](https://github.com/gradio-app/gradio/commit/98cbcaef827de7267462ccba180c7b2ffb1e825d) - chore: fix docs style. Thanks @imba-tjd! + ## 4.44.0 ### Features diff --git a/gradio/package.json b/gradio/package.json index fc614393fb187..0b2793b7c7a51 100644 --- a/gradio/package.json +++ b/gradio/package.json @@ -1,6 +1,6 @@ { "name": "gradio", - "version": "4.44.0", + "version": "4.44.1", "description": "", "python": "true" } diff --git a/js/_website/CHANGELOG.md b/js/_website/CHANGELOG.md index 9a986ac166728..91028de64a8d4 100644 --- a/js/_website/CHANGELOG.md +++ b/js/_website/CHANGELOG.md @@ -1,5 +1,16 @@ # website +## 0.39.1 + +### Features + +- [#9379](https://github.com/gradio-app/gradio/pull/9379) [`0cad5f3`](https://github.com/gradio-app/gradio/commit/0cad5f348a846024b95b92fb48f88137ccfcd589) - Testing CI. Thanks @aliabd! + +### Dependency updates + +- @gradio/code@0.9.1 +- @gradio/paramviewer@0.4.22 + ## 0.39.0 ### Features diff --git a/js/_website/package.json b/js/_website/package.json index 039d289cf24ee..35646904fb779 100644 --- a/js/_website/package.json +++ b/js/_website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "0.39.0", + "version": "0.39.1", "private": true, "scripts": { "dev": "pip install boto3 && python generate_jsons/generate.py && vite dev", diff --git a/js/core/CHANGELOG.md b/js/core/CHANGELOG.md index 61d08a5829e57..bd048ad466b51 100644 --- a/js/core/CHANGELOG.md +++ b/js/core/CHANGELOG.md @@ -2,6 +2,13 @@ ## 0.0.4 +### Dependency updates + +- @gradio/code@0.9.1 +- @gradio/paramviewer@0.4.22 + +## 0.0.4 + ### Fixes - [#9188](https://github.com/gradio-app/gradio/pull/9188) [`8f8e1c6`](https://github.com/gradio-app/gradio/commit/8f8e1c6a0b09b0d1985b8377d94d693cb00f8a18) - Fix multiple trigger bug when function has js. Thanks @freddyaboulton! diff --git a/js/preview/CHANGELOG.md b/js/preview/CHANGELOG.md index a8409e3b93e9d..6058baa830ab3 100644 --- a/js/preview/CHANGELOG.md +++ b/js/preview/CHANGELOG.md @@ -1,5 +1,11 @@ # @gradio/preview +## 0.11.2 + +### Features + +- [#9478](https://github.com/gradio-app/gradio/pull/9478) [`00d1846`](https://github.com/gradio-app/gradio/commit/00d18463ffeb49d882003f1e4c8bb72f8f7fb596) - fix exports in `main`. Thanks @abidlabs! + ## 0.11.1 ### Fixes diff --git a/js/preview/package.json b/js/preview/package.json index 44f251f7ebc67..d19c506ff964e 100644 --- a/js/preview/package.json +++ b/js/preview/package.json @@ -1,6 +1,6 @@ { "name": "@gradio/preview", - "version": "0.11.1", + "version": "0.11.2", "description": "Gradio UI packages", "type": "module", "main": "dist/index.js", From 991883e217dc0a3512b3ae3245378812f373b8db Mon Sep 17 00:00:00 2001 From: Hannah Date: Wed, 2 Oct 2024 21:51:24 +0100 Subject: [PATCH 04/24] Improve `gr.Code` (#9450) * fix check icon on download * * apply unused min_width param * improve gutter spacing * hide `BlockLabel` spacing if `show_label` is false * format * tweak spacing, remove `fit-content` * add changeset * revert height change * fix * allow setting max_lines to None * add line wrapping * add wrap lines param * fix type error * fix py test * fix type check --------- Co-authored-by: gradio-pr-bot --- .changeset/chilly-socks-poke.md | 7 ++++++ gradio/components/code.py | 9 ++++--- js/code/Index.svelte | 12 ++++++--- js/code/shared/Code.svelte | 16 +++++++++--- js/code/shared/Copy.svelte | 36 ++------------------------- js/code/shared/Download.svelte | 44 ++++++--------------------------- js/code/shared/Widgets.svelte | 28 +++------------------ js/icons/src/Check.svelte | 2 +- test/components/test_code.py | 3 ++- 9 files changed, 50 insertions(+), 107 deletions(-) create mode 100644 .changeset/chilly-socks-poke.md diff --git a/.changeset/chilly-socks-poke.md b/.changeset/chilly-socks-poke.md new file mode 100644 index 0000000000000..85f9336838641 --- /dev/null +++ b/.changeset/chilly-socks-poke.md @@ -0,0 +1,7 @@ +--- +"@gradio/code": minor +"@gradio/icons": minor +"gradio": minor +--- + +feat:Improve `gr.Code` diff --git a/gradio/components/code.py b/gradio/components/code.py index f18a2f3c730a1..15806843a97ad 100644 --- a/gradio/components/code.py +++ b/gradio/components/code.py @@ -93,7 +93,7 @@ def __init__( every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, lines: int = 5, - max_lines: int = 20, + max_lines: int | None = None, label: str | None = None, interactive: bool | None = None, show_label: bool | None = None, @@ -105,6 +105,7 @@ def __init__( elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | None = None, + wrap_lines: bool = False, ): """ Parameters: @@ -124,14 +125,16 @@ def __init__( 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. key: if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved. lines: Minimum number of visible lines to show in the code editor. - max_lines: Maximum number of visible lines to show in the code editor. + max_lines: Maximum number of visible lines to show in the code editor. Defaults to None and will fill the height of the container. + wrap_lines: If True, will wrap lines to the width of the container when overflow occurs. Defaults to False. """ if language not in Code.languages: raise ValueError(f"Language {language} not supported.") self.language = language self.lines = lines - self.max_lines = max(lines, max_lines) + self.max_lines = max(lines, max_lines) if max_lines is not None else None + self.wrap_lines = wrap_lines super().__init__( label=label, every=every, diff --git a/js/code/Index.svelte b/js/code/Index.svelte index 975e6a25b57f7..69c1832e6bc6b 100644 --- a/js/code/Index.svelte +++ b/js/code/Index.svelte @@ -29,7 +29,7 @@ export let value_is_output = false; export let language = ""; export let lines = 5; - export let max_lines = 20; + export let max_lines: number | undefined = undefined; export let elem_id = ""; export let elem_classes: string[] = []; export let visible = true; @@ -37,6 +37,8 @@ export let show_label = true; export let loading_status: LoadingStatus; export let scale: number | null = null; + export let min_width: number | undefined = undefined; + export let wrap_lines = false; export let interactive: boolean; @@ -55,13 +57,14 @@ gradio.dispatch("clear_status", loading_status)} /> - + {#if show_label} + + {/if} {#if !value && !interactive} @@ -85,6 +90,7 @@ {lines} {max_lines} {dark_mode} + {wrap_lines} readonly={!interactive} on:blur={() => gradio.dispatch("blur")} on:focus={() => gradio.dispatch("focus")} diff --git a/js/code/shared/Code.svelte b/js/code/shared/Code.svelte index 1266d0f5945b9..9f0c27efacbf9 100644 --- a/js/code/shared/Code.svelte +++ b/js/code/shared/Code.svelte @@ -20,11 +20,12 @@ export let basic = true; export let language: string; export let lines = 5; - export let max_lines = 20; + export let max_lines: number | null = null; export let extensions: Extension[] = []; export let use_tab = true; export let readonly = false; export let placeholder: string | HTMLElement | null | undefined = undefined; + export let wrap_lines = false; const dispatch = createEventDispatcher<{ change: string; @@ -109,7 +110,8 @@ const minLines = lines == 1 ? 1 : lines + 1; scroller.style.minHeight = `calc(${lineHeight} * ${minLines})`; - scroller.style.maxHeight = `calc(${lineHeight} * ${max_lines + 1})`; + if (max_lines) + scroller.style.maxHeight = `calc(${lineHeight} * ${max_lines + 1})`; } function handle_change(vu: ViewUpdate): void { @@ -150,6 +152,9 @@ fontFamily: "var(--font-mono)", minHeight: "100%" }, + ".cm-gutterElement": { + marginRight: "var(--spacing-xs)" + }, ".cm-gutters": { marginRight: "1px", borderRight: "1px solid var(--border-color-primary)", @@ -201,6 +206,9 @@ } extensions.push(EditorView.updateListener.of(handle_change)); + if (wrap_lines) { + extensions.push(EditorView.lineWrapping); + } return extensions; } @@ -235,13 +243,13 @@ .wrap { display: flex; flex-direction: column; - flex-flow: column; + flex-grow: 1; margin: 0; padding: 0; height: 100%; } .codemirror-wrapper { - height: 100%; + flex-grow: 1; overflow: auto; } diff --git a/js/code/shared/Copy.svelte b/js/code/shared/Copy.svelte index e8909fc1c55f9..c1979aa266216 100644 --- a/js/code/shared/Copy.svelte +++ b/js/code/shared/Copy.svelte @@ -1,7 +1,7 @@ - - - + diff --git a/js/code/shared/Download.svelte b/js/code/shared/Download.svelte index aefdd499e57bb..f103f271ecad7 100644 --- a/js/code/shared/Download.svelte +++ b/js/code/shared/Download.svelte @@ -1,8 +1,8 @@ -
- - - {#if copied} - - {/if} - -
- - + + + diff --git a/js/code/shared/Widgets.svelte b/js/code/shared/Widgets.svelte index 584c1944077ad..014676455e75e 100644 --- a/js/code/shared/Widgets.svelte +++ b/js/code/shared/Widgets.svelte @@ -1,35 +1,13 @@ -
+ -
- - + diff --git a/js/icons/src/Check.svelte b/js/icons/src/Check.svelte index 7c5fb8b96b50a..7ea8b356991c7 100644 --- a/js/icons/src/Check.svelte +++ b/js/icons/src/Check.svelte @@ -4,7 +4,7 @@ fill="none" stroke="currentColor" aria-hidden="true" - stroke-width="2" + stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> diff --git a/test/components/test_code.py b/test/components/test_code.py index 072e46d34c815..1d4169c73c1fb 100644 --- a/test/components/test_code.py +++ b/test/components/test_code.py @@ -32,7 +32,7 @@ def fn(a): "value": None, "language": None, "lines": 5, - "max_lines": 20, + "max_lines": None, "name": "code", "show_label": True, "label": None, @@ -45,6 +45,7 @@ def fn(a): "interactive": None, "proxy_url": None, "_selectable": False, + "wrap_lines": False, "key": None, } From 8ff76dbfcd5d77e47abbd876a94e07c9a2d5aa46 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 15:52:45 -0700 Subject: [PATCH 05/24] Add Semgrep to CI (#9498) * semgrep * Update semgrep.yml * ci --- .github/workflows/semgrep.yml | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 0000000000000..9accdd33773cc --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,68 @@ +name: Semgrep + +on: + workflow_run: + workflows: ["trigger-changeset"] + types: + - completed + +env: + CI: true + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" + +concurrency: + group: "${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}-${{ github.workflow_ref }}" + cancel-in-progress: true + +permissions: {} + +jobs: + changes: + permissions: + contents: read + pull-requests: read + name: "changes" + runs-on: ubuntu-latest + outputs: + should_run: ${{ steps.changes.outputs.should_run }} + sha: ${{ steps.changes.outputs.sha }} + source_branch: ${{ steps.changes.outputs.source_branch }} + source_repo: ${{ steps.changes.outputs.source_repo }} + pr_number: ${{ steps.changes.outputs.pr_number }} + steps: + - uses: actions/checkout@v4 + - uses: "gradio-app/gradio/.github/actions/changes@main" + id: changes + semgrep: + permissions: + contents: read + name: semgrep/ci + runs-on: ubuntu-latest + needs: changes + container: + image: semgrep/semgrep + if: (github.actor != 'dependabot[bot]') + steps: + - uses: actions/checkout@v4 + with: + repository: ${{ needs.changes.outputs.source_repo }} + ref: ${{ needs.changes.outputs.sha }} + - run: semgrep ci + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN2 }} + update-status: + permissions: + actions: read + statuses: write + runs-on: ubuntu-latest + needs: [changes, semgrep] + steps: + - name: update status + uses: gradio-app/github/actions/commit-status@main + with: + sha: ${{ needs.changes.outputs.sha }} + token: ${{ secrets.GITHUB_TOKEN }} + name: "Semgrep Results" + pr: ${{ needs.changes.outputs.pr_number }} + result: ${{ needs.semgrep.result == 'success' && 'success' || 'failure' }} + type: all \ No newline at end of file From b25a64e98b7acd5bd21f9ee7990e5d23f4b70a51 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 15:58:01 -0700 Subject: [PATCH 06/24] test semgrep in ci (#9507) * test * add changeset * add token * add filter --------- Co-authored-by: gradio-pr-bot --- .changeset/tall-dryers-own.md | 5 +++++ .github/workflows/semgrep.yml | 3 +++ gradio/interface.py | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/tall-dryers-own.md diff --git a/.changeset/tall-dryers-own.md b/.changeset/tall-dryers-own.md new file mode 100644 index 0000000000000..f959ad77fe5b4 --- /dev/null +++ b/.changeset/tall-dryers-own.md @@ -0,0 +1,5 @@ +--- +"gradio": minor +--- + +feat:test semgrep in ci diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 9accdd33773cc..d73d810c53461 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -33,6 +33,9 @@ jobs: - uses: actions/checkout@v4 - uses: "gradio-app/gradio/.github/actions/changes@main" id: changes + with: + filter: "gradio" + token: ${{ secrets.GITHUB_TOKEN }} semgrep: permissions: contents: read diff --git a/gradio/interface.py b/gradio/interface.py index e25a034498614..129e1fd816fb0 100644 --- a/gradio/interface.py +++ b/gradio/interface.py @@ -1,5 +1,5 @@ """ -This file defines two useful high-level abstractions to build Gradio apps: Interface and TabbedInterface. + This file defines two useful high-level abstractions to build Gradio apps: Interface and TabbedInterface. """ from __future__ import annotations From cc9674b101bd2287ae1c2409c4ce5ff6c86ac833 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 16:11:50 -0700 Subject: [PATCH 07/24] test semgrep 2 (#9509) * test semgrep 2 * add changeset * status * add yml : --------- Co-authored-by: gradio-pr-bot --- .changeset/swift-pumas-fail.md | 5 +++ .github/workflows/semgrep.yml | 45 +++++++++++---------------- .github/workflows/trigger-semgrep.yml | 29 +++++++++++++++++ gradio/interface.py | 2 +- 4 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 .changeset/swift-pumas-fail.md create mode 100644 .github/workflows/trigger-semgrep.yml diff --git a/.changeset/swift-pumas-fail.md b/.changeset/swift-pumas-fail.md new file mode 100644 index 0000000000000..6c5e60c677cd6 --- /dev/null +++ b/.changeset/swift-pumas-fail.md @@ -0,0 +1,5 @@ +--- +"gradio": minor +--- + +feat:test semgrep 2 diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index d73d810c53461..734bfde8ec435 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -2,7 +2,7 @@ name: Semgrep on: workflow_run: - workflows: ["trigger-changeset"] + workflows: ["trigger-semgrep"] types: - completed @@ -17,39 +17,32 @@ concurrency: permissions: {} jobs: - changes: - permissions: - contents: read - pull-requests: read - name: "changes" - runs-on: ubuntu-latest - outputs: - should_run: ${{ steps.changes.outputs.should_run }} - sha: ${{ steps.changes.outputs.sha }} - source_branch: ${{ steps.changes.outputs.source_branch }} - source_repo: ${{ steps.changes.outputs.source_repo }} - pr_number: ${{ steps.changes.outputs.pr_number }} - steps: - - uses: actions/checkout@v4 - - uses: "gradio-app/gradio/.github/actions/changes@main" - id: changes - with: - filter: "gradio" - token: ${{ secrets.GITHUB_TOKEN }} semgrep: permissions: contents: read name: semgrep/ci runs-on: ubuntu-latest - needs: changes container: image: semgrep/semgrep + outputs: + pr_number: ${{ steps.json.outputs.pr_number }} + sha: ${{ steps.json.outputs.sha }} if: (github.actor != 'dependabot[bot]') steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: changes + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + - uses: gradio-app/github/actions/json-to-output@main + id: json + with: + path: output.json - uses: actions/checkout@v4 with: - repository: ${{ needs.changes.outputs.source_repo }} - ref: ${{ needs.changes.outputs.sha }} + repository: ${{ steps.json.outputs.source_repo }} + ref: ${{ steps.json.outputs.sha }} - run: semgrep ci env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN2 }} @@ -58,14 +51,14 @@ jobs: actions: read statuses: write runs-on: ubuntu-latest - needs: [changes, semgrep] + needs: semgrep steps: - name: update status uses: gradio-app/github/actions/commit-status@main with: - sha: ${{ needs.changes.outputs.sha }} + sha: ${{ needs.semgrep.outputs.sha }} token: ${{ secrets.GITHUB_TOKEN }} name: "Semgrep Results" - pr: ${{ needs.changes.outputs.pr_number }} + pr: ${{ needs.semgrep.outputs.pr_number }} result: ${{ needs.semgrep.result == 'success' && 'success' || 'failure' }} type: all \ No newline at end of file diff --git a/.github/workflows/trigger-semgrep.yml b/.github/workflows/trigger-semgrep.yml new file mode 100644 index 0000000000000..08951f1f25298 --- /dev/null +++ b/.github/workflows/trigger-semgrep.yml @@ -0,0 +1,29 @@ +name: trigger-changeset +on: + pull_request: + branches: + - main + - 5.0-dev + +permissions: {} + +jobs: + changes: + permissions: + contents: read + pull-requests: read + name: "changes" + runs-on: ubuntu-latest + outputs: + should_run: ${{ steps.changes.outputs.should_run }} + sha: ${{ steps.changes.outputs.sha }} + pr_number: ${{ steps.changes.outputs.pr_number }} + source_branch: ${{ steps.changes.outputs.source_branch }} + source_repo: ${{ steps.changes.outputs.source_repo }} + steps: + - uses: actions/checkout@v4 + - uses: "gradio-app/gradio/.github/actions/changes@main" + id: changes + with: + filter: "gradio" + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/gradio/interface.py b/gradio/interface.py index 129e1fd816fb0..e25a034498614 100644 --- a/gradio/interface.py +++ b/gradio/interface.py @@ -1,5 +1,5 @@ """ - This file defines two useful high-level abstractions to build Gradio apps: Interface and TabbedInterface. +This file defines two useful high-level abstractions to build Gradio apps: Interface and TabbedInterface. """ from __future__ import annotations From 861f5e97ffde5f59e42cfa213364f19e84d799fd Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 16:22:34 -0700 Subject: [PATCH 08/24] Fix node process to run with correct server name (#9506) * fix node process * add changeset * add changeset * format * cleanup --------- Co-authored-by: gradio-pr-bot --- .changeset/thin-boxes-matter.md | 5 +++++ gradio/blocks.py | 19 ++++++++++--------- gradio/node_server.py | 15 +++++---------- gradio/routes.py | 17 +++++++++-------- 4 files changed, 29 insertions(+), 27 deletions(-) create mode 100644 .changeset/thin-boxes-matter.md diff --git a/.changeset/thin-boxes-matter.md b/.changeset/thin-boxes-matter.md new file mode 100644 index 0000000000000..fbd518932a621 --- /dev/null +++ b/.changeset/thin-boxes-matter.md @@ -0,0 +1,5 @@ +--- +"gradio": minor +--- + +feat:Fix node process to run with correct server name diff --git a/gradio/blocks.py b/gradio/blocks.py index 8519989932e74..cb501420d9e68 100644 --- a/gradio/blocks.py +++ b/gradio/blocks.py @@ -2424,15 +2424,16 @@ def reverse(text): self.node_path = os.environ.get( "GRADIO_NODE_PATH", "" if wasm_utils.IS_WASM else get_node_path() ) - self.node_server_name = node_server_name - self.node_port = node_port - - self.node_server_name, self.node_process, self.node_port = start_node_server( - server_name=self.node_server_name, - server_port=self.node_port, - node_path=self.node_path, - ssr_mode=self.ssr_mode, - ) + if self.ssr_mode: + self.node_server_name, self.node_process, self.node_port = ( + start_node_server( + server_name=node_server_name, + server_port=node_port, + node_path=self.node_path, + ) + ) + else: + self.node_server_name = self.node_port = self.node_process = None # self.server_app is included for backwards compatibility self.server_app = self.app = App.create_app( diff --git a/gradio/node_server.py b/gradio/node_server.py index b28ebfa643990..1b3d9f5e54db0 100644 --- a/gradio/node_server.py +++ b/gradio/node_server.py @@ -26,7 +26,6 @@ def start_node_server( server_name: str | None = None, server_port: int | None = None, node_path: str | None = None, - ssr_mode: bool | None = None, ) -> tuple[str | None, subprocess.Popen[bytes] | None, int | None]: """Launches a local server running the provided Interface Parameters: @@ -57,15 +56,11 @@ def start_node_server( else range(INITIAL_PORT_VALUE + 1, INITIAL_PORT_VALUE + 1 + TRY_NUM_PORTS) ) - node_process = None - node_port = None - - if ssr_mode: - (node_process, node_port) = start_node_process( - node_path=node_path or os.getenv("GRADIO_NODE_PATH"), - server_name=host, - server_ports=server_ports, - ) + node_process, node_port = start_node_process( + node_path=node_path or os.getenv("GRADIO_NODE_PATH"), + server_name=host, + server_ports=server_ports, + ) return server_name, node_process, node_port diff --git a/gradio/routes.py b/gradio/routes.py index f3ef0a1ee4e20..5894ce4c31015 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -374,8 +374,7 @@ async def conditional_routing_middleware( try: return await App.proxy_to_node( request, - os.getenv("GRADIO_SERVER_NAME", blocks.local_url) - or "0.0.0.0", + blocks.node_server_name or "0.0.0.0", blocks.node_port, App.app_port, request.url.scheme, @@ -1581,12 +1580,14 @@ def read_main(): blocks.node_server_name = node_server_name blocks.node_port = node_port - blocks.node_server_name, blocks.node_process, blocks.node_port = start_node_server( - server_name=blocks.node_server_name, - server_port=blocks.node_port, - node_path=blocks.node_path, - ssr_mode=blocks.ssr_mode, - ) + if blocks.ssr_mode: + blocks.node_server_name, blocks.node_process, blocks.node_port = ( + start_node_server( + server_name=blocks.node_server_name, + server_port=blocks.node_port, + node_path=blocks.node_path, + ) + ) gradio_app = App.create_app( blocks, From c46fe20f183328f7fe5a3ed83ba9e081e1e55492 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 16:54:20 -0700 Subject: [PATCH 09/24] yaml lint --- .github/workflows/semgrep.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 734bfde8ec435..03c1c4dbe62d8 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -1,32 +1,32 @@ name: Semgrep on: - workflow_run: - workflows: ["trigger-semgrep"] - types: - - completed - + workflow_run: + workflows: ["trigger-semgrep"] + types: + - completed + env: CI: true PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" concurrency: - group: "${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}-${{ github.workflow_ref }}" - cancel-in-progress: true + group: "${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}-${{ github.workflow_ref }}" + cancel-in-progress: true permissions: {} jobs: semgrep: permissions: - contents: read + contents: read name: semgrep/ci runs-on: ubuntu-latest container: image: semgrep/semgrep outputs: - pr_number: ${{ steps.json.outputs.pr_number }} - sha: ${{ steps.json.outputs.sha }} + pr_number: ${{ steps.json.outputs.pr_number }} + sha: ${{ steps.json.outputs.sha }} if: (github.actor != 'dependabot[bot]') steps: - name: Download artifact @@ -38,7 +38,7 @@ jobs: - uses: gradio-app/github/actions/json-to-output@main id: json with: - path: output.json + path: output.json - uses: actions/checkout@v4 with: repository: ${{ steps.json.outputs.source_repo }} @@ -61,4 +61,4 @@ jobs: name: "Semgrep Results" pr: ${{ needs.semgrep.outputs.pr_number }} result: ${{ needs.semgrep.result == 'success' && 'success' || 'failure' }} - type: all \ No newline at end of file + type: all From d8c939444451e8ce80a6256daba3ab7fbc1dcac3 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 2 Oct 2024 16:56:36 -0700 Subject: [PATCH 10/24] remove changesets (#9512) --- .changeset/swift-pumas-fail.md | 5 ----- .changeset/tall-dryers-own.md | 5 ----- 2 files changed, 10 deletions(-) delete mode 100644 .changeset/swift-pumas-fail.md delete mode 100644 .changeset/tall-dryers-own.md diff --git a/.changeset/swift-pumas-fail.md b/.changeset/swift-pumas-fail.md deleted file mode 100644 index 6c5e60c677cd6..0000000000000 --- a/.changeset/swift-pumas-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"gradio": minor ---- - -feat:test semgrep 2 diff --git a/.changeset/tall-dryers-own.md b/.changeset/tall-dryers-own.md deleted file mode 100644 index f959ad77fe5b4..0000000000000 --- a/.changeset/tall-dryers-own.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"gradio": minor ---- - -feat:test semgrep in ci From f8de5d2f0e67bef61bfaa2ba0764afef74a38801 Mon Sep 17 00:00:00 2001 From: "Yuichiro Tachibana (Tsuchiya)" Date: Thu, 3 Oct 2024 14:14:05 +0900 Subject: [PATCH 11/24] Add Bokeh plot demo (#9423) * Add Bokeh plot demo * Update notebook --------- Co-authored-by: Abubakar Abid --- demo/outbreak_forecast/requirements.txt | 1 - demo/outbreak_forecast/run.ipynb | 2 +- demo/outbreak_forecast/run.py | 24 +++++++++++++++------ js/spa/test/outbreak_forecast.spec.ts | 28 ++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/demo/outbreak_forecast/requirements.txt b/demo/outbreak_forecast/requirements.txt index 7a0aa970fdc8f..f513b41b84d2c 100644 --- a/demo/outbreak_forecast/requirements.txt +++ b/demo/outbreak_forecast/requirements.txt @@ -3,4 +3,3 @@ matplotlib bokeh plotly altair -opencv-python \ No newline at end of file diff --git a/demo/outbreak_forecast/run.ipynb b/demo/outbreak_forecast/run.ipynb index 1cfc4b9beaeae..48151f13b9897 100644 --- a/demo/outbreak_forecast/run.ipynb +++ b/demo/outbreak_forecast/run.ipynb @@ -1 +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 opencv-python"]}, {"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", "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", "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"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"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 gradio as gr\n", "from math import sqrt\n", "import numpy as np\n", "import pandas as pd\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", " import matplotlib.pyplot as plt\n", "\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", " import plotly.express as px\n", "\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", " import altair\n", "\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", " elif plot_type == \"Bokeh\":\n", " from bokeh.plotting import figure\n", " from bokeh.models import ColumnDataSource\n", "\n", " source = ColumnDataSource(df)\n", " fig = figure(title=\"Outbreak in \" + month, x_axis_label=\"Days since Day 0\", y_axis_label=\"Cases\")\n", " for country in countries:\n", " fig.line(\"day\", country, source=source, legend_label=country)\n", " return fig\n", " else:\n", " raise ValueError(\"A plot type must be selected\")\n", "\n", "inputs = [\n", " gr.Dropdown([\"Matplotlib\", \"Plotly\", \"Altair\", \"Bokeh\"], label=\"Plot Type\", value=\"Matplotlib\"),\n", " gr.Slider(1, 4, 3.2, label=\"R\"),\n", " gr.Dropdown([\"January\", \"February\", \"March\", \"April\", \"May\"], label=\"Month\", value=\"March\"),\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", " [\"Bokeh\", 3.2, \"April\", [\"Canada\", \"UK\"], False],\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/outbreak_forecast/run.py b/demo/outbreak_forecast/run.py index 1802e5766a6ef..797479db7999f 100644 --- a/demo/outbreak_forecast/run.py +++ b/demo/outbreak_forecast/run.py @@ -1,10 +1,6 @@ -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): @@ -21,6 +17,8 @@ def outbreak(plot_type, r, month, countries, social_distancing): df[country] = x ** (r) * (pop_count[country] + 1) if plot_type == "Matplotlib": + import matplotlib.pyplot as plt + fig = plt.figure() plt.plot(df["day"], df[countries].to_numpy()) plt.title("Outbreak in " + month) @@ -29,6 +27,8 @@ def outbreak(plot_type, r, month, countries, social_distancing): plt.legend(countries) return fig elif plot_type == "Plotly": + import plotly.express as px + fig = px.line(df, x="day", y=countries) fig.update_layout( title="Outbreak in " + month, @@ -37,16 +37,27 @@ def outbreak(plot_type, r, month, countries, social_distancing): ) return fig elif plot_type == "Altair": + import 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 + elif plot_type == "Bokeh": + from bokeh.plotting import figure + from bokeh.models import ColumnDataSource + + source = ColumnDataSource(df) + fig = figure(title="Outbreak in " + month, x_axis_label="Days since Day 0", y_axis_label="Cases") + for country in countries: + fig.line("day", country, source=source, legend_label=country) + return fig else: raise ValueError("A plot type must be selected") inputs = [ - gr.Dropdown(["Matplotlib", "Plotly", "Altair"], label="Plot Type"), + gr.Dropdown(["Matplotlib", "Plotly", "Altair", "Bokeh"], label="Plot Type", value="Matplotlib"), gr.Slider(1, 4, 3.2, label="R"), - gr.Dropdown(["January", "February", "March", "April", "May"], label="Month"), + gr.Dropdown(["January", "February", "March", "April", "May"], label="Month", value="March"), gr.CheckboxGroup( ["USA", "Canada", "Mexico", "UK"], label="Countries", value=["USA", "Canada"] ), @@ -62,6 +73,7 @@ def outbreak(plot_type, r, month, countries, social_distancing): ["Matplotlib", 2, "March", ["Mexico", "UK"], True], ["Altair", 2, "March", ["Mexico", "Canada"], True], ["Plotly", 3.6, "February", ["Canada", "Mexico", "UK"], False], + ["Bokeh", 3.2, "April", ["Canada", "UK"], False], ], cache_examples=True, ) diff --git a/js/spa/test/outbreak_forecast.spec.ts b/js/spa/test/outbreak_forecast.spec.ts index d3b3b24faeba6..b0e638904b027 100644 --- a/js/spa/test/outbreak_forecast.spec.ts +++ b/js/spa/test/outbreak_forecast.spec.ts @@ -52,7 +52,25 @@ test("selecting altair should show altair plot and pressing clear should clear o await expect(altair).toHaveCount(0); }); -test("switching between all 3 plot types and pressing submit should update output component to corresponding plot type", async ({ +test("selecting bokeh should show bokeh plot and pressing clear should clear output", async ({ + page +}) => { + await page.getByLabel("Plot Type").click(); + await page.getByRole("option", { name: "bokeh" }).click(); + await page.getByLabel("Month").click(); + await page.getByRole("option", { name: "January" }).click(); + await page.getByLabel("Social Distancing?").check(); + + await page.click("text=Submit"); + + const altair = await page.getByTestId("bokeh"); + await expect(altair).toHaveCount(1); + + await page.getByRole("button", { name: "Clear" }).click(); + await expect(altair).toHaveCount(0); +}); + +test("switching between all 4 plot types and pressing submit should update output component to corresponding plot type", async ({ page }) => { //Matplotlib @@ -82,4 +100,12 @@ test("switching between all 3 plot types and pressing submit should update outpu await page.click("text=Submit"); const altair = await page.getByTestId("altair"); await expect(altair).toHaveCount(1); + + //Bokeh + await page.getByLabel("Plot Type").click(); + await page.getByRole("option", { name: "Bokeh" }).click(); + + await page.click("text=Submit"); + const bokeh = await page.getByTestId("bokeh"); + await expect(bokeh).toHaveCount(1); }); From 3ec8e636766cc629444bc3cbc6b53deaf65f5ab1 Mon Sep 17 00:00:00 2001 From: Ali Abdalla Date: Thu, 3 Oct 2024 18:33:49 +0400 Subject: [PATCH 12/24] Expanding AI Playground Prompt for Qwen (#9452) * expand prompt for qwen * add changeset * clean * add changeset * heavily modify prompt * changes * many changes * fix weird syntax error * fix * ? * changes * fix requirements * formatting --------- Co-authored-by: gradio-pr-bot --- .changeset/dirty-lions-follow.md | 5 + js/_website/generate_jsons/generate.py | 11 +- .../generate_jsons/src/docs/__init__.py | 333 ++++++++++++++++-- .../src/lib/components/DemosLite.svelte | 44 ++- 4 files changed, 345 insertions(+), 48 deletions(-) create mode 100644 .changeset/dirty-lions-follow.md diff --git a/.changeset/dirty-lions-follow.md b/.changeset/dirty-lions-follow.md new file mode 100644 index 0000000000000..e1d472603a3d1 --- /dev/null +++ b/.changeset/dirty-lions-follow.md @@ -0,0 +1,5 @@ +--- +"website": minor +--- + +feat:Expanding AI Playground Prompt for Qwen diff --git a/js/_website/generate_jsons/generate.py b/js/_website/generate_jsons/generate.py index 4b48110b9095b..e49c469c3b632 100644 --- a/js/_website/generate_jsons/generate.py +++ b/js/_website/generate_jsons/generate.py @@ -6,7 +6,6 @@ from botocore import UNSIGNED from botocore.client import Config -from js._website.generate_jsons.src.docs import SYSTEM_PROMPT_8K from src import changelog, demos, docs, guides WEBSITE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) @@ -92,16 +91,20 @@ def create_dir_if_not_exists(path): demos.generate(make_dir(WEBSITE_DIR, "src/lib/json/demos.json")) guides.generate(make_dir(WEBSITE_DIR, "src/lib/json/guides/") + "/") -SYSTEM_PROMPT, SYSTEM_PROMPT_8K = docs.generate(make_dir(WEBSITE_DIR, "src/lib/json/docs.json")) -_, _ = docs.generate(make_dir(WEBSITE_DIR, "src/lib/templates/docs.json")) +SYSTEM_PROMPT = docs.generate(make_dir(WEBSITE_DIR, "src/lib/json/docs.json")) +_ = docs.generate(make_dir(WEBSITE_DIR, "src/lib/templates/docs.json")) changelog.generate(make_dir(WEBSITE_DIR, "src/lib/json/changelog.json")) get_latest_release() +# print("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") +# print(SYSTEM_PROMPT) +# print("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") + + with open(make_dir(WEBSITE_DIR, "src/lib/json/system_prompt.json"), "w+") as f: json.dump( { "SYSTEM": SYSTEM_PROMPT, - "SYSTEM_8K": SYSTEM_PROMPT_8K, }, f, ) diff --git a/js/_website/generate_jsons/src/docs/__init__.py b/js/_website/generate_jsons/src/docs/__init__.py index bfc4e49e499e9..524c81e8e226e 100644 --- a/js/_website/generate_jsons/src/docs/__init__.py +++ b/js/_website/generate_jsons/src/docs/__init__.py @@ -267,7 +267,7 @@ def organize_pages(): Never use any external library aside from: gradio, numpy, pandas, plotly, transformers_js and matplotlib. Do not include any code that is not necessary for the app to run. Respond with a full Gradio app. -Only respond with one full Gradio app. +Respond with a full Gradio app using correct syntax and features of the latest Gradio version. DO NOT write code that doesn't follow the signatures listed. Add comments explaining the code, but do not include any text that is not formatted as a Python comment. @@ -288,16 +288,63 @@ def greet(name): demo.launch() -Here are some more examples of Gradio apps: - +Below are all the class and function signatures in the Gradio library. """ - - -important_demos = ["annotatedimage_component", "audio_component_events", "audio_mixer", "blocks_chained_events", "blocks_essay", "blocks_essay_simple", "blocks_flipper", "blocks_form", "blocks_hello", "blocks_js_load", "blocks_js_methods", "blocks_kinematics", "blocks_layout", "blocks_plug", "blocks_simple_squares", "blocks_update", "blocks_xray", "calculator", "chatbot_consecutive", "chatbot_multimodal", "chatbot_simple", "chatbot_streaming", "chatinterface_multimodal", "custom_css", "datetimes", "diff_texts", "dropdown_key_up", "fake_diffusion", "fake_gan", "filter_records", "function_values", "gallery_component_events", "generate_tone", "hangman", "hello_blocks", "hello_blocks_decorator", "hello_world", "image_editor", "matrix_transpose", "model3D", "on_listener_decorator", "plot_component", "render_merge", "render_split", "reverse_audio_2", "sales_projections", "sentence_builder", "sepia_filter", "sort_records", "streaming_simple", "tabbed_interface_lite", "tax_calculator", "theme_soft", "timer", "timer_simple", "variable_outputs", "video_identity"] - -important_demos_8k = ["blocks_essay_simple", "blocks_flipper", "blocks_form", "blocks_hello", "blocks_kinematics", "blocks_layout", "blocks_simple_squares", "calculator", "chatbot_consecutive", "chatbot_simple", "chatbot_streaming", "chatinterface_multimodal", "datetimes", "diff_texts", "dropdown_key_up", "fake_diffusion", "filter_records", "generate_tone", "hangman", "hello_blocks", "hello_blocks_decorator", "hello_world", "image_editor", "matrix_transpose", "model3D", "on_listener_decorator", "plot_component", "render_merge", "render_split", "reverse_audio_2", "sepia_filter", "sort_records", "streaming_simple", "tabbed_interface_lite", "tax_calculator", "theme_soft", "timer", "timer_simple", "variable_outputs", "video_identity"] +for key in gradio_docs: + if key in ["events", "events_matrix"]: + continue + if "name" in key: + o = gradio_docs[key] + signature = f"""{o['name']}({', '.join([ + p['name'] + + ': ' + p['annotation'] + + (' = ' + p['default'] if 'default' in p else '') + for p in o['parameters']])})""" + SYSTEM_PROMPT += f"{signature}\n" + SYSTEM_PROMPT += f"{o['description']}\n\n" + else: + for c in gradio_docs[key]: + o = gradio_docs[key][c] + signature = f"""{o['name']}({', '.join([ + p['name'] + + ': ' + p['annotation'] + + (' = ' + p['default'] if 'default' in p else '') + for p in o['parameters']])})""" + SYSTEM_PROMPT += f"{signature}\n" + SYSTEM_PROMPT += f"{o['description']}\n\n" + if "fns" in o and key != "components": + for f in o["fns"]: + signature = f"""{o['name']}.{f['name']}({', '.join([ + p['name'] + + ': ' + p['annotation'] + + (' = ' + p['default'] if 'default' in p else '') + for p in f['parameters']])})""" + SYSTEM_PROMPT += f"{signature}\n" + SYSTEM_PROMPT += f"{f['description']}\n\n" + +SYSTEM_PROMPT += "\nEvent listeners allow Gradio to respond to user interactions with the UI components defined in a Blocks app. When a user interacts with an element, such as changing a slider value or uploading an image, a function is called.\n" + +SYSTEM_PROMPT += "All event listeners have the same signature:\n" + +f = gradio_docs["components"]["audio"]["fns"][0] +signature = f""".({', '.join([ + p['name'] + + ': ' + p['annotation'] + + (' = ' + p['default'] if 'default' in p else '') + for p in f['parameters']])})""" +SYSTEM_PROMPT += signature +SYSTEM_PROMPT += "\nEach component only supports some specific events. Below is a list of all gradio components and every event that each component supports. If an event is supported by a component, it is a valid method of the component." +for component in gradio_docs["events_matrix"]: + SYSTEM_PROMPT += f"{component}: {', '.join(gradio_docs['events_matrix'][component])}\n\n" + + +SYSTEM_PROMPT += "Below are examples of full end-to-end Gradio apps:\n\n" + +# 'audio_component_events', 'audio_mixer', 'blocks_essay', 'blocks_chained_events', 'blocks_xray', 'chatbot_multimodal', 'sentence_builder', 'custom_css', 'blocks_update', 'fake_gan' +# important_demos = ["annotatedimage_component", "blocks_essay_simple", "blocks_flipper", "blocks_form", "blocks_hello", "blocks_js_load", "blocks_js_methods", "blocks_kinematics", "blocks_layout", "blocks_plug", "blocks_simple_squares", "calculator", "chatbot_consecutive", "chatbot_simple", "chatbot_streaming", "chatinterface_multimodal", "datetimes", "diff_texts", "dropdown_key_up", "fake_diffusion", "fake_gan", "filter_records", "function_values", "gallery_component_events", "generate_tone", "hangman", "hello_blocks", "hello_blocks_decorator", "hello_world", "image_editor", "matrix_transpose", "model3D", "on_listener_decorator", "plot_component", "render_merge", "render_split", "reverse_audio_2", "sales_projections", "sepia_filter", "sort_records", "streaming_simple", "tabbed_interface_lite", "tax_calculator", "theme_soft", "timer", "timer_simple", "variable_outputs", "video_identity"] +important_demos = ['custom_css', "annotatedimage_component", "blocks_essay_simple", "blocks_flipper", "blocks_form", "blocks_hello", "blocks_js_load", "blocks_js_methods", "blocks_kinematics", "blocks_layout", "blocks_plug", "blocks_simple_squares", "calculator", "chatbot_consecutive", "chatbot_simple", "chatbot_streaming", "chatinterface_multimodal", "datetimes", "diff_texts", "dropdown_key_up", "fake_diffusion", "filter_records", "function_values", "gallery_component_events", "generate_tone", "hangman", "hello_blocks", "hello_blocks_decorator", "hello_world", "image_editor", "matrix_transpose", "model3D", "on_listener_decorator", "plot_component", "render_merge", "render_split", "reverse_audio_2", "sales_projections", "sepia_filter", "sort_records", "streaming_simple", "tabbed_interface_lite", "tax_calculator", "theme_soft", "timer", "timer_simple", "variable_outputs", "video_identity"] def length(demo): @@ -310,10 +357,8 @@ def length(demo): demo_code = demo_code.replace("# type: ignore", "").replace('if __name__ == "__main__":\n ', "") return len(demo_code) - -SYSTEM_PROMPT += "\n\nHere are some demos showcasing full Gradio apps: \n\n" - -SYSTEM_PROMPT_8K = SYSTEM_PROMPT +# important_demos = sorted(important_demos, key=length, reverse=True) +# print(important_demos) for demo in important_demos: if os.path.exists(os.path.join(DEMOS_DIR, demo, "run.py")): @@ -327,35 +372,246 @@ def length(demo): SYSTEM_PROMPT += "Code: \n\n" SYSTEM_PROMPT += f"{demo_code}\n\n" -for demo in important_demos_8k: - if os.path.exists(os.path.join(DEMOS_DIR, demo, "run.py")): - demo_file = os.path.join(DEMOS_DIR, demo, "run.py") - else: - continue - with open(demo_file) as run_py: - demo_code = run_py.read() - demo_code = demo_code.replace("# type: ignore", "").replace('if __name__ == "__main__":\n ', "") - SYSTEM_PROMPT_8K += f"Name: {demo.replace('_', ' ')}\n" - SYSTEM_PROMPT_8K += "Code: \n\n" - SYSTEM_PROMPT_8K += f"{demo_code}\n\n" - SYSTEM_PROMPT += """ +The latest verstion of Gradio includes some breaking changes, and important new features you should be aware of. Here is a list of the important changes: -The following RULES must be followed. Whenever you are forming a response, after each sentence ensure all rules have been followed otherwise start over, forming a new response and repeat until the finished response follows all the rules. then send the response. +1. Streaming audio, images, and video as input and output are now fully supported in Gradio. + +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. +Here's an example of a Gradio app that streams a sequence of images: + +CODE: + +import gradio as gr +import numpy as np +import time + +def fake_diffusion(steps): + rng = np.random.default_rng() + for i in range(steps): + time.sleep(1) + image = rng.random(size=(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") + +demo.launch() + + + +Gradio can stream audio and video directly from your generator function. This lets your user hear your audio or see your video nearly as soon as it's yielded by your function. All you have to do is + +Set streaming=True in your gr.Audio or gr.Video output component. +Write a python generator that yields the next "chunk" of audio or video. +Set autoplay=True so that the media starts playing automatically. + +For audio, the next "chunk" can be either an .mp3 or .wav file or a bytes sequence of audio. For video, the next "chunk" has to be either .mp4 file or a file with h.264 codec with a .ts extension. For smooth playback, make sure chunks are consistent lengths and larger than 1 second. + +Here's an example gradio app that streams audio: + +CODE: + +import gradio as gr +from time import sleep + +def keep_repeating(audio_file): + for _ in range(10): + sleep(0.5) + yield audio_file + +gr.Interface(keep_repeating, + gr.Audio(sources=["microphone"], type="filepath"), + gr.Audio(streaming=True, autoplay=True) +).launch() + + +Here's an example gradio app that streams video: + +CODE: + +import gradio as gr +from time import sleep + +def keep_repeating(video_file): + for _ in range(10): + sleep(0.5) + yield video_file + +gr.Interface(keep_repeating, + gr.Video(sources=["webcam"], format="mp4"), + gr.Video(streaming=True, autoplay=True) +).launch() + +Streaming Inputs: + +Gradio also allows you to stream images from a user's camera or audio chunks from their microphone into your event handler. This can be used to create real-time object detection apps or conversational chat applications with Gradio. + +Currently, the gr.Image and the gr.Audio components support input streaming via the stream event. + +Here's an example, which simply returns the webcam stream unmodified: + +CODE: + +import gradio as gr +import numpy as np +import cv2 + +def transform_cv2(frame, transform): + if transform == "cartoon": + # prepare color + img_color = cv2.pyrDown(cv2.pyrDown(frame)) + for _ in range(6): + img_color = cv2.bilateralFilter(img_color, 9, 9, 7) + img_color = cv2.pyrUp(cv2.pyrUp(img_color)) + + # prepare edges + img_edges = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) + img_edges = cv2.adaptiveThreshold( + cv2.medianBlur(img_edges, 7), + 255, + cv2.ADAPTIVE_THRESH_MEAN_C, + cv2.THRESH_BINARY, + 9, + 2, + ) + img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB) + # combine color and edges + img = cv2.bitwise_and(img_color, img_edges) + return img + elif transform == "edges": + # perform edge detection + img = cv2.cvtColor(cv2.Canny(frame, 100, 200), cv2.COLOR_GRAY2BGR) + return img + else: + return np.flipud(frame) + + +css=".my-group {max-width: 500px !important; max-height: 500px !important;}\n.my-column {display: flex !important; justify-content: center !important; align-items: center !important};" + +with gr.Blocks(css=css) as demo: + with gr.Column(elem_classes=["my-column"]): + with gr.Group(elem_classes=["my-group"]): + transform = gr.Dropdown(choices=["cartoon", "edges", "flip"], + value="flip", label="Transformation") + input_img = gr.Image(sources=["webcam"], type="numpy") + input_img.stream(transform_cv2, [input_img, transform], [input_img], time_limit=30, stream_every=0.1) + + +demo.launch() + + + +There are two unique keyword arguments for the stream event: + +time_limit - This is the amount of time the gradio server will spend processing the event. Media streams are naturally unbounded so it's important to set a time limit so that one user does not hog the Gradio queue. The time limit only counts the time spent processing the stream, not the time spent waiting in the queue. The orange bar displayed at the bottom of the input image represents the remaining time. When the time limit expires, the user will automatically rejoin the queue. + +stream_every - This is the frequency (in seconds) with which the stream will capture input and send it to the server. For demos like image detection or manipulation, setting a smaller value is desired to get a "real-time" effect. For demos like speech transcription, a higher value is useful so that the transcription algorithm has more context of what's being said. + + + +Your streaming function should be stateless. It should take the current input and return its corresponding output. However, there are cases where you may want to keep track of past inputs or outputs. For example, you may want to keep a buffer of the previous k inputs to improve the accuracy of your transcription demo. You can do this with Gradio's gr.State() component. + +Let's showcase this with a sample demo: + +CODE: + +def transcribe_handler(current_audio, state, transcript): + next_text = transcribe(current_audio, history=state) + state.append(current_audio) + state = state[-3:] + return state, transcript + next_text + +with gr.Blocks() as demo: + with gr.Row(): + with gr.Column(): + mic = gr.Audio(sources="microphone") + state = gr.State(value=[]) + with gr.Column(): + transcript = gr.Textbox(label="Transcript") + mic.stream(transcribe_handler, [mic, state, transcript], [state, transcript], + time_limit=10, stream_every=1) + + +demo.launch() + + +2. Audio files are no longer converted to .wav automatically + +Previously, the default value of the format in the gr.Audio component was wav, meaning that audio files would be converted to the .wav format before being processed by a prediction function or being returned to the user. Now, the default value of format is None, which means any audio files that have an existing format are kept as is. + +3. The 'every' parameter is no longer supported in event listeners + +Previously, if you wanted to run an event 'every' X seconds after a certain trigger, you could set `every=` in the event listener. This is no longer supported — do the following instead: + +- create a `gr.Timer` component, and +- use the `.tick()` method to trigger the event. + +E.g., replace something like this: + +with gr.Blocks() as demo: + a = gr.Textbox() + b = gr.Textbox() + btn = gr.Button("Start") + btn.click(lambda x:x, a, b, every=1) + +with this: + +with gr.Blocks() as demo: + a = gr.Textbox() + b = gr.Textbox() + btn = gr.Button("Start") + t = gr.Timer(1, active=False) + t.tick(lambda x:x, a, b) + btn.click(lambda: gr.Timer(active=True), None, t) + +This makes it easy to configure the timer as well to change its frequency or stop the event, e.g. + +# some code... +stop_btn = gr.Button("Stop") + stop_btn.click(lambda: gr.Timer(active=False), None, t) # deactivates timer +fast_btn = gr.Button("Fast") + fast_btn.click(lambda: gr.Timer(0.1), None, t) # makes timer tick every 0.1s + + +4. The `undo_btn`, `retry_btn` and `clear_btn` parameters of `ChatInterface` have been removed +5. Passing a tuple to `gr.Code` is not supported +6. The `concurrency_count` parameter has been removed from `.queue()` +7. The `additional_inputs_accordion_name` parameter has been removed from `gr.ChatInterface` +8. The `thumbnail` parameter has been removed from `gr.Interface` +9. The `root` parameter in `gr.FileExplorer` has been removed +10. The `signed_in_value` parameter in `gr.LoginButton` has been removed +11. The `gr.LogoutButton` component has been removed +12. The `gr.make_waveform` method has been removed from the library +13. SVGs are not accepted as input images into the `gr.Image` component unless `type=filepath` +14. The `height` parameter in `gr.DataFrame` has been renamed to `max_height` +15. The `likeable` parameter of `gr.Chatbot` has been removed. The chatbot will display like buttons whenever the `like` event is defined. +16. By default user messages are not likeable in the `gr.Chatbot`. To display like buttons in the user message, set the `user_like_button` parameter of the `like` event to True. +17. The argument for lazy-caching examples has been changed + +Previously, to lazy-cache examples, you would pass in “lazy” to the `cache_examples` parameter in `Interface`, `Chatinterface` , or `Examples`. Now, there is a separate `cache_mode` parameter, which governs whether caching should be `"lazy"` or `"eager"` . So if your code was previously: + +Now, your code should look like this: + +chatbot = gr.ChatInterface( + double, + examples=["hello", "hi"], + cache_examples=True, + cache_mode="lazy", +) -RULES: -Only respond with code, not text. -Only respond with valid Python syntax. -Never include backticks in your response such as ``` or ```python. -Never use any external library aside from: gradio, numpy, pandas, plotly, transformers_js and matplotlib. -Do not include any code that is not necessary for the app to run. -Respond with a full Gradio app. -Only respond with one full Gradio app. -Add comments explaining the code, but do not include any text that is not formatted as a Python comment. """ -SYSTEM_PROMPT_8K += """ + +SYSTEM_PROMPT += """ The following RULES must be followed. Whenever you are forming a response, after each sentence ensure all rules have been followed otherwise start over, forming a new response and repeat until the finished response follows all the rules. then send the response. @@ -363,15 +619,14 @@ def length(demo): Only respond with code, not text. Only respond with valid Python syntax. Never include backticks in your response such as ``` or ```python. -Never use any external library aside from: gradio, numpy, pandas, plotly, transformers_js and matplotlib. +Never import any external library aside from: gradio, numpy, pandas, plotly, transformers_js and matplotlib. Do not import any other library like pytesseract or PIL unless requested in the prompt. Do not include any code that is not necessary for the app to run. -Respond with a full Gradio app. +Respond with a full Gradio app using correct syntax and features of the latest Gradio version. DO NOT write code that doesn't follow the signatures listed. Only respond with one full Gradio app. Add comments explaining the code, but do not include any text that is not formatted as a Python comment. """ - def generate(json_path): with open(json_path, "w+") as f: json.dump(docs, f) - return SYSTEM_PROMPT, SYSTEM_PROMPT_8K \ No newline at end of file + return SYSTEM_PROMPT \ No newline at end of file diff --git a/js/_website/src/lib/components/DemosLite.svelte b/js/_website/src/lib/components/DemosLite.svelte index c57c9857e2689..652fd1c84ce17 100644 --- a/js/_website/src/lib/components/DemosLite.svelte +++ b/js/_website/src/lib/components/DemosLite.svelte @@ -20,6 +20,7 @@ let compare = false; const workerUrl = "https://playground-worker.pages.dev/api/generate"; + // const workerUrl = "http://localhost:5174/api/generate"; let model_info = ""; let abortController: AbortController | null = null; @@ -27,7 +28,6 @@ async function* streamFromWorker( query: string, system_prompt: string, - system_prompt_8k: string, signal: AbortSignal ) { const response = await fetch(workerUrl, { @@ -37,12 +37,18 @@ }, body: JSON.stringify({ query: query, - SYSTEM_PROMPT: system_prompt, - SYSTEM_PROMPT_8K: system_prompt_8k + SYSTEM_PROMPT: system_prompt }), signal }); + if (response.status == 429) { + generation_error = "Too busy... :( Please try again later."; + await new Promise((resolve) => setTimeout(resolve, 4000)); + generation_error = ""; + return; + } + const reader = response.body?.getReader(); const decoder = new TextDecoder(); let buffer = ""; @@ -116,7 +122,6 @@ for await (const chunk of streamFromWorker( query, SYSTEM_PROMPT.SYSTEM, - SYSTEM_PROMPT.SYSTEM_8K, abortController.signal )) { if (chunk.choices && chunk.choices.length > 0) { @@ -284,6 +289,15 @@ } controller.install(cleanupRequirements(current_demo.requirements)); + controller.install([ + "numpy", + "pandas", + "matplotlib", + "plotly", + "transformers_js_py", + "requests", + "pillow" + ]); } $: if (mounted) { // When the selected demo changes, we need to call controller.install() immediately without debouncing. @@ -294,7 +308,16 @@ } $: if (mounted) { debounced_install && - debounced_install(cleanupRequirements(requirementsStr.split("\n"))); + debounced_install(cleanupRequirements(requirementsStr.split("\n"))) && + debounced_install([ + "numpy", + "pandas", + "matplotlib", + "plotly", + "transformers_js_py", + "requests", + "pillow" + ]); } let position = 0.5; @@ -571,6 +594,16 @@ + {:else} +
+

+ Note: This is still an + experimental feature. The + generated code may be incorrect. +

+
{/if} @@ -605,6 +638,7 @@ >
Ask AI
+ BETA {:else}