# SemIf 中文版 · 实现说明

本站是 [openjev.com](https://openjev.com/)（SemIf，原名 OpenJev）页面的中文翻译克隆，用于本地研究与演示。
推理完全在访问者的浏览器里进行，没有后端：页面通过 [wllama](https://github.com/ngxson/wllama) 在 WebGPU 上加载 GGUF 量化权重。

## 两种决策路径

同一个模型、同一个提示词前缀，分别用两种方式得到"各选项的概率"：

1. **直接读取（02A）** — 一次前向计算，用 grammar 把输出限制为选项字母，并用 `logit_bias` 把候选字母的 logit 抬到可读位置，然后只在这些选项上做 softmax。不解码、不生成文本。
2. **生成（02B）** — 让模型把同一组选项的概率写成 JSON，逐 token 流式输出，再解析并校验（键集合、取值范围、和是否为 1）。

两者的耗时都用 `performance.now()` 在同一标签页内顺序测量，先直接读取后生成，避免争抢 GPU。

## 相对原站做了哪些改动

| 项目 | 原站 | 本站 |
| --- | --- | --- |
| 界面语言 | 英文 | 中文（提示词保持英文，见下） |
| Vue 运行时 | `cdn.jsdelivr.net` | 本地 `vendor/vue/` |
| 图标字体 | `fonts.googleapis.com` | 本地 `vendor/fonts/`（仅含 13 个用到的图标的 3 KB 子集） |
| 模型权重 | `huggingface.co` | `hf-mirror.com` 镜像（HF 原站在国内浏览器上不可达） |
| 中文排版 | — | 字体栈补充 `PingFang SC` / `Microsoft YaHei` 等回退 |
| 决策示例 | 2 个（账号支持、邮件分类） | 7 个（新增：工单定级、请求路由、工具放行、评论审核、意图识别） |
| 静态文件缓存 | 无 Cache-Control | `app.js`/`worker.js`/`style.css` 不缓存（发版立即生效），`vendor/` 长期缓存 |

**为什么提示词不翻译**：`worker.js` 里发给模型的 system/user 提示词保持英文原文，因为英文指令下小模型的格式跟随更稳定，也便于与原站给出的数字对照。界面上展示的示例文本（状态、问题、选项）已本地化为中文。

## 目录结构

```
site/
  index.html                  页面结构与全部文案
  style.css                   原站样式（末尾追加了中文字体回退）
  app.js                      UI 逻辑：模型选择、进度、结果渲染
  worker.js                   Web Worker：加载模型、两种决策路径
  vendor/vue/                 Vue 3.5.21 ESM 构建
  vendor/fonts/               Material Symbols Rounded 图标子集
  vendor/wllama/              wllama 运行时 + wllama.wasm（8.4 MB）
```

模型权重不会部署到服务器：访问者点击"加载"时才从镜像下载，并缓存在自己的浏览器缓存里。

## 注意

- 页面通过 nginx 设置了 `Cross-Origin-Embedder-Policy: require-corp` 与 `Cross-Origin-Opener-Policy: same-origin`，这是 wllama 多线程 WASM 需要的跨源隔离；因此所有第三方资源都必须自带 CORP 头或同源 —— 所以本页把外部依赖都本地化了。
- 浏览器端量化、`logit_bias` 与 grammar 约束都会影响结果，页面上的数字不代表模型的原生准确率。
