06/09/2026

从 Token 焦虑到算力自由:Antigravity IDE 2.0+ 本地 LLM 容灾自建全景记

yvonne
06/09/2026 · 3 min read

📌 引言

作为一名专注于现代化前端与 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,首先需要解决“播放器”和“电影”的问题。

  1. 引擎部署: 借助 Ollama 框架,一键在 Mac 本地拉起服务引擎。
  2. 模型选型: 考虑到显存耐受度,选定了 Google 最新开源的 gemma3:12b(体积约 8.1 GB),日志显示 M1 Pro 芯片的 Metal 硬件加速显存(10.7 GiB 可用 VRAM)被完美吃满。
  3. 环境调优配置: 默认的 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

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

WhatsApp Us

Product Inquiry

ID: #

We usually respond within 24 hours.

Message Sent!

Our team will contact you shortly.

TiHUBB WeChat

添加专属架构师微信

我们通常会在 24 小时内回复。

信息已发送!

我们的团队会尽快与您联系。