104 lines
4.7 KiB
Markdown
104 lines
4.7 KiB
Markdown
# FengAI ✦
|
||
|
||
一个简洁、好看的 OpenAI 兼容大模型对话桌面应用(Electron)。支持流式输出、思考过程、Markdown 渲染、思考强度(reasoning_effort)、Token 统计、供应商/模型配置、本地历史会话管理,可打包为 Windows exe 安装包。
|
||
|
||
## 功能
|
||
|
||
- **OpenAI 兼容协议**,API 地址自动拼接 `/chat/completions`
|
||
- **流式输出**,节流增量渲染,**支持中断**;超长输出自动降级,不卡顿、不截断
|
||
- **思考强度**:顶栏分段控制 `关闭 / 增强(high) / 深度(max)`,对应 `thinking` + `reasoning_effort`
|
||
- **Token 统计**:每条助手消息显示「输入 · 思考 · 输出 · 合计」,输入框下方显示本会话累计
|
||
- **分离展示「思考过程」与「回答」**,思考区可折叠、可独立滚动
|
||
- **Markdown 渲染**(marked + DOMPurify 消毒)
|
||
- **上下文条数控制**(默认保留最近 6 条,可调)
|
||
- **最大输出 tokens** 可配置(留空=不限制;GLM-5.2 可填 `131072`)
|
||
- **系统提示词**、深度思考开关
|
||
- **历史会话本地保存**,左侧列表 + 右侧对话,自动命名
|
||
- **智能滚动** + 「回到底部」按钮
|
||
- **消息操作**:复制、重新生成
|
||
- **会话管理**:删除单条、清空当前、清空全部、双击重命名
|
||
- **明/暗双主题**切换(持久化),渐变品牌风格
|
||
- 自定义渐变图标(青-靛「风」字形)
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
fengai/
|
||
├── package.json
|
||
├── .npmrc # 国内镜像
|
||
├── build/icon.ico # 应用图标(由脚本生成)
|
||
├── scripts/make-icon.js # 图标生成脚本(纯 Node,无外部依赖)
|
||
├── src/
|
||
│ ├── main/
|
||
│ │ ├── main.js # 主进程(窗口/IPC)
|
||
│ │ ├── preload.js # 预加载(安全暴露 API)
|
||
│ │ ├── store.js # 本地存储(供应商/会话 JSON)
|
||
│ │ └── api.js # 流式请求与 SSE 解析(含 usage 提取)
|
||
│ └── renderer/
|
||
│ ├── index.html
|
||
│ ├── styles.css
|
||
│ ├── app.js # 渲染层逻辑
|
||
│ └── vendor/ # marked + dompurify(本地副本,符合 CSP)
|
||
```
|
||
|
||
## 开发运行
|
||
|
||
```bash
|
||
npm install
|
||
npm start # 运行
|
||
npm run dev # 调试模式(打开 DevTools)
|
||
npm run icon # 重新生成 build/icon.ico
|
||
```
|
||
|
||
## 打包为 exe 安装包
|
||
|
||
```bash
|
||
npm run build # 生成 dist/FengAI-Setup-1.0.0.exe(NSIS 安装程序)
|
||
npm run pack # 仅生成免安装目录版本 dist/win-unpacked/
|
||
```
|
||
|
||
## 配置示例(GLM-5.2)
|
||
|
||
打开应用后点「⚙ 供应商与模型」:
|
||
|
||
| 字段 | 示例值 |
|
||
| --- | --- |
|
||
| 供应商名称 | GLM5.1 |
|
||
| API 地址 | `https://ark.cn-beijing.volces.com/api/coding/v3` |
|
||
| 密钥 | `sk-...` |
|
||
| 模型列表 | `glm-5.2`, `kimi-k2.6`, `deepseek-v4-pro`, ... |
|
||
| 最大输出 tokens | `131072` |
|
||
|
||
请求体(深度思考 + 128K 输出):
|
||
```json
|
||
{ "model": "glm-5.2", "stream": true,
|
||
"thinking": {"type":"enabled"}, "reasoning_effort": "max",
|
||
"max_tokens": 131072, "messages": [...] }
|
||
```
|
||
|
||
流式响应正确处理 `delta.reasoning_content` 与 `delta.content`,并解析末尾 `usage`(含 `completion_tokens_details.reasoning_tokens`)用于 Token 统计。
|
||
|
||
## 流式稳定性说明
|
||
|
||
为支持**几十万字的超长输出**与**数分钟的思考**,已做以下处理:
|
||
|
||
- **HTTP 层改用 Node `https` 模块**(非 `fetch`/undici),无默认 body 超时,避免长思考/长输出被 5 分钟超时截断。
|
||
- 渲染每 100ms 节流刷新一次 DOM;内容 < 40KB 实时 Markdown、超过自动切纯文本增量追加,流结束后最终格式化。
|
||
- **自动续写**:检测到 `finish_reason=length`(被 max_tokens 截断)或流异常中断时,自动拼接「继续」请求,无缝追加到同一条消息,最多 12 轮,无需手动发「继续」。
|
||
- 若仍被截断:在供应商配置里把「最大输出 tokens」设为 `131072`(GLM-5.2 最大输出 128K)。
|
||
|
||
## 排查与日志
|
||
|
||
所有流式请求均写入日志文件:`%APPDATA%\FengAI\fengai.log`。
|
||
|
||
日志记录:每次请求的迭代、模型、消息数、思考开关、HTTP 状态、每段的 `finish_reason`、是否 `sawDone`、累计长度、自动续写决策、错误堆栈等。
|
||
|
||
设置弹窗底部「📂 打开日志文件」可直接在资源管理器中定位该文件。遇到问题时把该文件内容发我即可定位。
|
||
|
||
## 技术栈
|
||
|
||
- Electron 31 + 原生 HTML/CSS/JS(无前端构建步骤)
|
||
- Node `https` 模块(流式 SSE 解析,无超时,AbortController 中断)
|
||
- marked + DOMPurify(Markdown 渲染与消毒)
|
||
- 本地文件存储(JSON),electron-builder 打包
|