Files
llm-in-text/README.md

6.4 KiB
Raw Blame History

LLM in Text - 智能写作助手

基于 Vue3 和 FastAPI 的智能 Markdown 编辑器集成大语言模型LLM实时补全建议功能提供类似 GitHub Copilot 的 Ghost Text 体验。

功能特性

Markdown 编辑器

  • 基于 Milkdown Crepe 的所见即所得编辑体验
  • 支持完整 Markdown 语法和 LaTeX 公式
  • 导入/导出 Markdown 文件

AI 智能补全

  • 实时生成文本补全建议(灰色显示)
  • 流式响应,低延迟体验
  • 多种交互方式:
    • Tab 键:接受建议
    • Esc 键:拒绝建议
    • 点击灰色文本:接受建议
    • 继续输入:自动拒绝建议

AI 开关控制

  • 右下角 AI 开关按钮
  • 白色 = AI 启用,黑色 = AI 禁用
  • 禁用时自动清除灰色文本并停止 API 调用

技术架构

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

快速开始

环境要求

  • Node.js 18+
  • Python 3.8+
  • Ollama 服务(或其他兼容 OpenAI API 的服务)

安装

# 前端
npm install

# 后端
cd backend
pip install -r requirements.txt

配置

backend/.env 中配置:

OLLAMA_MODEL=gpt-oss:20b
OLLAMA_HOST=http://localhost:11434

启动

# 后端(端口 8000
cd backend
python main.py

# 前端(端口 5173
npm run dev

访问 http://localhost:5173

API 接口

POST /v1/completions

流式获取补全建议

请求:

{
  "prefix": "# Title\n\nContent ",
  "suffix": "",
  "languageId": "markdown"
}

响应SSE

data: {"content": "here"}
data: {"content": "here is"}
data: {"done": true}

核心实现

后端设计

main.py - FastAPI 服务器

  • 定义 /v1/completions 端点
  • 使用 StreamingResponse 返回 SSE 流式响应
  • CORS 配置允许跨域请求

llm.py - LLM 调用封装

  • 使用 ollama.AsyncClient 异步调用
  • 支持 think='high' 思考模式
  • 返回 contentthinking 字段

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 系统实现灰色建议文本:

// 定义 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 核心逻辑

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 清除当前建议

数据流

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

设计亮点

  1. 前后端分离:前端只负责渲染和数据回传,后端负责 LLM 调用、Prompt 构建和数据解析
  2. 低延迟优化:防抖机制 (1000ms) + SSE 流式响应 + AbortController 取消过期请求
  3. ProseMirror Mark 系统:与编辑器状态完美集成,支持 Undo/Redo
  4. 多种交互方式Tab/Esc/点击/输入,用户体验友好
  5. 智能大小限制:文档超过 32KB 自动禁用 AI 功能

许可证

MIT License