ling-playground / docs /requirements /2025-10-11-21-09-implement-dynamic-gradio-app-generation.md
cafe3310's picture
little demo
cb6eafc
# 需求:实现 Gradio 应用的动态生成与预览
- **需求描述:**
在“代码生成”功能区,当用户选择“Gradio 应用”类型时,系统应能接收用户的自然语言需求,调用 AI 模型生成完整的、可运行的 Gradio 应用代码,并在预览区实时展示该应用。
- **实现方案:**
我们将借鉴 `anycoder` 项目的“代码提取 -> 外部执行 -> 界面嵌入”的成熟方案,以确保功能的安全性和稳定性。
1. **System Prompt 设计:**
- 创建一个专门的 `get_gradio_sys_prompt` 函数,用于生成指导模型输出完整、可运行的单文件 Gradio 应用的 System Prompt。
- **强制要求:**
- 模型生成的代码必须是自包含的。
- Gradio 应用实例必须赋值给一个固定的变量名 `demo`
- 脚本必须以 `demo.launch()` 结尾。
- 输出应仅包含 ```python ... ``` 代码块,无额外解释。
2. **后端核心逻辑 (位于 `tab_code.py` 的 `generate_code` 函数中):**
- **子进程管理:**
- 使用一个全局变量 `gradio_process` 来跟踪当前运行的 Gradio 子进程。
- 在生成新应用前,通过 `gradio_process.terminate()``gradio_process.join()` 检查并终止任何已存在的旧进程,以释放端口和资源。
- **动态端口分配:**
-`utils.py` 中实现一个 `find_free_port` 函数,该函数通过 `socket` 库绑定一个临时端口来动态查找一个当前未被占用的 TCP 端口。
- **代码生成与执行:**
- 从模型返回的流式响应中,实时累积代码,并使用正则表达式 `re.search(r"```python\n(.*?)```", full_code, re.DOTALL)` 提取代码块。
- 如果未找到代码块,则将整个输出作为代码。
- **安全检查:** 在执行前,使用 `compile(python_code, '<string>', 'exec')` 验证代码的语法正确性。
- 将提取的有效代码写入一个临时 Python 文件。
- 使用 `subprocess.Popen` 在一个隔离的子进程中执行该临时文件,并通过环境变量传递动态分配的端口号。
- **前端预览:**
- 子进程成功启动后,等待一个固定的时间(例如10秒)以确保 Gradio 服务完全启动。
- 后端 `yield` 一个包含 `<iframe>` 的 HTML 字符串给前端。
- `<iframe>``src` 属性将指向 `http://127.0.0.1:<动态分配的端口号>`,从而将子进程中运行的应用无缝嵌入到主应用的预览区域。
- **错误处理:**
- 如果代码编译失败,向前端返回详细的错误信息。
- **创建时间:** 2025-10-11-21-09
- **状态:** `已完成 (Done)`
- **重要性:** 中等 (Medium)
- **验证方式:**
1. 启动应用,进入“代码生成”标签页。
2. 选择“Gradio 应用”类型。
3. 输入“创建一个简单的 Gradio 应用,包含一个输入框和一个输出框”,点击“生成代码”。
4. 观察状态显示区域和预览区域。
5. 等待生成完成。
- **验证结果:**
- 成功生成了一个简单的 Gradio 应用,该应用回显用户输入。
- 在“生成的源代码”标签页中,确认了生成的代码是一个简单的回显应用。
- 在“实时预览”标签页中,对应用进行了测试,输入 "Hello, World!",得到了正确的输出 "Hello, World!"。
- 确认了该功能确实对接了 LLM 并能生成有效的、功能性的 Gradio 应用。
- 功能符合预期。