File size: 15,953 Bytes
a9fb7e9
 
 
 
 
 
cb6eafc
 
 
a9fb7e9
 
 
cb6eafc
 
 
a9fb7e9
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
 
 
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
 
 
 
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
 
 
 
a9fb7e9
cb6eafc
 
 
 
 
 
 
a9fb7e9
cb6eafc
 
 
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
 
 
 
 
a9fb7e9
cb6eafc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a9fb7e9
cb6eafc
 
 
 
 
 
 
 
 
 
 
 
 
 
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
 
 
 
 
a9fb7e9
cb6eafc
 
 
a9fb7e9
 
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
cb6eafc
 
a9fb7e9
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
 
 
cb6eafc
a9fb7e9
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# Ling & Ring Playground - 项目与协作文档

> **[重要] 上下文说明:** 本文档定义了 **Ling & Ring Playground** 项目的具体设计和流程。我们的整体协作模式、沟通风格、以及通用的文档和目录规范,均遵循一套**全局 `GEMINI.md` 核心协作指令**。阅读本文档前,建议先了解该全局框架,以获得完整的上下文。

---

## 第一部分:元信息

本文档遵循全局 `GEMINI.md` 的元信息结构,旨在作为项目唯一的“事实来源”。它定义了项目的目标、规范、设计和待办事项,并由我和我的用户共同维护。

---

## 第二部分:协作流程和规范

### 2.1 运行与部署流程

#### 本地运行

要启动此 Gradio 应用,请遵循以下步骤:

1.  **安装依赖:** 确保所有必要的库都已安装。
    ```bash
    uv pip install -r requirements.txt
    ```
    *注意: 如果遇到与 SOCKS 代理相关的 `ImportError`,请额外运行 `uv pip install "httpx[socks]"`。*

2.  **启动应用:** 在后台静默运行应用。
    ```bash
    source .venv/bin/activate && python3 app.py > /dev/null 2>&1 &
    ```

3.  **验证:** 在浏览器中打开 `http://127.0.0.1:7860` 以确认应用正在运行。

#### 部署到 Hugging Face Spaces

本项目可以轻松部署到 Hugging Face Spaces。推送代码到 Git 仓库后,Hugging Face 会自动构建并运行应用。应用地址是 `https://huggingface.co/spaces/inclusion/ling-playground`### 2.2 自动化测试流程

**核心方法:以需求文档为准的 Agent 驱动测试**

本项目的测试开发(TDD/BDD)由我,即 Agent,作为测试执行器来驱动。具体方法如下:

1.  **测试用例即需求:** 每个需求文档(`docs/requirements/*.md`)中的“验证方式”或“测试用例”部分,就是一份用自然语言描述的端到端测试脚本。
2.  **我来执行测试:** 我会严格按照“验证方式”中的步骤,通过调用我的浏览器自动化工具集(`navigate_page`, `click`, `fill`, `take_snapshot` 等)来模拟用户操作。
3.  **我来断言结果:** 在执行操作后,我会捕获 UI 快照,并在我的思考流程中,通过分析快照内容来判断实际结果是否与预期相符。

这种“以需求文档为准,Agent 驱动执行”的模式,是我在本项目中实践 TDD 的具体方式。

**具体工具流程:**

当需要验证应用核心功能时,我将遵循以下自动化流程:

1.  **启动应用:** 使用 `run_shell_command` 在后台启动 Gradio 应用。
2.  **导航与验证:** 使用 `navigate_page` 打开应用 URL (`http://127.0.0.1:7860`),并使用 `take_snapshot` 截取页面快照,以编程方式验证 UI 是否正确加载。**(重要规范:必须使用浏览器自动化工具进行验证,禁止使用 `web_fetch` 等非浏览器工具检查应用状态。)**
3.  **交互操作:** 使用 `fill` 和 `click` 等工具模拟用户操作,例如在聊天框中输入文本并点击发送。
4.  **结果断言:** 再次使用 `take_snapshot` 捕获操作后的界面状态,并检查其内容是否符合预期(例如,聊天记录中是否出现了模型的回复)。

此流程确保了关键用户路径的可靠性。

#### 代码生成功能测试示例

对于像代码生成这样涉及流式输出的动态界面,必须采用更严谨的测试方法来确保可靠性。

1.  **严格的“操作 -> 快照”模式:** 为避免“陈旧快照 (stale snapshot)”错误,**每次**交互操作(如 `click`, `fill`)后都**必须**立即调用 `take_snapshot` 来获取最新的 UI 状态和元素 `uid`2.  **输入与启动:**
    -   执行“环境重置流程”。
    -   导航至应用,获取初始快照,点击“代码生成”标签页。
    -   获取新快照,定位到输入框并填入需求,再定位到“生成代码”按钮并点击。

3.  **监控生成过程:**
    -   点击“生成代码”后,立即获取新快照,并点击切换到“生成的源代码”标签页。
    -   进入一个监控循环,以编程方式判断生成是否结束:
        -   获取一次快照,记录下源代码区域的内容。
        -   等待一个固定的时间间隔(例如 5 秒)。
        -   再次获取快照,获取新的源代码内容。
        -   **比较两次获取的内容。如果内容完全相同,则判定代码已停止生成,跳出循环。** 否则,继续循环。

4.  **验证预览:**
    -   跳出循环后,获取最终快照,点击“实时预览”标签页。
    -   最后,请求人工介入,以视觉方式确认最终渲染效果是否符合预期。

这个流程通过精确的状态管理和内容比较,实现了对动态生成过程的可靠自动化测试。

### 2.3 异常处理与重置流程

当自动化流程遇到问题或需要一个干净的环境时,我将执行以下标准的“重置”程序:

1.  **清理浏览器:** 将所有打开的浏览器页面导航至 `about:blank`2.  **终止服务:** 使用 `ps aux | grep app.py` 查找并使用 `kill` 命令终止所有正在运行的 `app.py` 应用进程。
3.  **重启服务:** 在确认环境干净后,重新在后台启动应用。
4.  **等待加载:** 等待 5 秒,以确保服务完全初始化。
5.  **重新访问:** 导航到应用 URL (`http://127.0.0.1:7860`) 并进行验证。

此流程是所有自动化测试和问题排查的起点。

### 2.4 分支与提交规范 (主干工作流)

为确保开发过程的敏捷、可靠与透明,我将遵循一套以需求为驱动、以 Git 为记录的自动化主干工作流。此流程将我的角色从被动执行者转变为能够主动推进项目迭代的合作伙伴。

**核心原则:用户指令优先**
在任何时候,您的直接指令都拥有最高优先级,可以中断或覆盖此自动化流程。

**工作流详解:**

**1. 智能调度与规划**
   - **领取任务:** 我将自动扫描 `docs/backlog/`,并根据**重要性 (Priority)** 字段来确定任务的执行顺序。
     - **重要性等级:** 需求文档中应包含一个 `重要性` 字段,其值可以是 `高 (High)``中 (Medium)``低 (Low)`     - **调度逻辑:** 我会优先处理 `高` 重要性的任务,然后是 `中` 等重要性,最后是 `低` 重要性。在同一重要性等级内,我将按时间顺序选取最旧的需求。如果一个需求没有明确的重要性,它将被当作 `中` 等处理。
   - **需求澄清:** 在正式开始前,我会分析需求文档。如果发现任何模糊、歧义或信息不足之处,我将**暂停工作流并主动向您提问**   - **TDD - 定义成功:** 我会为需求定义清晰的验收标准,并尽可能**优先编写自动化测试用例**。这是我后续开发和验证的“靶子”。如果需求文档中缺少“验证方式”,我将暂停并请求用户提供,绝不跳过验证环节。
   - **文档迁移:** 我会将需求文档从 `docs/backlog/` 移动到 `docs/requirements/`,并更新其状态为 `开发中`   - **`COMMIT` 1 (分析完成):** `git commit -m "docs(req): 完成需求 {文件名} 的分析与测试用例,即将开发"`

**2. 开发执行**
   - 我将根据需求文档和预先定义的测试用例,进行编码实现。
   - **`COMMIT` 2 (开发完成):** `git commit -m "feat(scope): 完成需求 {文件名} 的开发,即将验证"`

**3. 验证与修复循环 (带熔断机制)**
   - 我将自动运行在规划阶段编写的测试用例来验证我的代码。
   - **a. 如果验证成功:**
     - **`COMMIT` 5 (需求完成):** `git commit -m "docs(req): 需求 {文件名} 的开发和验证已经全部完成!"`
     - 我会向您报告此需求已圆满完成,并自动返回**步骤 1**,开始下一个需求的循环。
   - **b. 如果验证失败 (第 N 次尝试):**
     - **`COMMIT` 3 (发现问题):** `git commit -m "docs(req): 验证需求 {文件名} 时遇到问题 {问题描述} (第 N 次尝试),即将修复"`
     - **熔断机制:** 如果对同一个问题的修复尝试超过 **3 次**,我将触发熔断:
       1.  自动回滚所有失败的修复尝试。
       2.  将需求文档状态标记为 `Blocked`       3.  **主动向您报告,清晰阐述我遇到的问题、已尝试的方案及失败原因,请求您的指导。**
     - **修复执行:** 我将进入“调试流程”,分析日志,定位并修复问题。
     - **`COMMIT` 4 (修复完成):** `git commit -m "fix(scope): 验证需求 {文件名} ,成功解决了问题 {问题描述} (第 N 次尝试)"`
     - 修复后,我将自动返回**步骤 3a**,重新运行完整的自动化验证。

**日志分析:**

- When debugging, I must redirect application output to a log file (e.g., app.log) and then read that file to diagnose issues.

---

## 第三部分:项目整体设计

### 3.1 项目目标

创建一个名为 “Ling & Ring Playground” 的 Hugging Face Space,用于演示 Ling / Ring 系列模型能力。

### 3.2 核心设计原则

- **任务导向:** UI 围绕用户任务(聊天、编码等)组织,而非直接暴露模型。
- **品牌明晰:** 在每个功能界面清晰标注“由 Ling/Ring 模型驱动”。
- **无缝体验:** 用户无需手动输入 API Token,认证在后端自动完成。
- **引导优先:** 提供精心设计的示例,确保用户获得高质量的初次体验。

### 3.3 技术栈与架构

- **前端/UI:** Gradio `gr.Blocks`
- **后端:** Python
- **安全:** 所有 API 密钥通过 Hugging Face Space Secrets 管理。

#### 3.3.1 配置加载策略

为兼顾本地开发的便利性、线上部署的安全性与成本效益,项目采用了一种分层配置加载机制:

1.  **本地优先 (`local.py`):** 在项目根目录下,可以创建一个 `local.py` 文件来存放本地开发所需的配置,例如使用内部免费 Provider 的 API Key 和 Endpoint。此文件**必须**`.gitignore` 忽略,以防止任何敏感信息被提交到版本控制中。
2.  **环境变量回退:**`local.py` 文件不存在时(例如在 Hugging Face Spaces 的生产环境中),系统将自动回退,尝试从环境变量中读取所需的配置。这种方式使得 API Key 等敏感信息可以通过平台安全地注入,而无需硬编码在代码中。
3.  **模型 ID 本地映射:** 为了方便本地开发和调试,系统还支持通过在 `local.py` 文件中定义一个 `get_local_model_id_map` 函数,来实现从在线模型 ID 到本地模型 ID 的映射。这允许开发者在不修改核心代码库的情况下,将模型请求指向本地运行的服务或不同的模型版本。

此策略确保了开发者在本地可以快速迭代,而线上部署则遵循了安全最佳实践。

### 3.4 项目结构

```
/
├───.gitignore
├───app.py              # 应用主入口
├───config.py           # 配置文件,用于存放 API 密钥等
├───GEMINI.md           # 项目与协作文档(唯一事实来源)
├───models.py           # 模型交互逻辑
├───requirements.txt    # Python 依赖
├───tab_chat.py         # “聊天”功能模块
├───tab_code.py         # “代码生成”功能模块
├───tab_search.py       # “网页检索”功能模块
├───tab_workflow.py     # “工作流”功能模块
├───utils.py            # 通用工具函数
└───docs/
    ├───backlog/        # 待办需求池
    ├───requirements/   # 需求文档(Git 跟踪)
    └───refs/           # 本地参考资料(Git 忽略)
```

### 3.5 代码架构

1.  **`models.py`**: 存放所有与模型对接和交互的逻辑。
2.  **`app.py`**: 作为应用的统一入口,仅保留最精简的组装和启动逻辑。
3.  **`tab_*.py`**: 每个标签页(如 `tab_chat.py`)独立一个文件,负责构建该标签页的UI和处理其特定的后端逻辑。
4.  **`app.py` 调用**: 主入口 `app.py` 通过调用各个 `tab_*.py` 中的函数来创建和组装完整的应用界面。
5.  **`utils.py`**: 存放可被多处复用的纯静态方法、常量或辅助函数。

---

## 第四部分:项目详细设计

应用为一个包含页头和四个核心[GEMINI.md](../../.gemini/GEMINI.md)功能标签页的单页应用。

### 4.1 Tab 1: 聊天 (Chat) - `tab_chat.py`

- **目标:** 提供一个与 Ling 模型进行高质量对话的界面。
- **UI 布局:**
    - **左侧面板:** `gr.Chatbot` (对话历史), `gr.Textbox` (输入框) 与 `gr.Button` ("发送") 在同一行, `gr.Examples` (示例)。
    - **右侧面板:** `gr.Textbox` (System Prompt), `gr.Slider` (温度), `gr.Dropdown` (模型选择)。
- **用户用例:**
    1. 用户在输入框中输入问题,按回车提交。
    2. Ling 模型的响应以流式方式出现在聊天历史中,且每条回复的开头都会以 `**<模型名称>**` 的形式清晰地标识出当前是哪个模型在回答。
    3. 在模型输出期间,用户可点击“终止输出”按钮来随时中断回复。
    4. 用户可继续多轮对话,或通过右侧面板调整模型行为。

### 4.2 Tab 2: 代码生成 (Code Generation) - `tab_code.py`

- **目标:** 利用 Ring 模型,根据用户需求生成代码,并提供实时预览。
- **UI 布局:**
    - **左侧面板:** `gr.Radio` (代码类型), `gr.Radio` (模型选择), `gr.Textbox` (需求输入), `gr.Examples` (预设选项), `gr.Button` (生成)。
    - **右侧面板:** `gr.Tabs`
        - **Tab 1: "实时预览"**: `gr.Button` (全屏预览), `gr.HTML` (`<iframe>` 预览容器)。
        - **Tab 2: "生成的源代码"**: `gr.Code` (源代码显示)。
- **用户用例:**
    1. 用户选择代码类型(“静态页面”或“Gradio 应用”)。当选择“静态页面”时,功能由 `Ling-1T` 模型驱动。
    2. 用户输入需求(例如:“创建一个带标题和按钮的页面”)。
    3. 点击“生成代码”后,`tab_code.py` 中的 `generate_code` 函数会作为一个生成器工作。
    4. 它会迭代调用模型返回的流式数据,在每次 `yield` 时同时更新下方的源代码区域(累积的代码)和右侧的预览区域。
    5. 预览区域的 `<iframe>` 默认以**缩放模式**显示,以便用户看到整体效果。
    6. 用户可以点击“全屏预览”按钮,此时输入和代码区域会隐藏,预览区将放大以提供更沉浸的体验。再次点击可恢复。
    7. 对于 Gradio 应用,后端会启动一个独立的子进程来运行代码,并将应用界面嵌入到预览区。

### 4.3 Tab 3: 网页检索 (Web Search) - `tab_search.py`

- **目标:** 利用 Ring 模型的检索能力,提供精准的网页信息摘要。
- **UI 布局:** 单栏居中布局,包含 `gr.Textbox` (输入), `gr.Button` (搜索), `gr.Markdown` (结果)。
- **用户用例:**
    1. 用户输入问题(例如:“什么是 Transformer 架构?”)。
    2. 点击“搜索”后,Ring 模型返回的摘要和来源链接会显示在结果区。

### 4.4 Tab 4: 工作流执行 (Workflow Execution) - `tab_workflow.py`

- **目标:** 展示 Ring 模型作为 Agent 执行复杂工作流的能力。
- **UI 布局:**
    - **左侧面板:** `gr.Textbox` (工作流描述), `gr.Button` (执行), `gr.Markdown` (工作流可视化)。
    - **右侧面板:** `gr.Textbox` (状态日志), `gr.Chatbot` (人机交互)。
- **用户用例:**
    1. 用户输入任务描述(例如:“查找最新的 Llama 3 模型并总结其模型卡片”)。
    2. Ring 模型生成执行计划并可视化,然后开始执行。
    3. 右侧面板实时显示执行日志,并在需要时通过聊天机器人向用户请求决策。