实现一个 AI 编辑器 - 行内代码生成篇

发布时间:2026/7/27 19:38:03
实现一个 AI 编辑器 - 行内代码生成篇 实现一个 AI 编辑器 - 行内代码生成篇背景与目标在现代开发中AI 辅助编程逐渐成为标配。传统的代码补全提供的是基于上下文的候选列表而“行内代码生成”则更进一步当开发者输入特定注释或触发词时AI 直接在光标位置生成完整代码片段无需切换窗口或手动复制。本文将实战演示如何从零构建一个支持行内代码生成的编辑器核心模块。## 技术选型-前端编辑器框架使用 CodeMirror 6轻量、可扩展-AI 服务模拟调用 OpenAI API使用 Python FastAPI 构建后端-通信协议WebSocket实现流式响应避免阻塞 UI-核心机制基于编辑器 ChangeSet 实现非破坏性插入## 架构设计整体流程分为三步1. 用户输入触发词如//ai或#gen后前端捕获当前行内容2. 将上下文发送到后端 AI 服务3. 后端流式返回代码片段前端实时插入到编辑器光标位置。## 前端实现CodeMirror 6 集成### 1. 基础编辑器初始化首先我们创建一个支持语法高亮的编辑器实例并注册自定义扩展。javascript// editor.js - 使用 CodeMirror 6 创建编辑器import { EditorView, basicSetup } from codemirrorimport { javascript } from codemirror/lang-javascriptimport { EditorState } from codemirror/state// 创建编辑器状态const state EditorState.create({ doc: // 在这里输入代码...\n// 输入 //ai 触发代码生成, extensions: [ basicSetup, javascript(), // 开启 JavaScript 语法高亮 ]})// 挂载到 DOMconst view new EditorView({ state, parent: document.getElementById(editor)})// 导出 view 供后续使用export { view }### 2. 监听输入事件并提取上下文我们需要监听用户输入当检测到特定触发词时收集当前行的内容并发送请求。javascript// triggerHandler.js - 行内触发检测与上下文提取import { EditorView, keymap } from codemirror/viewimport { Prec } from codemirror/state// 定义触发正则行首或白空格后的 //ai 或 #genconst TRIGGER_PATTERN /^\s*(\/\/ai|#gen)\s?/function extractContext(view) { const state view.state const pos view.state.selection.main.head const line state.doc.lineAt(pos) const lineContent line.text // 如果当前行匹配触发模式 if (TRIGGER_PATTERN.test(lineContent)) { // 去除触发词获取用户意图例如//ai 生成一个排序函数 const intent lineContent.replace(TRIGGER_PATTERN, ).trim() return { intent, lineNumber: line.number } } return null}// 注册按键监听器监听回车或空格后检查const triggerExtension Prec.high( keymap.of([{ key: Enter, run: (view) { const context extractContext(view) if (context) { requestAICode(view, context) // 触发 AI 请求 return true // 阻止默认回车行为 } return false } }]))export { triggerExtension, extractContext }### 3. 流式插入代码片段后端返回的 AI 输出是流式的我们需要逐词插入到编辑器并保持光标跟随。javascript// aiInsertion.js - 流式插入代码片段import { EditorView } from codemirror/viewimport { ChangeSpec } from codemirror/state/** * 在光标的下一行插入代码并保持光标在插入内容末尾 * param {EditorView} view - 编辑器实例 * param {string} code - 要插入的代码块可能包含多行 */function insertCodeAtCaret(view, code) { const state view.state const pos state.selection.main.head const line state.doc.lineAt(pos) const insertPos line.to 1 // 在当前行末尾换行后插入 // 构建一个事务插入代码 const changes [{ from: insertPos, to: insertPos, insert: \n code }] view.dispatch({ changes, selection: { anchor: insertPos code.length 1 } // 光标移到代码末尾 })}/** * 模拟流式插入实际应使用 WebSocket 逐个字符接收 * param {EditorView} view * param {string} fullCode - 完整代码演示用 */function streamInsert(view, fullCode) { let index 0 const interval setInterval(() { if (index fullCode.length) { // 逐字符插入实际中可优化为逐词插入 const char fullCode[index] const pos view.state.selection.main.head view.dispatch({ changes: [{ from: pos, to: pos, insert: char }], selection: { anchor: pos 1 } }) index } else { clearInterval(interval) } }, 30) // 30ms 一个字符模拟流式效果}export { insertCodeAtCaret, streamInsert }## 后端实现FastAPI WebSocket### 1. AI 服务端点后端接收上下文并调用 OpenAI API此处用模拟数据代替。python# main.py - FastAPI 后端服务from fastapi import FastAPI, WebSocketfrom openai import OpenAI # 需要安装 openai 库import asyncioapp FastAPI()client OpenAI(api_keyyour-api-key) # 替换为真实密钥app.websocket(/ai/stream)async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: # 接收前端发送的上下文 data await websocket.receive_json() intent data.get(intent, ) context data.get(context, ) # 构造 prompt prompt f你是一个代码生成助手。用户意图{intent}上下文{context}请生成一段高质量的代码片段直接返回代码不要额外解释。 # 调用 OpenAI 流式 API response client.chat.completions.create( modelgpt-3.5-turbo, messages[{role: user, content: prompt}], streamTrue ) # 逐块发送给前端 for chunk in response: if chunk.choices[0].delta.content: await websocket.send_text(chunk.choices[0].delta.content) await asyncio.sleep(0.01) # 控制速度避免前端过载 # 发送结束标记 await websocket.send_text([DONE])# 启动命令uvicorn main:app --reload### 2. 模拟 AI 生成无 API 密钥时可用为了演示这里提供一个模拟生成函数直接返回硬编码的代码。python# mock_ai.py - 模拟 AI 生成用于测试def mock_generate(intent: str) - str: 根据意图生成模拟代码 intent_lower intent.lower() if 排序 in intent_lower or sort in intent_lower: return function quickSort(arr) { if (arr.length 1) return arr; const pivot arr[0]; const left [], right []; for (let i 1; i arr.length; i) { arr[i] pivot ? left.push(arr[i]) : right.push(arr[i]); } return [...quickSort(left), pivot, ...quickSort(right)];} elif fetch in intent_lower or 请求 in intent_lower: return async function fetchData(url) { try { const response await fetch(url); if (!response.ok) throw new Error(Network error); return await response.json(); } catch (error) { console.error(Fetch failed:, error); return null; }} else: return // 未匹配到意图请更具体描述## 完整集成 Demo将上述模块组合实现一个可运行的编辑器页面。html!-- index.html - 完整演示页面 --!DOCTYPE htmlhtmlhead titleAI 行内代码编辑器/title style #editor { border: 1px solid #ccc; height: 400px; } .status { margin-top: 10px; color: #666; } /style/headbody h2AI 行内代码生成编辑器/h2 p输入 code//ai 你的意图/code 然后回车即可生成代码/p div ideditor/div div idstatus classstatus等待输入.../div script typemodule import { EditorView, basicSetup } from https://cdn.jsdelivr.net/npm/codemirror6.0.1/esm import { javascript } from https://cdn.jsdelivr.net/npm/codemirror/lang-javascript/esm import { EditorState } from https://cdn.jsdelivr.net/npm/codemirror/state/esm import { keymap } from https://cdn.jsdelivr.net/npm/codemirror/view/esm import { Prec } from https://cdn.jsdelivr.net/npm/codemirror/state/esm // 模拟生成函数实际应用应连接 WebSocket function mockAI(intent) { if (intent.includes(排序)) { return function bubbleSort(arr) {\n for (let i 0; i arr.length; i) {\n for (let j 0; j arr.length - i - 1; j) {\n if (arr[j] arr[j 1]) {\n [arr[j], arr[j 1]] [arr[j 1], arr[j]];\n }\n }\n }\n return arr;\n} } return // 生成占位代码\nconsole.log(AI generated for: ${intent}); } // 创建编辑器 const view new EditorView({ state: EditorState.create({ doc: // 示例输入 //ai 排序数组 然后回车, extensions: [ basicSetup, javascript(), Prec.high(keymap.of([{ key: Enter, run: (view) { const pos view.state.selection.main.head const line view.state.doc.lineAt(pos) const match line.text.match(/^\s*\/\/ai\s(.)/) if (match) { const intent match[1] const code mockAI(intent) // 插入代码 view.dispatch({ changes: [{ from: line.to, insert: \n code }], selection: { anchor: line.to code.length 1 } }) document.getElementById(status).textContent 已生成代码: ${intent} return true } return false } }])) ] }), parent: document.getElementById(editor) }) // 在输入框上方显示状态提示 document.getElementById(editor).addEventListener(input, () { const pos view.state.selection.main.head const line view.state.doc.lineAt(pos) if (line.text.match(/^\s*\/\/ai\s/)) { document.getElementById(status).textContent 按下回车生成代码... } else { document.getElementById(status).textContent 输入 //ai 触发生成 } }) /script/body/html## 总结本文从实战角度完整实现了 AI 编辑器的行内代码生成功能涵盖以下关键点1.前端触发检测利用正则匹配//ai触发词在用户回车时拦截并提取意图。2.流式插入机制通过 WebSocket 或模拟流式返回逐字符插入代码提升用户体验。3.后端 AI 集成使用 FastAPI 封装 OpenAI 流式 API实现非阻塞响应。4.编辑器扩展借助 CodeMirror 6 的扩展机制将 AI 功能无缝嵌入编辑器核心。在实际生产环境中还需考虑- 错误处理与超时机制- 代码安全性校验- 基于编辑器上下文的智能补全而非仅靠行内意图- 多语言支持与模型调优行内代码生成不仅是技术的实现更是人机交互范式的革新——让开发者专注于逻辑而让 AI 处理重复编码。希望本文能为你的 AI 编辑器开发提供可复用的代码基础。