mirror of
https://github.com/modelscope/FunASR.git
synced 2026-10-12 02:19:18 +00:00
demo: add Gradio OpenAI API browser demo
Add an optional Gradio browser UI and docs for the FunASR OpenAI-compatible API.
This commit is contained in:
@@ -198,7 +198,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12
|
||||
```
|
||||
|
||||
[OpenAI API example →](./examples/openai_api/) · [Client recipes →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript recipes →](./examples/openai_api/JAVASCRIPT.md) · [Kubernetes template →](./examples/openai_api/kubernetes/) · [Workflow recipes →](./examples/openai_api/WORKFLOWS.md) · [Postman collection →](./examples/openai_api/POSTMAN.md) · [OpenAPI spec →](./examples/openai_api/OPENAPI.md) · [Deployment matrix →](./docs/deployment_matrix.md) · [Deployment docs →](./runtime/readme.md) · [Agent integration →](https://modelscope.github.io/FunASR/agent.html)
|
||||
[OpenAI API example →](./examples/openai_api/) · [Gradio demo →](./examples/openai_api/GRADIO.md) · [Client recipes →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript recipes →](./examples/openai_api/JAVASCRIPT.md) · [Kubernetes template →](./examples/openai_api/kubernetes/) · [Workflow recipes →](./examples/openai_api/WORKFLOWS.md) · [Postman collection →](./examples/openai_api/POSTMAN.md) · [OpenAPI spec →](./examples/openai_api/OPENAPI.md) · [Deployment matrix →](./docs/deployment_matrix.md) · [Deployment docs →](./runtime/readme.md) · [Agent integration →](https://modelscope.github.io/FunASR/agent.html)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12
|
||||
```
|
||||
|
||||
[OpenAI API 示例 →](./examples/openai_api/README_zh.md) · [客户端配方 →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript 配方 →](./examples/openai_api/JAVASCRIPT_zh.md) · [Kubernetes 模板 →](./examples/openai_api/kubernetes/README_zh.md) · [工作流配方 →](./examples/openai_api/WORKFLOWS_zh.md) · [Postman 集合 →](./examples/openai_api/POSTMAN_zh.md) · [OpenAPI 规范 →](./examples/openai_api/OPENAPI_zh.md) · [部署选型 →](./docs/deployment_matrix_zh.md) · [部署文档 →](./runtime/readme_cn.md) · [Agent 集成 →](https://modelscope.github.io/FunASR/agent.html)
|
||||
[OpenAI API 示例 →](./examples/openai_api/README_zh.md) · [Gradio Demo →](./examples/openai_api/GRADIO_zh.md) · [客户端配方 →](./examples/openai_api/CLIENTS.md) · [JavaScript/TypeScript 配方 →](./examples/openai_api/JAVASCRIPT_zh.md) · [Kubernetes 模板 →](./examples/openai_api/kubernetes/README_zh.md) · [工作流配方 →](./examples/openai_api/WORKFLOWS_zh.md) · [Postman 集合 →](./examples/openai_api/POSTMAN_zh.md) · [OpenAPI 规范 →](./examples/openai_api/OPENAPI_zh.md) · [部署选型 →](./docs/deployment_matrix_zh.md) · [部署文档 →](./runtime/readme_cn.md) · [Agent 集成 →](https://modelscope.github.io/FunASR/agent.html)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Use the Python API from the README. It is the shortest route for validating inst
|
||||
|
||||
### I want a local replacement for cloud transcription
|
||||
|
||||
Use the OpenAI-compatible API. It exposes `/v1/audio/transcriptions`, `/v1/models`, `/health`, and Swagger docs. Start with `sensevoice`, run `examples/openai_api/smoke_test.sh` or `examples/openai_api/smoke_test.py`, then connect existing SDK or HTTP clients using [client recipes](../examples/openai_api/CLIENTS.md) and [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md). For Dify, n8n, HTTP nodes, or webhook workers, follow the [workflow recipes](../examples/openai_api/WORKFLOWS.md). For API gateways, developer portals, and schema-driven imports, use the [OpenAPI spec](../examples/openai_api/OPENAPI.md).
|
||||
Use the OpenAI-compatible API. It exposes `/v1/audio/transcriptions`, `/v1/models`, `/health`, and Swagger docs. Start with `sensevoice`, run `examples/openai_api/smoke_test.sh` or `examples/openai_api/smoke_test.py`, then connect existing SDK or HTTP clients using [client recipes](../examples/openai_api/CLIENTS.md) and [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md). For browser upload or microphone demos, use the [Gradio browser demo](../examples/openai_api/GRADIO.md). For Dify, n8n, HTTP nodes, or webhook workers, follow the [workflow recipes](../examples/openai_api/WORKFLOWS.md). For API gateways, developer portals, and schema-driven imports, use the [OpenAPI spec](../examples/openai_api/OPENAPI.md).
|
||||
|
||||
### I want a repeatable container demo
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
### 我想替代云端转写服务
|
||||
|
||||
使用 OpenAI 兼容 API。它提供 `/v1/audio/transcriptions`、`/v1/models`、`/health` 和 Swagger docs。先用 `sensevoice` 跑通 `examples/openai_api/smoke_test.sh` 或 `examples/openai_api/smoke_test.py`,再根据 [客户端配方](../examples/openai_api/CLIENTS.md) 和 [JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 接入 SDK 或 HTTP 客户端。Dify、n8n、HTTP 节点或 webhook worker 可参考 [工作流配方](../examples/openai_api/WORKFLOWS_zh.md)。API 网关、开发者门户或按 schema 导入时可使用 [OpenAPI 规范](../examples/openai_api/OPENAPI_zh.md)。
|
||||
使用 OpenAI 兼容 API。它提供 `/v1/audio/transcriptions`、`/v1/models`、`/health` 和 Swagger docs。先用 `sensevoice` 跑通 `examples/openai_api/smoke_test.sh` 或 `examples/openai_api/smoke_test.py`,再根据 [客户端配方](../examples/openai_api/CLIENTS.md) 和 [JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 接入 SDK 或 HTTP 客户端。浏览器上传或麦克风 demo 可使用 [Gradio 浏览器 Demo](../examples/openai_api/GRADIO_zh.md)。Dify、n8n、HTTP 节点或 webhook worker 可参考 [工作流配方](../examples/openai_api/WORKFLOWS_zh.md)。API 网关、开发者门户或按 schema 导入时可使用 [OpenAPI 规范](../examples/openai_api/OPENAPI_zh.md)。
|
||||
|
||||
### 我想要可复现的容器 demo
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ FunASR is useful far beyond a single offline transcription command. This page co
|
||||
| Transcribe one file locally | [README quick start](../README.md#quick-start) and [model selection guide](./model_selection.md) | Verify install, model choice, and model download in minutes. |
|
||||
| Compare accuracy and speed | [Benchmark report](https://modelscope.github.io/FunASR/benchmark.html) | Reproduce the 184-file long-audio benchmark before choosing a model. |
|
||||
| Migrate from Whisper/cloud ASR | [Migration guide](./migration_from_whisper.md) | Map existing pipelines to FunASR, benchmark representative audio, and plan a safe rollout. |
|
||||
| Build a private speech API | [OpenAI-compatible API example](../examples/openai_api/), [client recipes](../examples/openai_api/CLIENTS.md), [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md), and [workflow recipes](../examples/openai_api/WORKFLOWS.md) | Reuse LangChain, Dify, n8n, AutoGen, and other OpenAI-style clients without sending audio to a cloud ASR provider. |
|
||||
| Build a private speech API | [OpenAI-compatible API example](../examples/openai_api/), [Gradio browser demo](../examples/openai_api/GRADIO.md), [client recipes](../examples/openai_api/CLIENTS.md), [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md), and [workflow recipes](../examples/openai_api/WORKFLOWS.md) | Reuse LangChain, Dify, n8n, AutoGen, and other OpenAI-style clients without sending audio to a cloud ASR provider. |
|
||||
| Add speech input to agents | [MCP server](../examples/mcp_server/) and [voice input](../examples/voice_input/) | Connect local ASR to Claude, Cursor, and desktop agent workflows. |
|
||||
| Choose a deployment path | [Deployment matrix](./deployment_matrix.md) | Compare Python API, OpenAI API, Docker Compose, Kubernetes, WebSocket, vLLM, MCP, batch, subtitles, and Triton. |
|
||||
| Serve streaming ASR | [Runtime service docs](../runtime/readme.md) | Run WebSocket or service-mode ASR for live captioning and call-center style workloads. |
|
||||
@@ -38,6 +38,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
Recommended next steps:
|
||||
|
||||
- Run the [OpenAI-compatible API smoke test](../examples/openai_api/smoke_test.sh) or the cross-platform [Python smoke test](../examples/openai_api/smoke_test.py).
|
||||
- For browser upload or microphone demos, start from the [Gradio browser demo](../examples/openai_api/GRADIO.md).
|
||||
- For Node.js or Next.js services, start from the [JavaScript/TypeScript recipes](../examples/openai_api/JAVASCRIPT.md).
|
||||
- For cluster services, start from the [Kubernetes deployment template](../examples/openai_api/kubernetes/).
|
||||
- Add authentication and network controls at your service boundary.
|
||||
|
||||
@@ -9,7 +9,7 @@ FunASR 不只是一个离线转写命令。这个页面把常见的评测、部
|
||||
| 本地转写一个文件 | [README 快速开始](../README_zh.md#快速开始) 和 [模型选择指南](./model_selection_zh.md) | 几分钟内验证安装、模型选择、模型下载和首次推理。 |
|
||||
| 对比准确率和速度 | [性能评测报告](https://modelscope.github.io/FunASR/zh/benchmark.html) | 选型前先查看 184 条长音频评测结果。 |
|
||||
| 从 Whisper/云端 ASR 迁移 | [迁移指南](./migration_from_whisper_zh.md) | 将现有流水线映射到 FunASR,用代表性音频评测并规划安全上线。 |
|
||||
| 搭建私有语音 API | [OpenAI 兼容 API 示例](../examples/openai_api/README_zh.md)、[客户端配方](../examples/openai_api/CLIENTS.md)、[JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 和 [工作流配方](../examples/openai_api/WORKFLOWS_zh.md) | 复用 LangChain、Dify、n8n、AutoGen 等 OpenAI 风格客户端,音频不出内网。 |
|
||||
| 搭建私有语音 API | [OpenAI 兼容 API 示例](../examples/openai_api/README_zh.md)、[Gradio 浏览器 Demo](../examples/openai_api/GRADIO_zh.md)、[客户端配方](../examples/openai_api/CLIENTS.md)、[JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 和 [工作流配方](../examples/openai_api/WORKFLOWS_zh.md) | 复用 LangChain、Dify、n8n、AutoGen 等 OpenAI 风格客户端,音频不出内网。 |
|
||||
| 给 Agent 增加语音输入 | [MCP 服务](../examples/mcp_server/) 和 [语音输入示例](../examples/voice_input/) | 将本地 ASR 接入 Claude、Cursor 和桌面 Agent 工作流。 |
|
||||
| 选择部署路径 | [部署选型表](./deployment_matrix_zh.md) | 对比 Python API、OpenAI API、Docker Compose、Kubernetes、WebSocket、vLLM、MCP、批处理、字幕和 Triton。 |
|
||||
| 部署流式 ASR | [Runtime 服务文档](../runtime/readme_cn.md) | 面向实时字幕、客服、会议等低延迟场景。 |
|
||||
@@ -38,6 +38,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
建议下一步:
|
||||
|
||||
- 运行 [OpenAI 兼容 API smoke test](../examples/openai_api/smoke_test.sh) 或跨平台 [Python smoke test](../examples/openai_api/smoke_test.py)。
|
||||
- 浏览器上传或麦克风 demo 可从 [Gradio 浏览器 Demo](../examples/openai_api/GRADIO_zh.md) 开始。
|
||||
- Node.js 或 Next.js 服务可从 [JavaScript/TypeScript 配方](../examples/openai_api/JAVASCRIPT_zh.md) 开始。
|
||||
- 集群内服务可从 [Kubernetes 部署模板](../examples/openai_api/kubernetes/README_zh.md) 开始。
|
||||
- 在服务边界增加鉴权、限流和网络访问控制。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Client Recipes for the FunASR OpenAI-Compatible API
|
||||
|
||||
Use this page when `funasr-server` is already running and you want to connect an existing application, agent tool, or workflow engine to local speech recognition. For JavaScript, TypeScript, and Next.js examples, see the [JavaScript/TypeScript recipes](JAVASCRIPT.md) or [Chinese JavaScript/TypeScript recipes](JAVASCRIPT_zh.md). For Dify, n8n, HTTP nodes, and webhook workers, see the [workflow recipes](WORKFLOWS.md) or [Chinese workflow recipes](WORKFLOWS_zh.md). For no-code API smoke tests, import the [Postman collection](POSTMAN.md). For schema-driven imports or client generation, use the [OpenAPI spec](OPENAPI.md).
|
||||
Use this page when `funasr-server` is already running and you want to connect an existing application, agent tool, or workflow engine to local speech recognition. For JavaScript, TypeScript, and Next.js examples, see the [JavaScript/TypeScript recipes](JAVASCRIPT.md) or [Chinese JavaScript/TypeScript recipes](JAVASCRIPT_zh.md). For Dify, n8n, HTTP nodes, and webhook workers, see the [workflow recipes](WORKFLOWS.md) or [Chinese workflow recipes](WORKFLOWS_zh.md). For browser upload or microphone demos, use the [Gradio browser demo](GRADIO.md). For no-code API smoke tests, import the [Postman collection](POSTMAN.md). For schema-driven imports or client generation, use the [OpenAPI spec](OPENAPI.md).
|
||||
|
||||
## Preflight
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Gradio Browser Demo for the FunASR OpenAI-Compatible API
|
||||
|
||||
Use this demo when you want a browser UI for uploading or recording audio while the FunASR OpenAI-compatible API server runs locally, in Docker, or behind a private Kubernetes service.
|
||||
|
||||
The Gradio app does not load FunASR models itself. It calls the same `/health`, `/v1/models`, and `/v1/audio/transcriptions` endpoints used by the smoke tests, SDK recipes, Postman collection, and OpenAPI spec.
|
||||
|
||||
## 1. Start the API server
|
||||
|
||||
From `examples/openai_api`:
|
||||
|
||||
```bash
|
||||
pip install funasr fastapi uvicorn python-multipart
|
||||
python server.py --model sensevoice --device cuda --port 8000
|
||||
```
|
||||
|
||||
For a portable CPU check, use `--device cpu`. For Docker Compose or Kubernetes, keep the service private and expose it locally with the documented port mapping or `kubectl port-forward`.
|
||||
|
||||
## 2. Install and launch the browser UI
|
||||
|
||||
In another terminal:
|
||||
|
||||
```bash
|
||||
pip install gradio
|
||||
python gradio_app.py --base-url http://localhost:8000
|
||||
```
|
||||
|
||||
Open the printed local URL, upload or record an audio file, choose a model alias, and click **Transcribe**.
|
||||
|
||||
## 3. Verify the backend first
|
||||
|
||||
The UI has a **Check service** button. You can run the same check in a terminal:
|
||||
|
||||
```bash
|
||||
python smoke_test.py --base-url http://localhost:8000
|
||||
curl http://localhost:8000/v1/models
|
||||
```
|
||||
|
||||
If the API server is remote, set the reachable URL explicitly:
|
||||
|
||||
```bash
|
||||
python gradio_app.py --base-url http://funasr-api.speech.svc.cluster.local:8000
|
||||
```
|
||||
|
||||
For OpenAI SDK clients, remember that SDK base URLs include `/v1`; this Gradio demo expects the direct service base URL without `/v1`.
|
||||
|
||||
## Model aliases
|
||||
|
||||
| Alias | Good first use |
|
||||
|---|---|
|
||||
| `sensevoice` | Fast multilingual private transcription and agent voice input. |
|
||||
| `paraformer` | Mandarin-oriented production transcription. |
|
||||
| `paraformer-en` | English-only compatibility checks. |
|
||||
| `fun-asr-nano` | LLM-based ASR and vLLM experiments. |
|
||||
|
||||
See the [model selection guide](../../docs/model_selection.md) for a deeper comparison.
|
||||
|
||||
## Production notes
|
||||
|
||||
- Treat the Gradio app as a demo or internal operator UI, not a public production frontend.
|
||||
- Add authentication, TLS, upload-size limits, and rate limits before exposing any audio upload UI outside a trusted network.
|
||||
- Keep browser uploads close to your backend; do not send private audio to an unauthenticated public endpoint.
|
||||
- Log model alias, audio duration, latency, response format, and error text when debugging.
|
||||
@@ -0,0 +1,62 @@
|
||||
# FunASR OpenAI 兼容 API Gradio 浏览器 Demo
|
||||
|
||||
当 FunASR OpenAI 兼容 API 已经在本地、Docker 或私有 Kubernetes 服务中运行,而你想用浏览器上传或录制音频时,可以使用这个 Gradio demo。
|
||||
|
||||
Gradio app 本身不加载 FunASR 模型。它调用和 smoke test、SDK 配方、Postman 集合、OpenAPI 规范相同的 `/health`、`/v1/models` 和 `/v1/audio/transcriptions` 接口。
|
||||
|
||||
## 1. 启动 API 服务
|
||||
|
||||
在 `examples/openai_api` 目录中执行:
|
||||
|
||||
```bash
|
||||
pip install funasr fastapi uvicorn python-multipart
|
||||
python server.py --model sensevoice --device cuda --port 8000
|
||||
```
|
||||
|
||||
便携 CPU 验证可以使用 `--device cpu`。如果使用 Docker Compose 或 Kubernetes,请保持服务私有,并通过文档中的端口映射或 `kubectl port-forward` 暴露到本机验证。
|
||||
|
||||
## 2. 安装并启动浏览器 UI
|
||||
|
||||
在另一个终端执行:
|
||||
|
||||
```bash
|
||||
pip install gradio
|
||||
python gradio_app.py --base-url http://localhost:8000
|
||||
```
|
||||
|
||||
打开命令行输出的本地 URL,上传或录制音频,选择模型 alias,然后点击 **Transcribe**。
|
||||
|
||||
## 3. 先验证后端服务
|
||||
|
||||
UI 中有 **Check service** 按钮。你也可以在终端运行相同检查:
|
||||
|
||||
```bash
|
||||
python smoke_test.py --base-url http://localhost:8000
|
||||
curl http://localhost:8000/v1/models
|
||||
```
|
||||
|
||||
如果 API 服务在远端,请显式设置可访问的地址:
|
||||
|
||||
```bash
|
||||
python gradio_app.py --base-url http://funasr-api.speech.svc.cluster.local:8000
|
||||
```
|
||||
|
||||
OpenAI SDK 的 base URL 需要包含 `/v1`;这个 Gradio demo 使用的是不带 `/v1` 的直接服务 base URL。
|
||||
|
||||
## 模型别名
|
||||
|
||||
| Alias | 适合场景 |
|
||||
|---|---|
|
||||
| `sensevoice` | 快速多语种私有转写和 Agent 语音输入。 |
|
||||
| `paraformer` | 中文生产转写。 |
|
||||
| `paraformer-en` | 英文兼容性检查。 |
|
||||
| `fun-asr-nano` | LLM-based ASR 和 vLLM 实验。 |
|
||||
|
||||
更完整的对比见 [模型选择指南](../../docs/model_selection_zh.md)。
|
||||
|
||||
## 生产注意事项
|
||||
|
||||
- Gradio app 适合作为 demo 或内部操作界面,不建议直接作为公网生产前端。
|
||||
- 任何音频上传 UI 对可信网络外开放前,都需要先增加鉴权、TLS、上传大小限制和限流。
|
||||
- 浏览器上传应尽量靠近你的后端服务,不要把私有音频发送到未鉴权的公网端点。
|
||||
- 排查问题时记录模型 alias、音频时长、延迟、响应格式和错误文本。
|
||||
@@ -13,7 +13,7 @@ python server.py --model sensevoice --device cuda --port 8000
|
||||
|
||||
Server starts in ~20s (model loading). Health check: `GET /health`
|
||||
|
||||
Need copy-paste integration snippets for Python SDK, JavaScript/TypeScript, HTTP clients, agent tools, Postman, OpenAPI imports, Kubernetes deployment, or Dify/n8n-style workflows? See [Client recipes](CLIENTS.md), [JavaScript/TypeScript recipes](JAVASCRIPT.md), [workflow recipes](WORKFLOWS.md), the [Chinese workflow recipes](WORKFLOWS_zh.md), the [Postman collection](POSTMAN.md), the [OpenAPI spec](OPENAPI.md), and the [Kubernetes deployment template](kubernetes/README.md).
|
||||
Need copy-paste integration snippets for Python SDK, JavaScript/TypeScript, HTTP clients, agent tools, a browser demo, Postman, OpenAPI imports, Kubernetes deployment, or Dify/n8n-style workflows? See [Client recipes](CLIENTS.md), [JavaScript/TypeScript recipes](JAVASCRIPT.md), [Gradio browser demo](GRADIO.md), [workflow recipes](WORKFLOWS.md), the [Chinese workflow recipes](WORKFLOWS_zh.md), the [Postman collection](POSTMAN.md), the [OpenAPI spec](OPENAPI.md), and the [Kubernetes deployment template](kubernetes/README.md).
|
||||
|
||||
### End-to-end smoke test
|
||||
|
||||
@@ -36,6 +36,17 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
-F response_format=verbose_json
|
||||
```
|
||||
|
||||
## Browser demo with Gradio
|
||||
|
||||
If you want a local browser UI for upload or microphone testing, run the API server first and then launch the optional Gradio frontend:
|
||||
|
||||
```bash
|
||||
pip install gradio
|
||||
python gradio_app.py --base-url http://localhost:8000
|
||||
```
|
||||
|
||||
The browser demo calls the same OpenAI-compatible API endpoints as the smoke tests. See [Gradio browser demo](GRADIO.md) for Docker, Kubernetes, and production notes.
|
||||
|
||||
## Usage with OpenAI SDK (Python)
|
||||
|
||||
```python
|
||||
@@ -91,7 +102,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
| `/health` | GET | Health check + loaded models |
|
||||
| `/docs` | GET | Interactive API documentation (Swagger) |
|
||||
|
||||
Prefer no-code API checks? Import the [Postman collection](POSTMAN.md) and run health, model-list, and transcription requests from Postman. For API gateways, developer portals, or client generation, use the [OpenAPI spec](OPENAPI.md).
|
||||
Prefer no-code API checks? Use the [Gradio browser demo](GRADIO.md) for local upload or microphone testing, or import the [Postman collection](POSTMAN.md) and run health, model-list, and transcription requests from Postman. For API gateways, developer portals, or client generation, use the [OpenAPI spec](OPENAPI.md).
|
||||
|
||||
## Agent Framework Integration
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ python server.py --model sensevoice --device cuda --port 8000
|
||||
|
||||
服务通常会在模型加载后启动。健康检查:`GET /health`。
|
||||
|
||||
需要直接复制的接入示例?可以继续查看 [客户端配方](CLIENTS.md)、[JavaScript/TypeScript 配方](JAVASCRIPT_zh.md)、[工作流配方](WORKFLOWS_zh.md)、[Postman 集合](POSTMAN_zh.md)、[OpenAPI 规范](OPENAPI_zh.md) 和 [Kubernetes 部署模板](kubernetes/README_zh.md)。
|
||||
需要直接复制的接入示例?可以继续查看 [客户端配方](CLIENTS.md)、[JavaScript/TypeScript 配方](JAVASCRIPT_zh.md)、[Gradio 浏览器 Demo](GRADIO_zh.md)、[工作流配方](WORKFLOWS_zh.md)、[Postman 集合](POSTMAN_zh.md)、[OpenAPI 规范](OPENAPI_zh.md) 和 [Kubernetes 部署模板](kubernetes/README_zh.md)。
|
||||
|
||||
### 端到端 smoke test
|
||||
|
||||
@@ -36,6 +36,17 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
-F response_format=verbose_json
|
||||
```
|
||||
|
||||
## Gradio 浏览器 Demo
|
||||
|
||||
如果希望用本地浏览器上传音频或测试麦克风,先启动 API 服务,再运行可选 Gradio 前端:
|
||||
|
||||
```bash
|
||||
pip install gradio
|
||||
python gradio_app.py --base-url http://localhost:8000
|
||||
```
|
||||
|
||||
这个浏览器 demo 调用的就是 smoke test 使用的 OpenAI 兼容 API 端点。Docker、Kubernetes 和生产注意事项见 [Gradio 浏览器 Demo](GRADIO_zh.md)。
|
||||
|
||||
## 使用 OpenAI SDK
|
||||
|
||||
```python
|
||||
@@ -88,7 +99,7 @@ curl http://localhost:8000/v1/audio/transcriptions \
|
||||
| `/health` | GET | 健康检查、已加载模型和可用模型 |
|
||||
| `/docs` | GET | FastAPI Swagger 文档 |
|
||||
|
||||
不想写代码验证接口时,可以导入 [Postman 集合](POSTMAN_zh.md)。如果要接入 API 网关、开发者门户或生成内部客户端,可以使用 [OpenAPI 规范](OPENAPI_zh.md)。
|
||||
不想写代码验证接口时,可以使用 [Gradio 浏览器 Demo](GRADIO_zh.md) 做本地上传或麦克风测试,也可以导入 [Postman 集合](POSTMAN_zh.md)。如果要接入 API 网关、开发者门户或生成内部客户端,可以使用 [OpenAPI 规范](OPENAPI_zh.md)。
|
||||
|
||||
## Agent 与低代码工作流
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Browser demo for the FunASR OpenAI-compatible API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
from pathlib import Path
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
import uuid
|
||||
|
||||
DEFAULT_BASE_URL = "http://localhost:8000"
|
||||
DEFAULT_MODEL = "sensevoice"
|
||||
|
||||
|
||||
def request_json(url: str, timeout: float) -> dict:
|
||||
request = urllib.request.Request(url, headers={"Accept": "application/json"})
|
||||
with urllib.request.urlopen(request, timeout=timeout) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
|
||||
|
||||
def multipart_body(audio_path: Path, model: str, response_format: str) -> tuple[bytes, str]:
|
||||
boundary = f"----funasr-gradio-{uuid.uuid4().hex}"
|
||||
content_type = mimetypes.guess_type(str(audio_path))[0] or "application/octet-stream"
|
||||
parts: list[bytes] = []
|
||||
|
||||
def add_text(name: str, value: str) -> None:
|
||||
parts.append(
|
||||
(
|
||||
f"--{boundary}\r\n"
|
||||
f"Content-Disposition: form-data; name=\"{name}\"\r\n\r\n"
|
||||
f"{value}\r\n"
|
||||
).encode("utf-8")
|
||||
)
|
||||
|
||||
parts.append(
|
||||
(
|
||||
f"--{boundary}\r\n"
|
||||
f"Content-Disposition: form-data; name=\"file\"; filename=\"{audio_path.name}\"\r\n"
|
||||
f"Content-Type: {content_type}\r\n\r\n"
|
||||
).encode("utf-8")
|
||||
)
|
||||
parts.append(audio_path.read_bytes())
|
||||
parts.append(b"\r\n")
|
||||
add_text("model", model)
|
||||
add_text("response_format", response_format)
|
||||
parts.append(f"--{boundary}--\r\n".encode("utf-8"))
|
||||
return b"".join(parts), boundary
|
||||
|
||||
|
||||
def transcribe_audio(base_url: str, audio_path: str | None, model: str, response_format: str, timeout: float) -> tuple[str, str]:
|
||||
if not audio_path:
|
||||
return "", "Upload or record an audio file first."
|
||||
|
||||
base_url = base_url.rstrip("/")
|
||||
path = Path(audio_path)
|
||||
body, boundary = multipart_body(path, model, response_format)
|
||||
request = urllib.request.Request(
|
||||
f"{base_url}/v1/audio/transcriptions",
|
||||
data=body,
|
||||
method="POST",
|
||||
headers={
|
||||
"Accept": "application/json",
|
||||
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
||||
"Content-Length": str(len(body)),
|
||||
},
|
||||
)
|
||||
with urllib.request.urlopen(request, timeout=timeout) as response:
|
||||
payload = json.loads(response.read().decode("utf-8"))
|
||||
|
||||
text = payload.get("text", "")
|
||||
return text, json.dumps(payload, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def check_service(base_url: str, timeout: float) -> str:
|
||||
base_url = base_url.rstrip("/")
|
||||
health = request_json(f"{base_url}/health", timeout)
|
||||
models = request_json(f"{base_url}/v1/models", timeout)
|
||||
return json.dumps({"health": health, "models": models}, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def safe_transcribe(base_url: str, audio_path: str | None, model: str, response_format: str, timeout: float) -> tuple[str, str]:
|
||||
try:
|
||||
return transcribe_audio(base_url, audio_path, model, response_format, timeout)
|
||||
except urllib.error.HTTPError as error:
|
||||
detail = error.read().decode("utf-8", errors="replace")
|
||||
return "", f"HTTP {error.code} from {error.url}: {detail}"
|
||||
except Exception as error:
|
||||
return "", f"Transcription failed: {error}"
|
||||
|
||||
|
||||
def safe_check(base_url: str, timeout: float) -> str:
|
||||
try:
|
||||
return check_service(base_url, timeout)
|
||||
except urllib.error.HTTPError as error:
|
||||
detail = error.read().decode("utf-8", errors="replace")
|
||||
return f"HTTP {error.code} from {error.url}: {detail}"
|
||||
except Exception as error:
|
||||
return f"Service check failed: {error}"
|
||||
|
||||
|
||||
def build_app(default_base_url: str, default_timeout: float):
|
||||
try:
|
||||
import gradio as gr
|
||||
except ImportError as error:
|
||||
raise SystemExit("Install Gradio first: pip install gradio") from error
|
||||
|
||||
with gr.Blocks(title="FunASR OpenAI API Demo") as demo:
|
||||
gr.Markdown("# FunASR OpenAI-Compatible API Demo")
|
||||
gr.Markdown("Start `python server.py --model sensevoice --device cuda --port 8000`, then upload or record audio here.")
|
||||
|
||||
with gr.Row():
|
||||
base_url = gr.Textbox(label="API base URL", value=default_base_url)
|
||||
model = gr.Dropdown(
|
||||
label="Model alias",
|
||||
choices=["sensevoice", "paraformer", "paraformer-en", "fun-asr-nano"],
|
||||
value=DEFAULT_MODEL,
|
||||
)
|
||||
response_format = gr.Radio(label="Response format", choices=["json", "verbose_json"], value="verbose_json")
|
||||
timeout = gr.Number(label="Timeout seconds", value=default_timeout, precision=0)
|
||||
|
||||
audio = gr.Audio(label="Audio", sources=["upload", "microphone"], type="filepath")
|
||||
with gr.Row():
|
||||
check_button = gr.Button("Check service")
|
||||
transcribe_button = gr.Button("Transcribe", variant="primary")
|
||||
|
||||
transcript = gr.Textbox(label="Transcript", lines=6)
|
||||
raw_json = gr.Code(label="Raw JSON or status", language="json")
|
||||
|
||||
check_button.click(fn=safe_check, inputs=[base_url, timeout], outputs=raw_json)
|
||||
transcribe_button.click(
|
||||
fn=safe_transcribe,
|
||||
inputs=[base_url, audio, model, response_format, timeout],
|
||||
outputs=[transcript, raw_json],
|
||||
)
|
||||
|
||||
return demo
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="Run a Gradio demo for the FunASR OpenAI-compatible API")
|
||||
parser.add_argument("--base-url", default=os.getenv("BASE_URL", DEFAULT_BASE_URL), help="FunASR API base URL")
|
||||
parser.add_argument("--host", default=os.getenv("GRADIO_HOST", "127.0.0.1"), help="Gradio bind host")
|
||||
parser.add_argument("--port", type=int, default=int(os.getenv("GRADIO_PORT", "7860")), help="Gradio bind port")
|
||||
parser.add_argument("--timeout", type=float, default=float(os.getenv("TIMEOUT", "300")), help="HTTP timeout in seconds")
|
||||
parser.add_argument("--share", action="store_true", help="Create a temporary Gradio share link")
|
||||
args = parser.parse_args()
|
||||
|
||||
app = build_app(args.base_url, args.timeout)
|
||||
app.launch(server_name=args.host, server_port=args.port, share=args.share)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user