欢迎光临
我们一直在努力

AI Code编辑器到底是怎么做出来的?

1. AI Code编辑器 是什么?

可以把它们理解为:在“聊天大脑”(LLM)外面,加了一层专门为“写代码”设计的壳和工具系统。

大模型本来只会“根据文本预测下一个词”,要变成编程助手,至少得多几个能力:

  • 理解工程上下文

    • 不只是你当前打开的一个文件
    • 还要理解整个项目结构(目录、依赖、配置等)
  • 能“动手操作代码”

    • 不是只给你一段建议,而是直接替你批量改文件
    • 能在多处同步修改、插入注释、重构等
  • 能执行一些辅助工具

    • 搜索代码
    • 跑测试 / 编译
    • 调试、查看错误日志
  • Claude Code / OpenAI CodeX 的“魔法体验”主要来自于后台这几件事做得比较好,而不是靠一个“更神秘的大模型”。

    可以先看一个非常简化的架构图(适用于 Claude Code / OpenAI Code / Cursor,一家一套,思路类似):

    ┌──────────────────────────────┐
    │ IDE / 客户端 │
    │ – VSCode / Cursor / Web IDE │
    └──────────────┬──────────────┘


    ┌──────────────────────────────┐
    │ AI 编程“中间层” │
    │ – 会话管理(聊天记录) │
    │ – 项目索引(文件、符号) │
    │ – 上下文构造(prompt 构造) │
    │ – 代码操作(apply edits) │
    │ – 工具调用(搜索、运行) │
    └──────────────┬──────────────┘
    │(API 请求)

    ┌──────────────────────────────┐
    │ 大语言模型(LLM) │
    │ – Claude / GPT-4.x / o3 等 │
    │ – 有“工具调用”能力 │
    └──────────────────────────────┘

    1.1 IDE / 客户端层

    例如:

    • Cursor 自己的 IDE
    • VSCode 插件(OpenAI / Claude Code)
    • Web 版 IDE(像 GitHub Codespaces 内嵌的)

    主要负责:

    • 监控文件编辑、光标位置
    • 把用户操作和当前文件内容传给后台
    • 用“差异(highlight) / diff / inline” 的方式展示 AI 建议

    1.2 “中间层”是核心:让模型“懂项目、能动手”

    可以把中间层当作一个“AI 管家系统”:

  • 项目索引 / 语义搜索

    • 扫描项目所有文件,构建索引(关键词 + 向量)
    • 支持按文件名、符号、语义搜索:
      “找到所有调用 getUserInfo 的地方”
  • 上下文构造(prompt engineering)

    • 用户提问:“帮我重构这个函数”
    • 中间层会去:
      • 找到相关文件
      • 找到相关类型 / 依赖函数
      • 找到报错信息 / commit 记录(视产品而定)
    • 然后拼成一条“大而有序的提示词(prompt)”发给 LLM:
      • 用户目标
      • 当前文件片段
      • 相关文件摘要
      • 项目结构/约定(如框架、代码风格)
  • 工具调用(tool calling / function calling)

    • 比如模型说:“我需要搜索全局对 User 类型的定义”
    • 中间层提供一个 search_code(query) 工具
    • 模型调用 → 中间层去代码库里搜 → 把结果返回给模型
    • 如此循环,模型像一个“会问问题的程序员”,一步步探索项目
  • 代码编辑 / diff 应用

    • 模型返回的不是“整文件”,而是:
      • 修改建议(diff)
      • 要插入/替换的片段位置
    • 中间层负责:
      • 确认冲突
      • 应用补丁(patch)
      • 可能先展示预览,再让用户确认
  • 1.3 底层大模型(LLM)负责“脑力活”

    • 训练好了的通用大模型(Claude 3.5, GPT-4.1/4.5, o3 等)
    • 关键增强点:
      • 单次上下文长度较大(几十万 token),才能容纳多文件
      • 支持“工具调用”(function calling / tool use)
      • 对代码做过特别多训练(代码语料 + RL 代码任务)

    2. AI Code编辑器 实现思路分解

  • IDE 监控到:

    • 当前文件路径
    • 你选中的代码范围
    • 编辑器里其他未保存的改动
  • 中间层会收集:

    • 当前文件的全内容/相关上下文
    • 相关类型定义 / interface / class
    • 相关文件(根据索引召回:比如调用链上游/下游)
  • 构造 prompt,大致结构如下(简化版):

  • 系统指令:
    你是一个资深工程师,负责对项目进行安全的局部重构。
    避免引入破坏性变化,注意继承现有风格与约定。

    项目背景:
    – 项目使用 React + TypeScript + Zustand
    – 使用 ESLint 规则 XYZ
    – …

    用户请求:
    请重构下文选中的函数,目标是…

    当前文件内容(含选中片段标记):
    // … 上文代码
    // [BEGIN_SELECTED]
    function …
    // [END_SELECTED]
    // … 下文代码

    相关文件摘要:
    文件A.ts:…
    文件B.ts:…

    输出约定:
    只返回 JSON 格式的 patch 列表:
    [
    {
    "file": "src/xxx.ts",
    "range": {…},
    "replacement": "…"
    }
    ]

  • 调用 LLM API,模型返回 JSON patch。
  • 模型如何“自己找文件”和“自己看日志”? 依赖的是:工具调用(tool use)机制。

    中间层先这样告诉模型(在系统提示词工具描述中):

    {
    "tools": [
    {
    "name": "search_code",
    "description": "在当前项目中搜索代码",
    "parameters": {
    "type": "object",
    "properties": { "query": { "type": "string"} },
    "required": ["query"]
    }
    },
    {
    "name": "read_file",
    "description": "读取指定文件的内容",
    "parameters": { … }
    },
    {
    "name": "run_tests",
    "description": "执行测试命令并返回输出",
    "parameters": { … }
    }
    ]
    }

    • 模型在回答时,可以输出一段“调用工具”的结构
    • 中间层看到这段结构,就去执行实际的函数(比如在本地跑 npm test)
    • 把执行结果(测试输出 / 搜索结果)再作为“工具结果”塞回给模型
    • 模型再继续思考、修改方案

    这就让模型:
    从“纯文本预测机” → “能主动调用 IDE/CLI 的智能体”。

    3. AI Code编辑器 核心技术

    不管是 Claude Code、OpenAI Code 还是 Cursor,核心都依赖三类技术:

    3.1 大模型本身(LLM)

    • 训练数据中大量代码
    • 使用专门的训练目标(例如:补全代码、修 bug、执行测试反馈)
    • 通过 RL / 反馈学习强化“可执行性”、“正确性”

    这决定了“它会不会写、会不会改”。

    3.2 上下文管理 & 检索(RAG)

    • 如何从超大的代码库中,只挑出“这一问真正相关的几部分”塞给模型
    • 如何在有限上下文长度下,构造一个最佳 prompt:
      • 用户意图
      • 当前文件(重点标记改动区)
      • 关键依赖文件的片段 / 摘要
      • 错误信息 / 日志
      • 项目风格和约定(例如 lint / 框架结构)

    这决定了“它能否理解整个工程”。

    3.3 工具调用 & 自动化操作

    • 通过 tool calling,让模型“主动拉取信息”和“主动执行动作”
      • 搜索代码
      • 查看某个文件
      • 执行测试 / 编译
    • 通过 patch 机制精确修改文件
      • 小范围 diff
      • 多轮迭代(改完再跑测试、再修)

    这决定了“它能否自己动手,闭环解决问题”。

    4. 一个“最小但完整”的伪代码架构,

    基于

    • run_command(命令行)
    • 少量高级工具:read_file / write_file / apply_patch

    完成一个闭环:

    读文件 → 修改 → 写回 → 跑测试 → 看失败原因 → 再修一轮

    4.1 工具定义(提供给 LLM 的 function / tool)

    假设你用的是支持 tool calling 的模型(OpenAI / Claude 都类似),你需要给模型声明这些工具:

    TOOLS = [
    {
    "name": "read_file",
    "description": "读取项目中的一个文本文件内容",
    "parameters": {
    "type": "object",
    "properties": {
    "path": {"type": "string", "description": "文件路径,相对于项目根目录"},
    },
    "required": ["path"],
    },
    },
    {
    "name": "write_file",
    "description": "写入文件(覆盖),慎用。通常用于应用模型生成的修改。",
    "parameters": {
    "type": "object",
    "properties": {
    "path": {"type": "string"},
    "content": {"type": "string"},
    },
    "required": ["path", "content"],
    },
    },
    {
    "name": "run_command",
    "description": "在受限 shell 中执行命令,返回 stdout/stderr 和退出码。",
    "parameters": {
    "type": "object",
    "properties": {
    "cmd": {"type": "string", "description": "要执行的 shell 命令,比如 'pytest' 或 'npm test'"},
    "timeout_sec": {"type": "integer", "description": "超时时间(秒)", "default": 120}
    },
    "required": ["cmd"],
    },
    },
    {
    "name": "apply_patch",
    "description": "对已有文件内容应用一个统一 diff(unified diff)或简单 patch,返回新内容。",
    "parameters": {
    "type": "object",
    "properties": {
    "original_content": {"type": "string", "description": "文件当前的完整内容"},
    "patch": {"type": "string", "description": "一个简单的 diff/patch 描述(例如 unified diff)"},
    },
    "required": ["original_content", "patch"],
    },
    },
    ]

    这些是 后端真实实现的函数,模型只能通过 tool 调用它们。

    4.2 后端工具实现(非常简化版本)

    伪代码(Python 风格):

    import subprocess
    import textwrap

    PROJECT_ROOT = "/path/to/your/project"

    def tool_read_file(args):
    path = args["path"]
    with open(PROJECT_ROOT + "/" + path, "r", encoding="utf-8") as f:
    return {"content": f.read()}

    def tool_write_file(args):
    path = args["path"]
    content = args["content"]
    with open(PROJECT_ROOT + "/" + path, "w", encoding="utf-8") as f:
    f.write(content)
    return {"ok": True}

    def tool_run_command(args):
    cmd = args["cmd"]
    timeout_sec = args.get("timeout_sec", 120)

    try:
    result = subprocess.run(
    cmd,
    shell=True,
    cwd=PROJECT_ROOT,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    timeout=timeout_sec,
    text=True,
    )
    return {
    "returncode": result.returncode,
    "stdout": result.stdout,
    "stderr": result.stderr,
    }
    except subprocess.TimeoutExpired as e:
    return {
    "returncode": 1,
    "stdout": e.stdout or "",
    "stderr": f"TIMEOUT: command exceeded {timeout_sec}s\\n" + (e.stderr or ""),
    }

    def tool_apply_patch(args):
    original = args["original_content"]
    patch = args["patch"]
    # 这里可以:
    # – 自己实现一个极简 patch 应用器
    # – 或者直接让模型返回“新的全文内容”,这时 apply_patch 可以是 no-op
    # 为了简化 Demo,我们假设模型不搞复杂 diff,而是直接输出新文件内容,
    # 那 apply_patch 只负责返回它。
    # 实际产品里,这里会解析 unified diff,再对 original 应用。
    # 在最小 Demo 中,可以忽略 patch,直接返回 patch 作为新内容:
    new_content = patch # 假装 patch 就是完整新内容
    return {"new_content": new_content}

    说明:
    真正的 apply_patch 会解析 diff,这里为了“最小 demo”,可以先让模型直接生成 完整的新文件内容,那 patch 参数就等价于 new_content;将来你再换成真正的 diff 应用器即可。

    4.3 Agent 主循环(核心逻辑)

    这个“主循环”负责:

    • 收到用户的任务描述
    • 多轮调用 LLM + 工具,直到:
      • 测试通过,或者
      • 达到最大迭代次数

    伪代码:

    from some_llm_client import call_llm_with_tools # 你自己封装的 LLM 调用

    MAX_ITERATIONS = 5

    SYSTEM_PROMPT = """
    你是一个自动化代码修复 Agent。
    目标:在给定项目中,修复指定的 bug 或让测试通过。

    你可以使用这些工具:
    – read_file: 阅读某个文件
    – write_file: 将修改写入文件
    – run_command: 执行测试命令(如 pytest / npm test)
    – apply_patch: 根据你生成的 patch 更新文件内容

    工作流建议(但你可以自己决策):
    1. 先通过 read_file 查看相关文件内容。
    2. 分析问题,生成修改方案。
    3. 使用 apply_patch 生成新文件内容,再用 write_file 写回。
    4. 用 run_command 运行测试命令(如 'pytest')。
    5. 如果测试失败,分析 stderr,继续修正。
    6. 在你认为问题已经解决、测试通过时,以总结说明结束。

    非常重要:
    – 不要进行危险操作(删除大量文件、运行与任务无关的命令)。
    – 在一次改动中尽量改少量文件,分步进行。
    """

    def code_agent_main(user_task: str):
    """
    user_task: 用户的自然语言描述,例如:
    "请修复这个项目中导致 pytest 失败的 bug,让所有测试通过。"
    """

    messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
    {"role": "user", "content": user_task},
    ]

    for step in range(MAX_ITERATIONS):
    # 调 LLM,看它要不要用工具
    llm_response = call_llm_with_tools(
    messages=messages,
    tools=TOOLS,
    )

    if llm_response.type == "tool_call":
    # 模型请求调用某个工具
    tool_name = llm_response.tool_name
    tool_args = llm_response.tool_args

    # 根据 tool_name 分派到我们实现的函数
    if tool_name == "read_file":
    result = tool_read_file(tool_args)
    elif tool_name == "write_file":
    result = tool_write_file(tool_args)
    elif tool_name == "run_command":
    result = tool_run_command(tool_args)
    elif tool_name == "apply_patch":
    result = tool_apply_patch(tool_args)
    else:
    result = {"error": f"Unknown tool {tool_name}"}

    # 把工具结果作为新的 message 反馈给 LLM
    messages.append({
    "role": "assistant",
    "tool_call_id": llm_response.tool_call_id, # 视具体 API 而定
    "content": None,
    "name": tool_name,
    })
    messages.append({
    "role": "tool",
    "tool_call_id": llm_response.tool_call_id,
    "content": json.dumps(result),
    })
    # 然后继续下一轮循环(让 LLM 基于工具结果再想下一步)

    else:
    # llm_response 是普通自然语言回答,不再请求工具
    final_answer = llm_response.content
    print("Agent 最终回答:")
    print(final_answer)
    break

    else:
    print("达到最大迭代次数,自动停止。")

    call_llm_with_tools 的具体实现取决于你用哪家 API:

    • OpenAI:chat.completions + tools / tool_choice
    • Claude:messages.create + tools

    核心模式都是一样的:

  • 把 messages + TOOLS 发给 LLM

  • 如果它想用工具,会返回类似:

    {
    "type": "tool_call",
    "tool_name": "run_command",
    "tool_args": { "cmd": "pytest", "timeout_sec": 120 },
    "tool_call_id": "xxx"
    }

  • 你执行工具 → 把结果塞回 messages

  • 再调一次 LLM,重复直到它不再发出 tool_call,而是“正常回答”(表示完成任务)

  • 4.4 一个典型“修 bug”流程(逻辑视角)

    假设用户输入:

    “请在这个 Python 项目中修复导致 pytest 失败的问题,让所有测试通过。”

    一个完整的典型交互(逻辑层面,大致如下):

  • LLM:

    • 调 run_command(cmd="pytest")
    • 结果:测试失败,stderr 里有堆栈:
      E AttributeError: 'User' object has no attribute 'email' in user_service.py:42
  • LLM:

    • 调 read_file(path="user_service.py")
    • 看第 42 行附近代码
  • LLM:

    • 分析:User 类在别处定义,没 email 字段
    • 调 read_file(path="models.py") 看 User 定义
  • LLM:

    • 决定修改 models.py 中的 User 类,增加 email 字段,或修掉错误访问
    • 生成 patch(在最小 Demo 中可以是“新的完整 file 内容”)
    • 调 apply_patch(original_content=旧内容, patch=新内容) → 得到 new_content
    • 再调 write_file(path="models.py", content=new_content)
  • LLM:

    • 再次调 run_command("pytest")
    • 如果测试通过:返回总结说明,循环结束
    • 如果仍然失败:解析新的 stderr,继续第 2 步那样迭代
  • 整个过程就是:

    读文件 → 修改 → 写回 → 跑测试 → 看失败原因 → 再修一轮

    只不过每一步都通过 tool 调用来实现,agent 只负责“决策和生成 patch”。

    赞(0)
    未经允许不得转载:171主机测评 » AI Code编辑器到底是怎么做出来的?
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址