Langchain-Chatchat 如何实现富文本编辑?WYSIWYG 集成深度解析
在企业知识管理日益智能化的今天,一个核心矛盾逐渐显现:AI 能够快速生成答案,但这些答案往往缺乏结构与可读性;而人工编写的文档虽格式精美,却难以实时更新和智能检索。如何让系统既能“聪明地答”,又能“漂亮地写”?
Langchain-Chatchat正是为解决这一问题而生的开源本地知识库问答系统。它基于 LangChain 框架与国产大模型(如 ChatGLM、Qwen),实现了私有文档的离线解析、向量化存储与语义检索。然而,当用户希望对 AI 生成的回答进行润色、补充图表或导出为正式材料时,纯文本输出便显得力不从心。
于是,富文本编辑能力(WYSIWYG)的集成成为了提升其实用性的关键一步。这不仅关乎排版美观,更关系到知识能否被有效沉淀、复用与协作。
为什么需要 WYSIWYG?
传统问答系统的输出通常是 Markdown 或纯文本,虽然便于程序处理,但在实际业务场景中存在明显短板:
- HR 编写的员工手册需要加粗重点条款;
- 技术支持文档需插入代码块和截图;
- 培训资料要包含有序列表和引用框;
- 多人协作时,版本混乱导致信息失真。
这些问题的本质在于:AI 输出的是“内容”,而组织需要的是“资产”。只有将内容以结构化、可视化的方式固化下来,才能真正进入企业的知识资产体系。
WYSIWYG(What You See Is What You Get)编辑器正是为此设计。它允许用户像使用 Word 一样直接操作文本样式——加粗、斜体、插入图片、创建表格,所有更改即时可见,无需掌握任何标记语言。
更重要的是,现代 WYSIWYG 已不再是简单的 HTML 容器。以 Quill、ProseMirror 为代表的框架提供了强大的插件机制、状态树管理和安全过滤能力,使其能够无缝融入 AI 系统的工作流。
编辑器是如何工作的?
WYSIWYG 的核心技术建立在浏览器原生能力之上,其运行逻辑可以概括为五个阶段:
容器激活
通过设置contenteditable="true",将某个<div>变成可编辑区域。早期编辑器依赖此特性实现基本输入功能。行为捕获
监听键盘事件(如 Ctrl+B)、鼠标选择、剪贴板粘贴等动作,识别用户的格式意图。命令执行
调用document.execCommand()或框架自定义 API 执行加粗、缩进、插入节点等操作。不过该 API 已被现代标准废弃,因其不可控性和兼容性差。状态同步
高级编辑器(如 ProseMirror)不再直接操作 DOM,而是维护一棵 JSON 格式的“文档树”(Document Model),所有变更先作用于模型,再渲染到视图,确保数据一致性。内容序列化
最终将富文本转换为标准化格式输出。常见的有:
- HTML:适合网页展示
- Markdown:利于 LLM 理解与再加工
- Delta / AST:用于协同编辑与版本追踪
⚠️ 安全提示:直接存储用户输入的 HTML 极其危险。必须使用
DOMPurify等库进行净化,移除<script>、onerror=等潜在 XSS 攻击载体。
在前端集成 Quill.js 的实战示例
以下是一个典型的 WYSIWYG 集成代码片段,使用轻量级且高度可定制的 Quill.js 实现:
<!-- index.html --> <div id="editor"></div> <button onclick="saveContent()">保存修改</button>// editor.js import Quill from 'quill'; import 'quill/dist/quill.snow.css'; const quill = new Quill('#editor', { theme: 'snow', placeholder: '请输入回答内容...', modules: { toolbar: [ ['bold', 'italic', 'underline'], [{ list: 'ordered' }, { list: 'bullet' }], ['link', 'image'], ['clean'] ] } }); function saveContent() { const htmlContent = quill.root.innerHTML; const delta = quill.getContents(); // 获取操作记录,可用于协同编辑 fetch('/api/knowledge/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: htmlContent, format: 'html', source: 'manual_edit' }) }) .then(res => res.json()) .then(data => console.log('保存成功:', data)); }这段代码完成了从编辑到提交的完整闭环。值得注意的是,除了返回 HTML 外,还可以获取 Quill 的Delta 格式——一种描述编辑动作的 JSON 结构,非常适合用于实现多人协同编辑或变更审计。
后端接收到内容后,应立即进行安全处理:
# Python 后端示例:使用 dompuriy 净化 HTML from bs4 import BeautifulSoup import re def sanitize_html(dirty_html): allowed_tags = ['p', 'strong', 'em', 'u', 'ul', 'ol', 'li', 'br', 'img', 'a'] allowed_attrs = { 'a': ['href'], 'img': ['src'] } soup = BeautifulSoup(dirty_html, 'html.parser') for tag in soup.find_all(True): if tag.name not in allowed_tags: tag.decompose() else: # 过滤属性 for attr in list(tag.attrs.keys()): if attr not in allowed_attrs.get(tag.name, []): del tag[attr] # 防止 javascript: 协议 if tag.name == 'a' and tag.get('href', '').startswith('javascript:'): tag['href'] = '#' return str(soup)这套组合拳既保留了必要的富文本功能,又杜绝了安全隐患。
Langchain-Chatchat 的知识处理全流程
要理解 WYSIWYG 的价值,必须将其置于整个知识流转链条中审视。Langchain-Chatchat 的核心流程如下:
文档上传与解析
用户上传 PDF、DOCX 或 TXT 文件,系统调用专用解析器提取原始文本:
from langchain.document_loaders import PyPDFLoader, Docx2txtLoader def load_document(file_path): if file_path.endswith(".pdf"): loader = PyPDFLoader(file_path) elif file_path.endswith(".docx"): loader = Docx2txtLoader(file_path) else: raise ValueError("不支持的文件格式") return loader.load()文本分块与向量化
长文档会被切分为语义完整的段落,并通过嵌入模型转化为向量:
from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import FAISS text_splitter = RecursiveCharacterTextSplitter( chunk_size=300, chunk_overlap=50 ) docs = load_document("company_handbook.pdf") chunks = text_splitter.split_documents(docs) embedding_model = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") vectorstore = FAISS.from_documents(chunks, embedding_model) vectorstore.save_local("faiss_index")这里的关键是选用针对中文优化的嵌入模型(如 BGE-zh),以保证语义匹配精度。
提问与检索
当用户提问时,系统会将问题也编码为向量,在 FAISS 中执行近似最近邻搜索(ANN),找出最相关的几个文本块作为上下文送入 LLM。
回答生成与展示
LLM 生成的回答默认以 Markdown 形式返回前端,由前端渲染为富文本。此时若启用 WYSIWYG 编辑功能,用户即可对其进行二次加工。
这种“AI 初稿 + 人工精修”的模式,极大提升了知识产出的质量与可用性。
典型应用场景与架构设计
在一个典型的企业部署中,系统架构呈现清晰的分层结构:
graph TD A[Web Frontend] -->|HTTP| B[Backend Server] B --> C[Vector Database] B --> D[LLM Service] subgraph "前端层" A((React/Vue +<br>WYSIWYG Editor)) end subgraph "服务层" B[(FastAPI/Flask<br>- 文件解析<br>- 问答调度)] end subgraph "存储与推理" C[(FAISS/Chroma)] D[(Local LLM<br>CPU/GPU)] end前端负责交互体验,集成 WYSIWYG 编辑器供用户美化回答;后端协调文档处理流程;向量数据库支撑毫秒级检索;本地运行的 LLM 保障数据安全。
举个真实案例:某科技公司 HR 部门利用该系统构建“政策问答机器人”。每当员工询问年假规则时,AI 自动返回基础条款,HR 人员随后可在编辑器中添加计算公式、流程图和常见案例说明,最终形成一份图文并茂的标准答复模板,供后续重复使用。
工程实践中的关键考量
在实际集成过程中,有几个容易被忽视但至关重要的设计点:
统一内容格式
建议后端统一采用HTML或Markdown存储富文本内容,避免混合格式造成解析困难。如果 LLM 输出 Markdown,前端应支持双向转换(如使用marked+turndown库)。
权限控制
编辑权限应仅限管理员或特定角色,防止普通用户随意篡改核心知识条目。可通过 JWT token 携带角色信息,在接口层做鉴权拦截。
版本管理
对于重要文档,建议引入轻量级版本控制系统。每次编辑保存时记录变更摘要,支持查看历史版本与一键回滚。简单实现可基于 SQLite 存储快照,复杂场景可对接 Git 仓库。
性能优化
超长文档可能导致页面卡顿。可采用懒加载策略,仅渲染可视区域内容;或对编辑器内容分页展示,提升响应速度。
插件扩展
未来可逐步引入高级插件,如:
- 表格编辑(支持合并单元格)
- LaTeX 公式渲染(MathJax 集成)
- 流程图绘制(Mermaid 支持)
- 语音输入(Web Speech API)
这些功能将进一步拓宽系统的适用边界。
从“能回答”到“可持续用”
Langchain-Chatchat 的意义远不止于搭建一个本地化的 ChatGPT 替代品。它的真正潜力在于成为一个组织级的知识操作系统。
通过 WYSIWYG 编辑器的引入,系统实现了三个跃迁:
- 表达跃迁:从线性文本到结构化内容,支持图文混排、层级组织;
- 协作跃迁:允许多角色参与内容优化,形成 AI 与人类的协同创作闭环;
- 资产跃迁:回答不再是临时输出,而是可归档、可复用的知识资产。
未来,随着更多智能化插件的加入——比如自动推荐格式化建议、根据语义智能插入图表、支持多模态输入——这类系统将逐步演化为真正的“数字大脑”,成为企业智慧的核心载体。
技术的价值不在炫技,而在解决问题。而 Langchain-Chatchat 与 WYSIWYG 的结合,正是朝着“让 AI 更好地服务于人”迈出的坚实一步。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考