feat(plugin): add document export, doc‑block, and TTS/ASR support

Adds a DocBlock component that renders embedded documents, new export buttons for DOCX
and PDF, and updates the file‑upload picker to accept *.txt, *.docx, *.pptx, and *.pdf.
Introduces a DOCX→PDF conversion bridge in the backend and new /tts and /asr
endpoints that expose TTS and speech‑recognition functionality.  The README is
rewritten to describe the new features and clean up legacy documentation.  All
changes are backward‑compatible and do not introduce breaking API changes.
This commit is contained in:
2026-04-04 23:56:18 +08:00
parent be4000b774
commit 9ff51ac2f3
25 changed files with 2995 additions and 1124 deletions

293
README.md
View File

@@ -1,264 +1,93 @@
# LLM in Text - 智能写作助手
# LLM in Text - 智能写作助手
基于 Vue3 和 FastAPI 的智能 Markdown 编辑器集成大语言模型LLM实时补全建议功能,提供类似 GitHub Copilot 的 Ghost Text 体验
基于 Vue3 和 FastAPI 的智能 Markdown 编辑器集成大语言模型LLM实时补全建议功能。
## 功能特性
### Markdown 编辑器
- 基于 Milkdown Crepe 的所见即所得编辑体验
- 支持完整 Markdown 语法和 LaTeX 公式
- 支持 Markdown 语法和 LaTeX 公式
- 支持 Mermaid 图表渲染
- 导入/导出 Markdown 文件
- 导出 DOCX 和 PDF 格式
### AI 智能补全
- 实时生成文本补全建议(灰色显示)
- 流式响应,低延迟体验
- 多种交互方式:
- **Tab 键**:接受建议
- **Esc 键**:拒绝建议
- **点击灰色文本**:接受建议
- **继续输入**:自动拒绝建议
- 多种交互方式:Tab接受、Esc拒绝、点击接受
### AI 开关控制
- 右下角 AI 开关按钮
- 白色 = AI 启用,黑色 = AI 禁用
- 禁用时自动清除灰色文本并停止 API 调用
### 文档处理
- OCR 图片识别:上传图片自动识别文字
- 文档转换PDF、DOCX、PPTX、TXT 转 Markdown
- 文档块嵌入:可折叠的文档预览块
- 智能大小限制32KB自动禁用AI
### 设置面板
- 外观主题:亮色/暗色/跟随系统
- 背景模式:默认/暖色/阅读灯/自定义图片
- 模型智能:低/中/高思考级别
- 隐私控制隐私模式防止发送IP
- 多语言界面:中英日韩德法
### 语音功能
- TTS文字转语音macOS
- STT语音转文字
## 技术架构
```mermaid
flowchart TB
subgraph Frontend["前端 (Vue3 + Vite)"]
A[App.vue] --> B[MilkdownEditor.vue]
B --> C[Crepe Editor]
C --> D[ProseMirror]
D --> E[copilotPlugin.ts]
E --> F[copilotGhostMark]
E --> G[api.js]
end
subgraph Backend["后端 (FastAPI + Python)"]
H[main.py<br/>FastAPI Server] --> I[prompt.py<br/>Prompt 构建]
H --> J[llm.py<br/>Ollama 调用]
J --> K[Ollama API]
end
G -->|POST /v1/completions<br/>SSE 流式响应| H
K -->|LLM 响应| J
```
## 项目结构
```
llm-in-text/
├── src/
│ ├── components/
│ │ └── MilkdownEditor.vue # 主编辑器组件
│ ├── plugins/
│ │ ├── copilotPlugin.ts # ProseMirror AI 补全插件
│ │ ├── types.ts # 类型定义
│ │ └── index.ts # 插件导出
│ ├── utils/
│ │ ├── api.js # API 调用封装
│ │ ├── config.js # 配置文件
│ │ └── ocrCache.js # OCR 缓存管理
│ ├── App.vue
│ └── main.js
├── backend/
│ ├── main.py # FastAPI 服务器
│ ├── llm.py # LLM API 调用
│ ├── prompt.py # Prompt 构建
│ └── requirements.txt
└── README.md
```
前端: Vue3 + Vite + Milkdown + ProseMirror
后端: FastAPI + Python + Ollama
## 快速开始
### 环境要求
- Node.js 18+
- Python 3.8+
- Ollama 服务(或其他兼容 OpenAI API 的服务)
环境: Node.js 18+、Python 3.8+、Ollama
### 安装
安装:
- 前端: npm install
- 后端: pip install -r backend/requirements.txt
```bash
# 前端
npm install
启动:
- 后端: python backend/main.py (端口8001)
- 前端: npm run dev (端口5173)
# 后端
cd backend
pip install -r requirements.txt
```
## API接口
### 配置
`backend/.env` 中配置:
```env
OLLAMA_MODEL=gpt-oss:20b
OLLAMA_HOST=http://localhost:11434
```
### 启动
```bash
# 后端(端口 8000
cd backend
python main.py
# 前端(端口 5173
npm run dev
```
访问 http://localhost:5173
## API 接口
### POST /v1/completions
流式获取补全建议
**请求:**
```json
{
"prefix": "# Title\n\nContent ",
"suffix": "",
"languageId": "markdown"
}
```
**响应SSE**
```
data: {"content": "here"}
data: {"content": "here is"}
data: {"done": true}
```
- POST /v1/completions 流式补全建议
- POST /v1/ocr 图片文字识别
- POST /v1/convert 文档转换
- POST /v1/completions/cancel 取消请求
## 核心实现
### 后端设计
### 后端
- main.py: FastAPI服务器、SSE流式响应
- llm.py: 异步Ollama调用、超时控制
- prompt.py: 7条Prompt规则
- tts_asr.py: macOS 语音处理
#### main.py - FastAPI 服务器
- 定义 `/v1/completions` 端点
- 使用 `StreamingResponse` 返回 SSE 流式响应
- CORS 配置允许跨域请求
#### llm.py - LLM 调用封装
- 使用 `ollama.AsyncClient` 异步调用
- 支持 `think='high'` 思考模式
- 返回 `content``thinking` 字段
#### prompt.py - Prompt 工程
精心设计的 Prompt 模板,包含 7 条核心规则:
| 规则 | 说明 |
|------|------|
| RULE #1 | 无缝连接 - 不重复 suffix 内容,避免"复读机"错误 |
| RULE #2 | 空白处理 - 避免双空格,正确对接标点 |
| RULE #3 | 缩进对齐 - 匹配当前缩进级别和类型 |
| RULE #4 | 列表维护 - 识别并继续任务列表、有序列表、无序列表 |
| RULE #5 | 语法闭合 - 自动闭合未完成的 Markdown 语法 |
| RULE #6 | 输出格式 - 仅输出续写文本,无解释无注释 |
| RULE #7 | 必须输出 - 始终提供有用的续写建议 |
### 前端设计
#### ProseMirror Mark 系统
使用 ProseMirror 的 Mark 系统实现灰色建议文本:
```typescript
// 定义 ghost mark
export const copilotGhostMark = $markSchema('copilot_ghost', () => ({
excludes: '_',
inclusive: true,
toDOM: () => ['span', {
'data-copilot-ghost': '',
class: 'copilot-ghost-text'
}, 0]
}))
// CSS 样式
.copilot-ghost-text {
color: #999;
opacity: 0.6;
}
```
#### copilotPlugin 核心逻辑
```mermaid
flowchart LR
A[用户输入] --> B{文档变化?}
B -->|是| C[清除旧建议]
C --> D[防抖 1000ms]
D --> E[发送 API 请求]
E --> F[收到建议]
F --> G[插入 Ghost Text]
G --> H{用户操作}
H -->|Tab| I[接受建议<br/>移除 mark]
H -->|Esc| J[拒绝建议<br/>删除文本]
H -->|点击 Ghost| I
H -->|继续输入| J
```
#### 关键函数
| 函数 | 作用 |
|------|------|
| `scheduleFetch` | 防抖调度 API 请求 |
| `insertGhostText` | 插入带 mark 的建议文本 |
| `acceptSuggestion` | Tab 接受建议 |
| `rejectSuggestion` | Esc 拒绝建议 |
| `clearGhostText` | 清除当前建议 |
### 数据流
```mermaid
sequenceDiagram
participant U as 用户
participant E as Editor (ProseMirror)
participant P as copilotPlugin
participant A as api.js
participant B as Backend
participant L as LLM
U->>E: 输入文本
E->>P: view.update()
P->>P: 清除旧建议
P->>P: 防抖 1000ms
P->>A: fetchSuggestion(prefix, suffix)
A->>B: POST /v1/completions
B->>B: build_prompt()
B->>L: ollama.chat()
L-->>B: {content, thinking}
B-->>A: SSE stream
A-->>P: suggestion text
P->>E: insertGhostText()
E-->>U: 显示灰色建议
alt Tab 键
U->>P: Tab
P->>E: acceptSuggestion()
E-->>U: 建议变为正常文本
else Esc 键
U->>P: Esc
P->>E: rejectSuggestion()
E-->>U: 建议消失
else 继续输入
U->>E: 输入其他字符
E->>P: handleKeyDown()
P->>E: clearGhostText()
end
```
### 前端
- copilotPlugin.ts: ProseMirror Mark系统
- 关键函数: scheduleFetch、insertGhostText
- Pinia Store状态管理
## 设计亮点
1. **前后端分离**:前端只负责渲染和数据回传,后端负责 LLM 调用、Prompt 构建和数据解析
2. **低延迟优化**:防抖机制 (1000ms) + SSE 流式响应 + AbortController 取消过期请求
3. **ProseMirror Mark 系统**:与编辑器状态完美集成,支持 Undo/Redo
4. **多种交互方式**Tab/Esc/点击/输入,用户体验友好
5. **智能大小限制**:文档超过 32KB 自动禁用 AI 功能
1. 前后端分离
2. 低延迟优化:防抖+SSE+AbortController
3. ProseMirror Mark系统
4. 多种交互方式
5. 智能大小限制
6. 隐私保护
7. 多语言支持
8. 主题定制
9. 文档处理
10. 语音功能
## 开发指南
代码风格: Python(4空格,snake_case) JS/TS(2空格,camelCase)
测试: pytest
构建: npm run build
## 许可证