# 第二步：统一网页打标

## 一、第二步要达到什么

第二步在第一步命令行跑通的基础上，做一个**统一点选式网页**。

页面让学生可以：

1. **点击**选择打标方式（分类 / 抽取 / 匹配）
2. **点击**选择数据来源（示例数据 / 自己输入）
3. **点击**选择难度（简单 / 中等 / 困难）
4. **点击**选择一条示例，自动填入待打标内容
5. **点击**「开始打标」，调用后端
6. **左右对比**查看提示词与模型返回结果

第一步的命令行能力不变；第二步只是把同一套逻辑做成更好用的交互界面。

```text
前端点选数据
后端读取提示词
后端调用大模型
模型返回结果
前端左右对比展示
```

## 二、页面设计原则

| 原则 | 说明 |
| --- | --- |
| 默认点选，少打字 | 默认「使用示例数据」，学生点难度、点卡片即可 |
| 对比要明显 | 左栏提示词（蓝灰底）、右栏模型结果（绿灰底），标题和边框颜色区分 |
| 一步完成打标 | 选好示例后，点一次「开始打标」即可 |
| 保留自由输入 | 进阶学生可切换到「自己输入」模式 |

## 三、统一页面布局

页面只有一个主界面，从上到下分 4 个区域：

### 区域 1：任务选择（卡片式，点击切换）

- 金融文本分类
- 金融信息抽取
- 金融文本匹配

### 区域 2：数据来源（切换按钮）

| 模式 | 交互 |
| --- | --- |
| 使用示例数据（默认） | 显示难度按钮 + 示例卡片列表，点击卡片即选中 |
| 自己输入 | 显示文本框，供自由输入 |

### 区域 3：待打标内容预览

选中示例或输入文本后，在显眼位置展示当前待打标内容，避免学生搞不清正在测哪条数据。

### 区域 4：左右对比区

| 左栏 | 右栏 |
| --- | --- |
| 当前提示词（只读展示） | 模型返回结果（格式化 JSON） |
| 蓝色系标题和边框 | 绿色系标题和边框 |

底部居中放一个大按钮：**开始打标**。

## 四、示例数据交互（重点）

### 难度选择

每个任务在 `data/` 中已准备 3 条数据：

- `easy`：简单，适合验证流程
- `medium`：中等，适合测试提示词
- `hard`：困难，适合观察边界情况

页面上用三个按钮切换难度，只显示当前难度下的示例卡片。

### 示例卡片

每张卡片显示：

- 样本 ID
- 文本摘要（匹配任务显示 A / B 两段摘要）
- 难度标签

点击卡片即选中，卡片高亮，并自动更新「待打标内容预览」。

**不需要学生手动输入任何内容。**

### 生成测试数据（新增）

在「使用示例数据」模式下，难度按钮旁增加：

```text
生成当前难度测试数据
```

点击后调用 `POST /generate-sample`，由大模型生成 1 条带标准答案的新样本，并自动加入当前列表顶部。

难度设计必须能真正区分：

| 难度 | 生成要求 |
| --- | --- |
| 简单 | 意图明显，标准答案一眼可验证 |
| 中等 | 多个信息点，需要读完整句 |
| 困难 | 多重歧义/指代/条件嵌套；**程序校验**拒绝过短、过简单的样本 |

困难样本具体标准（生成器会自动校验，不合格则重试）：

| 任务 | 困难样本必须满足 |
| --- | --- |
| 分类 | ≥60 字；含转折（但/然而/同时）；至少 2 类表面信号词 |
| 抽取 | ≥80 字；≥5 个字段非空；主体用指代；含条件推测（若/可能） |
| 匹配 | 每段 ≥45 字；高度相关但难判断（如回购 vs 减持） |

生成的样本带 `AI生成` 标记，可立即用于打标和对比。

生成过程状态（按钮旁状态芯片）：

| 状态 | 含义 |
| --- | --- |
| 待生成 | 初始状态，可点击生成 |
| 生成中... | 正在调用大模型，按钮禁用 |
| 已生成 | 成功，新样本已加入列表顶部 |
| 生成失败 | 失败，提示区会显示具体原因 |

### 生成测试数据常见问题

| 现象 | 原因 | 解决办法 |
| --- | --- | --- |
| 点击后完全没反应 | 前端 JS 报错（如 `app.js` 语法错误） | 浏览器 F12 看 Console；Ctrl+F5 强制刷新 |
| 一直显示「生成中...」 | 大模型 API 慢或未返回 | 等待 90s；检查 `DASHSCOPE_API_KEY` 和网络 |
| 状态变为「生成失败」 | API Key 未设置、JSON 校验失败等 | 看提示区错误详情；检查 `config.yaml` 中 `generator` 段 |
| 后端报 `No module named 'backend'` | 用 PyCharm 打开 `financial-labeling-project`；或运行 `run_web.py` / `label.py` |

`config.yaml` 中可调整生成超时与重试：

```yaml
generator:
  model: qwen-plus
  temperature: 0.85
  timeout_seconds: 90
  max_retries: 3
  hard_temperature: 0.95      # 困难样本更高随机性
  hard_max_retries: 5         # 困难样本更多重试
  hard_timeout_seconds: 120
```

## 五、自己输入模式（可选）

切换到「自己输入」后：

- 分类 / 抽取：显示一个文本框
- 匹配：显示文本 A、文本 B 两个文本框

此模式供学生测试自定义句子，课堂默认不强制使用。

## 六、配置与后端共用

网页后端与命令行**共用同一套配置和业务代码**：

```text
config.yaml          → backend/config.py 读取
backend/label_service.py  → 打标逻辑
backend/llm_client.py     → 模型调用（参数来自 config.yaml）
```

改模型名、temperature 时，只改 `config.yaml`，命令行和网页同时生效。

### 启动网页

**PyCharm 推荐**：右上角选 **Run Web**，或右键 `run_web.py` → Run。

命令行 / README 一键运行：

```bash
python run_web.py
```

`bootstrap.py` 会自动切换工作目录，通常不需要再 `cd financial-labeling-project`。

网页返回结果也应**精简展示**：右栏默认只显示 `result` 核心字段，不把 `raw_output` 重复堆给学生看；解析失败时才显示错误和原始返回。

## 七、后端接口设计

### 主要接口

```text
POST /label
```

请求体示例（分类）：

```json
{
  "task": "classify",
  "text": "某上市公司发布公告称，预计上半年净利润同比增长 40%。"
}
```

### 辅助接口

```text
GET /prompt/{task}
```

作用：切换任务时，左栏展示对应提示词。

```text
GET /samples/{task}?difficulty=easy
```

作用：获取示例数据列表；`difficulty` 可选 `easy`、`medium`、`hard`，不传则返回全部。

## 八、讲师演示顺序

1. 打开网页，默认选「金融文本分类」
2. 保持「使用示例数据」，点「简单」难度
3. 点第一条示例卡片，展示待打标内容
4. 点「开始打标」，看左右对比结果
5. 不改数据，切换到「困难」难度，再打一标，对比结果差异
6. 打开 `prompts/classify.txt`，删掉「只能从给定类别中选择」
7. 回到网页，对同一条数据重新打标，观察右栏变化
8. 切换到「金融信息抽取」，演示 7 个中文字段（主体机构、财务指标等）如何被约束
9. 切换到「金融文本匹配」，强调判断标准写法的影响

这样学生能直观看到：**同一数据 + 不同提示词 = 不同结果**。

## 九、给 AI 编程工具的生成计划（可直接复制）

```text
请帮我开发一个「金融文本统一网页打标」项目，要求标准 Python 结构、配置可控、页面美观、默认点选操作。

一、项目目标
做一个统一网页，学生可以点选三种金融文本打标方式：
1. 金融文本分类
2. 金融文本信息抽取
3. 金融文本匹配

二、项目结构
financial-labeling-project/
  config.yaml
  label.py
  backend/（config.py、llm_client.py、label_service.py、cli_output.py、main.py）
  prompts/、data/、outputs/、frontend/

三、技术要求
1. config.yaml 统一管理 model、temperature、base_url、paths、cli 输出模式
2. API Key 从环境变量 DASHSCOPE_API_KEY 读取
3. 命令行与网页共用 label_service.py
4. 命令行默认 summary 输出，网页右栏只展示 result 核心字段

四、前端页面要求
1. 卡片切换任务；默认示例数据 + 难度按钮 + 可点击卡片
2. 左右分栏：蓝=提示词，绿=结果
3. 支持自己输入模式

五、后端接口
POST /label、GET /prompt/{task}、GET /samples/{task}

请生成完整可运行代码。
```

## 十、验收标准

- 学生不输入任何文字，只靠点击就能完成一次打标
- 左栏提示词、右栏结果一眼能区分
- 切换难度后，待打标内容跟着变化
- 修改 `prompts/` 后刷新网页，再打同一示例，结果有明显变化
