从 Token 焦虑到算力自由:Antigravity IDE 2.0+ 本地 LLM 容灾自建全景记
📌 引言
作为一名专注于现代化前端与 WordPress 定制开发的工程师,最让人崩溃的瞬间,莫过于在深夜高强度写代码、灵感如泉涌时,AI 界面冷冰冰地弹出一行:Error Individual quota reached. Contact your administrator.
云端 Token 突发耗尽,难道开发流就必须中断?为了彻底摆脱商业 AI 平台的“额度勒索”,我决定利用手头这台 Mac Book Pro (M1 Pro) 的本地硬件算力,为我的 Antigravity IDE (v2.0.1) 搭建一套无缝切换的本地大模型(Local LLM)容灾高可用方案。
本以为是一次简单的 API 端点替换,未曾想却演变成了一场与全新“全代理架构(Agentic IDE)”底层商业逻辑的斗智斗勇。以下是全套代码配置与踩坑进化流的完整记录。
🛠️ 第一阶段:基础设施兵马就位
要在本地跑 AI,首先需要解决“播放器”和“电影”的问题。
- 引擎部署: 借助 Ollama 框架,一键在 Mac 本地拉起服务引擎。
- 模型选型: 考虑到显存耐受度,选定了 Google 最新开源的
gemma3:12b(体积约 8.1 GB),日志显示 M1 Pro 芯片的 Metal 硬件加速显存(10.7 GiB 可用 VRAM)被完美吃满。 - 环境调优配置: 默认的 Ollama 在闲置 5 分钟后会自动卸载模型。为了保障随时秒回,在启动前必须对终端环境变量做一次微调配置:
Bash
# 1. 延长模型显存常驻时间至 3 小时,避免写代码中途频繁冷启动
export OLLAMA_KEEP_ALIVE="3h"
# 2. 限制单次并行只有 1 个,腾出更多显存专门给这一路代码生成
export OLLAMA_NUM_PARALLEL=1
# 3. 启动本地服务引擎
ollama serve
🧭 第二阶段:两次无功而返的“代码破局”
由于 Antigravity 2.0+ 完全摒弃了传统编辑器那种简单的 API 输入框,为了强推云端订阅,它设下了重重硬编码拦截。为了攻破它,我进行了两次代码层面的尝试:
尝试 1:编写 Node.js 自动化故障转移网关(gateway.js)
由于图形界面不给改端点,我决定在本地用 Node.js 搭建一个多模型分发网关。利用 try...catch 捕捉云端 API 返回的 429(额度耗尽)状态码,一旦熔断,自动在 100ms 内将请求体改写,无缝吐给本地 Ollama:
JavaScript
// ~/tihubb-ai-gateway/gateway.js
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// 💡 基础配置
const CLOUD_API_URL = 'https://api.google.com/v1/chat/completions'; // 云端API地址
const CLOUD_API_KEY = 'YOUR_CLOUD_API_KEY'; // 云端Token
const LOCAL_OLLAMA_URL = 'http://127.0.0.1:11434/v1/chat/completions'; // 本地Ollama
const LOCAL_MODEL_NAME = 'gemma3:12b'; // 本地备份模型
// 支持 Antigravity IDE 的 MCP 基础探测协议
app.get('/', (req, res) => {
res.json({
mcp: true,
name: "tihubb-failover-gateway",
version: "1.0.0",
supportedFeatures: ["chat", "tools"]
});
});
// 核心:大模型请求拦截与灾备分发
app.post('/v1/chat/completions', async (req, res) => {
const originalBody = req.body;
try {
console.log('🔄 正在尝试调用云端模型...');
const response = await axios.post(CLOUD_API_URL, originalBody, {
headers: {
'Authorization': `Bearer ${CLOUD_API_KEY}`,
'Content-Type': 'application/json'
},
timeout: 15000 // 15秒超时则触发降级
});
return res.json(response.data);
} catch (error) {
const status = error.response ? error.response.status : null;
console.warn(`⚠️ 云端服务不可用 (状态码: ${status || '超时'}), 正在无缝切换至本地 Gemma 3...`);
try {
// ✨ 降级核心:修正请求体中的模型名字为本地模型
const localBody = { ...originalBody, model: LOCAL_MODEL_NAME };
const localResponse = await axios.post(LOCAL_OLLAMA_URL, localBody, {
headers: { 'Content-Type': 'application/json' }
});
console.log('✅ 本地 Gemma 3 接管成功!');
return res.json(localResponse.data);
} catch (localError) {
console.error('❌ 本地 Ollama 也没有响应,请检查 ollama serve 是否开启。');
return res.status(500).json({ error: "Both cloud and local models failed." });
}
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`🚀 TiHUBB 容灾网关已在本地跑起来了: http://127.0.0.1:${PORT}`);
});
随后,我们在 Antigravity IDE 的 MCP Tools 面板中成功挂载了该网关(亮起绿色 🟢 信号,激活 10 种本地工具能力)。
尝试 2:强行拦截 VSCode OSS 级别全局策略(settings.json)
联调测试时遭遇了第二道硬拦截:即便网关亮起绿灯,一旦云端额度归零,Antigravity 2.0.1 会在最外层 UI 上直接弹出报错提示。
为了彻底在底层锁死熔断逻辑,我利用快捷键打开了其底层的 settings.json,在全局大括号中强行追加了针对 2.0+ 原子化代理架构的硬核配置:
JSON
{
"workbench.colorTheme": "Default Light Modern",
"antigravity.agent.routing.strategy": "failover",
"antigravity.agent.failover.target": "mcp",
"antigravity.agent.failover.mcpServerName": "tihubb-failover-gateway",
"antigravity.agent.quotaErrorKeywords": [
"quota reached",
"Quota exceeded",
"Individual quota reached",
"429"
],
"antigravity.models.allowLocalExecutionFallback": true
}
遭遇死局: 即使配置加满,2.0.1 版本的官方主聊天框(GUI)依旧固执地卡死发送功能。这证实了我的猜测:新版 UI 的账户鉴权是第一道硬编码拦截,它不把话传给底下的 Agent,任何 Fallback 配置都无法在 UI 层触发。
🔓 第三阶段:曲线救国,走通“终端越狱”
既然“最高统帅”(主对话框 UI)因为没钱而罢工,那我们就绕过它,直接把任务派发给拥有项目工作区最高特权的沙盒终端(Terminal Execution Pipeline)。
在 Antigravity 内置终端中,通过命令行直接跨过云端鉴权层,直接驱动 M1 Pro 的 Metal 硬件加速:
Bash
ollama run gemma3:12b "请为我写一个基于 WordPress REST API 的前端异步本地缓存 Hook,采用 React 风格,包含 localStorage 缓存过期机制。请直接输出完整的代码。"
本地的 gemma3:12b 瞬间满载运转!虽然中途因默认上下文长度限制遭遇了“生成截断”,但凭借本地模型强大的上下文记忆,输入一个 继续 便完美补全。以下是本地模型最终吐出的高质量容灾 Hook 代码:
JavaScript
import { useState, useEffect, useRef } from 'react';
// 默认缓存时间 (单位:秒),默认 1 小时
const DEFAULT_CACHE_EXPIRY = 3600;
export function useWPCache(apiUrl, options = {}) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// 统一的 WordPress 基础域名配置
const WP_API_BASE = 'https://tihubb.com/wp-json';
const cacheKey = useRef(`wp_cache_${btoa(apiUrl)}`); // 使用 useRef 确保缓存 Key 稳定
useEffect(() => {
if (!apiUrl) return;
const fetchData = async () => {
setLoading(true);
try {
// 1. 检查客户端本地缓存
const cachedItem = localStorage.getItem(cacheKey.current);
if (cachedItem) {
const { timestamp, payload } = JSON.parse(cachedItem);
// 校验强缓存是否处于有效期内
if (Date.now() - timestamp < DEFAULT_CACHE_EXPIRY * 1000) {
setData(payload);
setLoading(false);
return; // 命中缓存,直接截断网络请求
}
}
// 2. 缓存失效,向后端发起异步请求
const response = await fetch(`${WP_API_BASE}${apiUrl}`);
if (!response.ok) {
throw new Error(`WordPress API 响应异常: ${response.status}`);
}
const jsonResult = await response.json();
// 3. 写入本地存储并更新状态
const cacheData = {
timestamp: Date.now(),
payload: jsonResult
};
localStorage.setItem(cacheKey.current, JSON.stringify(cacheData));
setData(jsonResult);
} catch (err) {
setError(err.message);
// 容灾:网络请求失败时降级读取本地旧数据(过期也照样用)
const fallback = localStorage.getItem(cacheKey.current);
if (fallback) {
const { payload } = JSON.parse(fallback);
setData(payload);
console.warn('⚠️ 网络请求失败,已降级使用客户端历史缓存');
}
} finally {
setLoading(false);
}
};
fetchData();
}, [apiUrl]);
return { data, loading, error };
}
📊 深度复盘与技术总结
1. 2026 年 Agentic IDE 的双轨制防线
现代 AI 编辑器(以 Antigravity 2.0+ 为代表)在商业化上往往采取“UI 锁死计费,终端保留越狱”的双轨制。跟官方硬编码的云端 UI 计费拦截死磕是低效的,善用 Terminal 权限或在扩展商店中安装 Continue 这种完全开源开放的侧边栏进行“借壳”,才是保障个人不间断开发的最高效解法。
2. 硬件统一内存(Unified Memory)的红利
在 Mac M1 Pro 上运行 12B 级别的模型,Metal 显存加速能够提供极为流畅的 Token 输出速度。通过限制并发数 OLLAMA_NUM_PARALLEL=1 腾出 VRAM,完全可以把你的 Mac 变成一台永不掉线的私人代码服务器。
3. 构建真正的“开发 HA(高可用)”架构
对于独立站、外贸站以及品牌产品的定制开发而言,真正的安全感来自于基础设施的自主可控。
- 云端主线(充沛时): 用云端大模型做跨文件的复杂全局架构设计与核心重构。
- 本地容灾(枯竭时): 用终端里的本地
gemma3:12b承接模块化组件编写与高频 Debug。
💡 结语
这次折腾的意义,不在于写出那几行 WordPress 缓存 Hook,而在于成功将个人生产力与商业平台的 API 额度完成了解耦。
算力自由的种子已经种下,从此深夜写代码,再无 Quota 焦虑。
By : TiHUBB