refactor(editor): migrate to ProseMirror Mark-based ghost text system

- Replace overlay-based GhostTextOverlay.vue with ProseMirror Mark system
- Add AI toggle button with enable/disable functionality
- Implement new copilotPlugin.ts using copilotGhostMark for inline suggestions
- Fix cursor position offset in prompt.py by moving first suffix char to prefix
- Improve API error handling with abort signal support and debug logging
- Update model configuration from gpt-oss:120b to gpt-oss:20b
- Add button tooltips and improve editor styling
- Remove deprecated inlineSuggestionPlugin.ts
- Update README with new architecture diagram and feature documentation
This commit is contained in:
“ydy0615”
2026-02-13 09:24:50 +08:00
parent 16e76e1e90
commit 65d4a57d33
12 changed files with 617 additions and 440 deletions
+87 -117
View File
@@ -1,46 +1,46 @@
# LLM in Text - 智能写作助手
基于 Vue3 和 FastAPI 的智能写作助手,实现类似 GitHub Copilot 的 inline suggestions(行内建议功能。
基于 Vue3 和 FastAPI 的智能 Markdown 编辑器,集成大语言模型(LLM)实时补全建议功能。
## 项目概述
## 功能特性
本项目是一个全屏 Markdown 编辑器,集成了大语言模型(LLM)的智能补全功能。当用户输入时,系统会根据上下文实时提供文本补全建议,用户可以通过 Tab 键接受建议或点击建议文本直接插入。
## 技术栈
### 前端
- **Vue 3** - 渐进式 JavaScript 框架
- **Vite** - 下一代前端构建工具
- **Milkdown** - 基于 ProseMirror 的 WYSIWYG Markdown 编辑器
- **Pinia** - Vue 状态管理
- **Axios** - HTTP 客户端
### 后端
- **FastAPI** - 现代化的 Python Web 框架
- **OpenAI API** - 大语言模型接口
- **Ollama** - 本地 LLM 服务支持
## 核心功能
### 1. 全屏 Markdown 编辑器
### Markdown 编辑器
- 基于 Milkdown Crepe 的所见即所得编辑体验
- 支持完整 Markdown 语法
- 代码块高亮、图片粘贴等功能
- **上传/导出 Markdown 文件**(底部图标按钮)
- 支持完整 Markdown 语法和 LaTeX 公式
- 导入/导出 Markdown 文件
### 2. 智能行内建议
- 实时监听用户输入
- 基于上下文(光标前后文本)生成补全建议
- 流式响应,实时显示建议内容
- 支持多种交互方式:
### AI 智能补全
- 实时生成文本补全建议(灰色显示)
- 流式响应,低延迟体验
- 多种交互方式:
- **Tab 键**:接受建议
- **Esc 键**取消建议
- **点击建议**:直接插入
- **Esc 键**拒绝建议
- **点击灰色文本**:接受建议
- **继续输入**:自动拒绝建议
### 3. 性能优化
- 500ms 防抖机制,避免频繁请求
- 流式传输(SSE),降低延迟
- 上下文智能截取(光标前30行 + 后5行)
### AI 开关控制
- 右下角 AI 开关按钮
- 白色 = AI 启用,黑色 = AI 禁用
- 禁用时自动清除灰色文本并停止 API 调用
## 技术架构
```mermaid
flowchart LR
subgraph Frontend
A[Vue3] --> B[Milkdown Editor]
B --> C[ProseMirror Plugin]
C --> D[Ghost Text Mark]
end
subgraph Backend
E[FastAPI] --> F[LLM API]
F --> G[Stream Response]
end
D -->|SSE| E
G -->|text| D
```
## 项目结构
@@ -48,146 +48,116 @@
llm-in-text/
├── src/
│ ├── components/
│ │ ── MilkdownEditor.vue # 主编辑器组件
│ │ ├── GhostTextOverlay.vue # 建议文本显示组件
│ │ └── MarkdownEditor.vue # 备用编辑器
│ │ ── MilkdownEditor.vue # 主编辑器组件
│ ├── plugins/
│ │ ── inlineSuggestionPlugin.ts # 行内建议插件
│ └── types.ts # 类型定义
│ ├── router/
│ │ └── index.js # 路由配置
│ ├── store/
│ └── index.js # 状态管理
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
│ │ ── copilotPlugin.ts # ProseMirror AI 补全插件
├── utils/
│ ├── api.js # API 调用封装
│ │ └── config.js # 配置文件
│ ├── App.vue
│ └── main.js
├── backend/
│ ├── main.py # FastAPI 服务器
│ ├── llm.py # LLM API 调用
│ ├── prompt.py # Prompt 构建
── requirements.txt # Python 依赖
│ └── .env # 环境变量配置
├── plans/
│ ├── milkdown-editor-plan.md # 编辑器实施计划
│ └── inline-suggestions-plan.md # 建议功能实施计划
├── index.html
├── package.json
├── vite.config.js
│ ├── main.py # FastAPI 服务器
│ ├── llm.py # LLM API 调用
│ ├── prompt.py # Prompt 构建
── requirements.txt
└── README.md
```
## 快速开始
### 前置要求
### 环境要求
- Node.js 18+
- Python 3.8+
- OpenAI API Key 或 Ollama 服务
### 安装依赖
### 安装
**前端:**
```bash
# 前端
npm install
```
**后端:**
```bash
# 后端
cd backend
pip install -r requirements.txt
```
### 配置环境变量
### 配置
`backend/.env` 文件中配置:
`backend/.env` 中配置:
```env
OPENAI_API_KEY=your_api_key_here
OPENAI_API_KEY=your_api_key
OLLAMA_BASE_URL=http://localhost:11434/v1/
OLLAMA_MODEL=gpt-4
```
### 启动服务
### 启动
**启动后端:**
```bash
# 后端(端口 8000
cd backend
python main.py
```
**启动前端:**
```bash
# 前端(端口 5173
npm run dev
```
访问 `http://localhost:5173` 开始使用。
访问 http://localhost:5173
## API 接口
### POST /v1/completions
获取文本补全建议(流式响应)
流式获取补全建议
**请求**
**请求:**
```json
{
"prefix": "# Hello\n\nThis is ",
"prefix": "# Title\n\nContent ",
"suffix": "",
"languageId": "markdown"
}
```
**响应(SSE):**
**响应(SSE):**
```
data: {"content": "a "}
data: {"content": "a te"}
data: {"content": "a test"}
data: {"content": "here"}
data: {"content": "here is"}
data: {"done": true}
```
## 已知问题
## 核心实现
### 待优化项(P1
### ProseMirror Mark 系统
1. 代码重复 - fetchSuggestion 逻辑在两个文件中重复
2. 全局状态污染 - 插件使用模块级全局变量
使用 ProseMirror 的 Mark 系统实现灰色建议文本:
### 轻微问题(P2
```typescript
// 定义 ghost mark
export const copilotGhostMark = $markSchema('copilot_ghost', () => ({
excludes: '_',
inclusive: true,
toDOM: () => ['span', {
'data-copilot-ghost': '',
class: 'copilot-ghost-text'
}, 0]
}))
3. 大量调试日志影响性能
4. 缺少完整的类型定义
5. 建议文本无长度限制
6. API URL 硬编码在前端
// CSS 样式
.copilot-ghost-text {
color: #999;
opacity: 0.6;
}
```
## 开发指南
### 交互处理
### 代码规范
- **前端**:遵循 Vue 3 Composition API 最佳实践
- **后端**:遵循 FastAPI 异步编程模式
- **错误处理**:获取失败直接报错,不返回默认值
- **性能优化**:优先考虑降低延迟,避免冗余代码
### 调试
前端使用浏览器开发者工具,后端查看控制台输出。所有关键操作都有日志记录。
## 贡献指南
欢迎提交 Issue 和 Pull Request。在提交代码前,请确保:
1. 代码通过 ESLint 检查
2. 所有测试通过
3. 添加必要的注释和文档
4. 遵循项目的代码规范
- 点击灰色文本区域:接受建议(移除 mark,保留文本)
- 点击其他区域:拒绝建议(删除灰色文本)
- Tab 键:接受建议
- Esc 键:拒绝建议
## 许可证
MIT License
## 致谢
- [Milkdown](https://milkdown.dev/) - 优秀的 Markdown 编辑器框架
- [FastAPI](https://fastapi.tiangolo.com/) - 现代化的 Python Web 框架
- [OpenAI](https://openai.com/) - 大语言模型 API