游乐游手机版
首页/AI教程/文章详情

用 Mac mini 运行 Gemma 打造本地版 Codex

时间:2026-06-06 16:38
最初,我只是想在 Mac mini 上测试一下本地大模型能否顺利运行。没想到越跑越深入,最终顺手为自己打造了一个本地版的“Codex”工具。 01 这件事的最初形态,其实远没有达到“产品化”的程度。 为什么突然开始折腾本地开源大模型?背后有一个非常现实的原因:Claude 和 Codex 确实很好用

最初,我只是想在 Mac mini 上测试一下本地大模型能否顺利运行。没想到越跑越深入,最终顺手为自己打造了一个本地版的“Codex”工具。

01

这件事的最初形态,其实远没有达到“产品化”的程度。

我原本只是想在 Mac mini 上跑 Gemma,却给自己做了一个本地版“Codex”

为什么突然开始折腾本地开源大模型?背后有一个非常现实的原因:Claude 和 Codex 确实很好用,但要算起账来,费用真的令人心疼。

偶尔问几个问题,成本还不算明显;可一旦你把它当作日常项目中的高频助手——反复分析代码、修改方案、查阅文档、修复漏洞——那笔开销就会不断攀升。

所以,当 Google 开源模型 Gemma4 发布的消息传来时,我脑海中跳出的第一个念头不是“又可以追热点了”,而是:现在,我能不能在自己的 Mac 上,真正借助开源大模型承接一部分日常开发工作?

先交代一下硬件配置:不是什么高端工作站,只是一台 2024 款的 Mac mini,配备 M4 芯片,16GB 统一内存。

那么,首个问题就显得非常朴素:这台设备,真的能在本地运行一个“足够好用”的大模型吗?注意,不是跑个演示案例就拍照收工,而是要实实在在地分担一部分 Claude 或 Codex 正在做的工作。

真正装起来之后,我找到了答案——“能”。但紧接着,剧情就走向了另一个方向。

因为在终端手动敲下 ollama run xxx 虽然也能聊几句,但我早已习惯了 Codex CLI、Claude Code 的那种交互方式。于是,一个念头开始疯狂生长:我能否复制出类似的工作风格?

02

首先说说模型选择这件事。

最终,真正在我这台 Mac 上站稳脚跟的,是以下三个模型:

gemma4:e4b
modelscope.cn/Qwen/Qwen2.5-Coder-14B-Instruct-GGUF:latest
gemma3:12b-it-qat

它们的分工简单而明确:

  • Qwen2.5-Coder-14B:主攻代码解释、局部修改方案、生成小范围的差异补丁。
  • Gemma3 12B:负责常规文档问答、图片理解,以及视频录屏抽帧后的辅助分析。
  • Gemma4 E4B:目前主要被安排成 fast-doc 角色,专门处理更快速的文档扫描和简短总结。

这中间还有个小插曲。

我也试过安装 Qwen3-VL-8B,原本指望它能专门盯着截图和录屏帧来工作。模型确实能装上去,ollama show 也明确标注了 vision 能力。但只要我通过 Ollama HTTP API 传入一张图片,它立刻翻脸,报错提示 model runner has unexpectedly stopped

这个情况非常适合拿出来说一句实话:本地开源模型这套东西,很多时候难点不在于“能不能下载”,而在于“下载完,真正调用时,到底稳不稳定”

所以后来我干脆删掉了 Qwen3-VL,所有图片和视频分析任务全部回归到 Gemma3。这个决定听起来一点也不酷,但它像一个真正要把工具用起来的人会做出的选择。

03

模型能运行之后,我很快就意识到一个问题:仅仅在终端里跟模型聊天,远远不够。

比如,我在一个老旧的 iOS 项目里动手改代码时,真正麻烦的从来不是让它回答一个问题,而是一系列结构性的问题:

  • 它不知道这个项目的目录结构和关键模块具体在什么位置。
  • 它不清楚哪些核心流程已经通过测试,不允许它顺手重写。
  • 它不明白我这一轮只打算改哪个文件,不希望它把旁边的文件也顺便“优化”了。
  • 它不知道我默认禁止它替我执行 git commitgit push
  • 它也记不住我在此项目中设定好的长期协作规则,每轮都得从头交代一遍。

那一刻,我脑海中冒出的念头不是再去找一个更大的模型,而是另一个方向:

能不能在 Ollama 之上,自己封装一层终端工具,让本地模型按照我的项目上下文、我的修改边界、我的使用习惯来工作?

这就是 Marcodex 这个想法的起点。

直说吧,我不是突然想“造一个新玩具”,而是想试试看:在成本更可控的前提下,能否将一部分原来交给 Claude 或 Codex 的工作流程,转移到本地开源模型上来。

当时的定位也非常收敛,绝对不是“复刻一个完整版 Codex”。毕竟受限于本地算力,下载下来的开源模型能力,根本无法与 GPT-5.4 或 Claude Opus 4.6 这些云端巨兽相抗衡。

所以,我的目标非常务实:先为自己做一个真正有用的本地版本。

Marcodex = 全局命令行界面 + 项目索引 + 上下文装配 + 模型路由 + 补丁草稿 + 安全门控 + 项目记忆

而且,有几个边界条件从一开始就写死了:

第一,它不会在你打开终端时自动接管 Shell,只有当你输入 marcodex ... 时它才会启动。
第二,它不负责代码提交流程,只做本地开发和问题修复的辅助,不会触碰 git commit/push
第三,第一版不追求“模型自己全自动改完整个项目”,而是坚持:“先分析 -> 再出补丁 -> 你确认后 -> 再落文件”

这几个边界条件,后来反而成了整个工具最坚实的地基。

04

在做架构设计时,我没有一上来就堆砌很多“智能体”、“Agent”之类的花哨概念,而是先把这件事拆解成几个非常具体的模块。

最终,Marcodex 的骨架大致是这样:

marcodex CLI -> WorkspaceState / MemoryStore / SessionStore
-> ProjectIndexer
-> ContextBuilder
-> ModelRouter
-> OllamaClient
-> PatchManager / SafetyGuard
-> VideoFrameExtractor

每个模块做的事情都很简单,但组合在一起就足够实用了。

ProjectIndexer 负责 /init 命令。它不会让模型自己去翻阅仓库,而是由脚本先做一次确定性的扫描:顶层目录有哪些?AGENTS.mddocs/memory/ 这些规则文档是否存在?主要编程语言是什么?当前 Git 分支和未暂存的修改有哪些?扫描完成后,再把这批结构化结果交给文档模型,生成一份人眼可读的 project-index.md

这个顺序很重要。因为我不想把“代码仓库遍历”这件事交给模型去猜测,模型的任务应该只是归纳和总结。

ContextBuilder 负责在执行 /ask/patch 之前把上下文装好。我设定的顺序是:先放入项目长期规则,然后放入项目结构摘要,再放入这次我显式指定的文件内容,接着补充当前工作区的只读状态,最后才放入我的问题。

代码里的思路大致如下:

sections = [prompt_template.strip(), "", "## 项目硬规则 / 用户偏好", self._read_optional_text(self.memory_path, fallback="(当前项目尚未初始化 memory)"),] if include_project_index: sections.extend([ "", "## 项目结构摘要", self._read_optional_text(self.project_index_path, fallback="(当前项目尚未生成 project-index.md)"),])

完成这一步后,我特别明显的一个感受是:本地模型能否真正帮上忙,很多时候不只取决于参数规模,还看你喂给它的上下文是否按正确的顺序整理好了。

ModelRouter 负责决定这一轮到底该调用哪个模型。第一版没有依靠另一个模型来决策,而是直接编写规则路由:有图片或视频就走视觉模型,执行 /patch 就走代码模型,执行 /init 和文档类任务就走文档模型,而 fast-doc 优先使用 Gemma4,若不可用则回退到 Gemma3。

if role == "vision" or has_image: return RouteResult(model=self._config_text("vision_model")) if command == "/patch": return RouteResult(model=self._config_text("code_model")) if role == "fast-doc": fast_doc_model = self._config_text("fast_doc_model") doc_model = self._config_text("doc_model") if fast_doc_model not in self.a vailable_models and doc_model: return RouteResult(model=doc_model, fallback_message=...) return RouteResult(model=fast_doc_model)

这套分工规则没什么神秘之处,但在一台 16GB 内存的机器上,它远比“让几个大模型常驻内存并互相商量”来得现实和稳定。

05

真正让我觉得这个工具开始“像个能干活的东西”,其实是 /patch/apply 这条逻辑链。

因为单纯做 /ask,本质上就是一个带项目上下文的聊天外壳。但一旦模型要开始动手修改代码,游戏规则就彻底变了:如何确保它只修改我允许它修改的文件?如何避免它触碰 .git/Pods/ 这些敏感目录?又如何保证它生成的差异补丁确实能安全地应用到文件中?

所以我没有让模型直接写文件,而是设计成了下面这个明确的工作流程:

marcodex /patch --files path/to/file "只改这个文件,修复这个问题"
marcodex /apply

中间那一层 PatchManager + SafetyGuard,我刻意做得比“能跑就行”要重一些。

具体来说:

  • /patch 必须显式传递 --files 参数,否则直接拒绝执行。
  • 补丁中如果出现任何不在白名单里的文件路径,直接拒绝。
  • 如果路径指向 .gitPods.marcodex、绝对路径或者包含 .. 的路径逃逸,直接拒绝。
  • 如果单次差异修改超过 5 个文件或 800 行,也直接拒绝——需要先让我缩小范围再说。

代码中最核心的判断逻辑大致如下:

if safe_relative_path not in allowed_files: raise PatchSafetyError(f"patch 越界修改未授权文件:{safe_relative_path}") if normalized_path.parts and normalized_path.parts[0] in BLOCKED_TOP_LEVEL_DIRS: raise PatchSafetyError(f"禁止修改高风险目录:{relative_path}")

还有一个后来补充的细节,我认为特别值得拿出来讲一讲。

模型生成补丁的那一刻,我会把目标文件当时的 sha256 摘要记录下来。等到真正执行 /apply 之前,再重新计算当前文件的摘要。如果发现该文件在补丁生成之后曾被手动修改过,就直接拒绝应用。

这个机制并不复杂,但它解决了一个极其现实的困境:风险不仅在于“模型会不会改错”,还有一种更令人头疼的情况——模型手里拿着旧版本的差异补丁,但我这边的文件已经先被修改过了。

另外,本地模型输出的统一差异格式偶尔也不稳定:它可能把 hunk 行数写错,或者在差异中混入一些没有前缀的纯文本。所以我额外加了一层格式校验:先从模型输出中提取代码块,然后检查 hunk 行的前缀,再根据实际的正文重新计算 @@ -x,y +u,v @@ 的行数,尽量避免 git apply --check 因为行数不准而直接失败。

完成这一步之后,Marcodex 才算从“只会给你建议”的阶段向前迈进了一大步,变成了一台能够在非常小、非常安全的边界内,提供一份你可以审查、可以应用、也可以随时拒绝的修改草稿

06

再来说说视频这条线。我一开始就没打算让模型“看完一整段视频并理解全部交互”。

在本地机器上,这样做很可能既沉重又不稳定。而且对于 UI 录屏这个场景来说,真正有价值的往往不是每一帧都看,而是先把关键画面按时间顺序提取出来。

所以 /ask --video 的最终实现,走的是“先用 ffmpeg/ffprobe 抽帧,再将帧图和时间戳摘要交给模型”的路线。

现在支持三种抽帧模式:

  • interval:按固定的时间间隔抽取帧。适用于 UI 流程保底,确保不会遗漏主要画面。
  • scene:按画面变化程度抽取帧。适合捕获页面跳转、弹窗出现等明显变化。
  • iframe:只抽取编码 I 帧。作为一个补充方案,不作为默认主方案。

我自己目前最常用的命令是:

marcodex /ask --video ./demo.mp4 --frame-mode interval --fps 1 --max-video-frames 8 "按时间顺序说明这段录屏里页面状态如何变化、问题出在哪里"

这个设计背后的判断很简单:能先交给脚本处理好的事情,就不要一股脑扔给模型去硬猜;模型更适合查看整理好的材料,而不是直接吞下整坨原始输入。

07

最后,真正落地时,我用了四个阶段把 Marcodex 打磨出来。

第一阶段,先把全局命令入口和项目状态跑通。也就是 marcodex/model/status/memory show/add,配合 ~/.marcodex/global-config.json 和每个项目自己的 .marcodex/ 目录。

第二阶段,补充 /init/ask 功能。这一步完成后,它就不再只是一个“Ollama 启动器”,而是开始能够带着项目索引、项目规则和指定文件内容来回答问题。

第三阶段,实现 /patch/apply 功能。这一阶段的重点不是“让模型更自由”,而是先把“只改哪些文件、如何保存差异、如何安全应用、如何留下本轮记录”这一套流程稳妥地工程化。

第四阶段,补充 /ask --videofast-doc 功能。在 Gemma4 尚未安装好之前,fast-doc 先回退到 Gemma3;待 Gemma4 下载完成后,直接调整配置将这个角色切换过去,主程序代码完全无需改动。

现在,这套工具已经可以像下面这样来使用了:

marcodex /init --refresh
marcodex /ask "先结合当前项目索引,帮我说明这个需求大概应该从哪些模块入手"
marcodex /ask --files path/to/A.swift,path/to/B.swift "先解释这几个文件现在的职责和调用关系"
marcodex /patch --files path/to/A.swift "只改这个文件,按最小风险方式修复这个问题"
marcodex /status
marcodex /apply

如果是长文档快速扫描阅读,可以直接使用:

marcodex /ask --role fast-doc "先快速总结当前项目文档中与这个需求最相关的约束"

如果这个项目中新形成了一条长期规则,我不会只让它留在聊天窗口里,而是直接写进项目记忆:

marcodex /memory add "已跑通的核心业务流程默认不要大范围重写,优先做低侵入修复"

这样一来,下一轮再提问时,这条规则会自动进入上下文,不需要每次都靠我专门提醒一遍。

08

当然,我必须承认,现在的 Marcodex 还不是一个“本地版 Codex 的完全替代品”。

我对它的定位反而比以前更收敛了:它不是用来证明本地小模型已经无所不能的,而是尝试将本地开源模型接入一个更像真实工程工作流程的外壳中。

因此,它现在最适合做的事情是以下这些:

  • 先阅读项目结构和规则,再帮你分析一个需求应该从哪里入手。
  • 针对你指定的几个文件,解释当前代码的作用。
  • 在很小的文件范围内,给出一个你可以人工复查的补丁草稿。
  • 对截图或录屏抽帧进行一层辅助分析。
  • 将项目级的长期规则和单轮会话记录保留在本地。

而那些它不适合做的事情,我也不会硬吹:

  • 让它自己去接手一个老项目的大模块,跨几十个文件进行稳定重构。
  • 让多个本地大模型长期并行常驻,像云端 agent 一样长时间连续自主规划。
  • 完全不查看差异补丁、不做人工确认,就让模型直接修改核心流程。

这也正是这一轮折腾下来,我最明确的一个感受。

在本地搭建开源大模型,真正有意思的地方,并不只是“模型能否跑起来”,而是你能否将其放入一个——边界足够清晰、上下文足够稳定、出了问题还能及时收得住——的工作流程中。

Marcodex 对我来说,就是沿着这个方向先做出来的一个版本。

它并不神奇,但它确实已经开始能帮上忙了。

如果接下来我还继续往下做,下一步大概率会先补上这三件事:

第一,把 /memory summarize 从“仅备份”升级为真正的模型压缩;
第二,为 .marcodex/cache/video-frames/ 补充一个更明确的缓存清理策略;
第三,为 SafetyGuardPatchManagerContextBuilderModelRouter 这些核心模块补充一组最小的单元测试。

因为当一件工具真正开始被你天天使用时,下一步最该补充的,往往不是那些花哨的新功能——而是那些能让它更稳定、更不容易在关键时刻给你添乱的细节。

来源:https://juejin.cn/post/7624370218575675411
上一篇编程语言深度运用:软件开发进阶(二) 下一篇Agentic AI正改变你的工作方式而非取代你
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
刚刚,OpenClaw和Cursor杀入手机!
AI教程 · 2026-07-01

刚刚,OpenClaw和Cursor杀入手机!

AI Agent,真的开始从电脑里“跑出来”了。以前我们用 Agent,基本离不开网页、IDE、终端、云环境。你想让它写代码、查资料、改项目、跑任务,很多时候还得坐在工位前盯着。但现在不一样了。OpenClaw 推出了 iOS 和安卓原生 App,手机可以变成私有 Agent 网络里的一个移动节点。

幻灯片排版优化AI智能助手,节省时间与精力
AI教程 · 2026-07-01

幻灯片排版优化AI智能助手,节省时间与精力

说起来,今天想和大家聊聊一个特别实在的话题:怎么用AI工具把PPT排版效率提上去,真正省下时间和精力。谁不想在忙忙碌碌的工作里找到点儿省事的诀窍呢?我有个朋友,为了准备一次重要汇报,连着熬了三个晚上折腾PPT,最后出来的效果也就是勉强及格。要是当时他能用上AI工具,结果会不会完全不一样?PPT排版优

AI排版软件让文档制作轻松又高效
AI教程 · 2026-07-01

AI排版软件让文档制作轻松又高效

AI智能排版工具通过自动识别文档结构、调整格式,显著提升排版效率。实际案例显示,文档处理时间可缩短约50%,项目交付效率提高40%。其功能涵盖自动排版、模板库、智能校对等,重构了文档制作流程,使用户专注内容创作,提升专业形象与市场竞争力。

Karpathy晒邮件曝光注意力机制真正起源:10年前三项独立研究
AI教程 · 2026-07-01

Karpathy晒邮件曝光注意力机制真正起源:10年前三项独立研究

2014年,三项研究几乎同时独立提出注意力机制:DzmitryBahdanau在YoshuaBengio实验室开发出RNNSearch(后称注意力),AlexGraves和JasonWeston团队也发表了类似机制。该思想源于解决循环神经网络信息瓶颈的需求,采用可微加权平均,成为深度学习核心算法。

如何选择AI排版工具与技巧提升内容创作效率
AI教程 · 2026-07-01

如何选择AI排版工具与技巧提升内容创作效率

AI排版工具推荐与技巧:如何提升内容创作效率与视觉设计效果其实,AI排版早已成为内容创作领域的热门话题。在信息爆炸的时代,大家都想知道如何让内容在海量信息中脱颖而出。简单来说,AI排版就是借助人工智能技术自动化处理文本、图像等内容的布局与设计。不妨想象一下:星巴克菜单上那些赏心悦目的排版,背后可能就