讓 Gemini CLI 跑在你的私有大模型上
前不久,Google 開源了 Gemini CLI 工具,它允許用戶通過命令行與 Gemini AI 模型進行高效交互。
然而,在實際應用中,出于安全性和成本控制的考慮,很多場景更適合使用本地部署的大語言模型(LLM)。因此,讓 Gemini CLI 支持連接本地 LLM 就顯得尤為重要。
我們的核心目標是:無需身份驗證,并支持接入 兼容 OpenAI 接口規范 的本地模型服務。
本文將介紹如何對 Gemini CLI 進行二次開發,使其能夠作為本地 LLM(如 Ollama、vLLM)的輕量私有客戶端使用。

1. 明確改造目標
- 刪除身份驗證功能,使用于本地LLM
- 使用OpenAI Compatible API(Ollama、Vllm都支持)
- 將啟動標志從GEMINI更改為ZONE(可以忽略)
2. 修改代碼和文件結構
(1) 了解ContentGenerator接口
/packages/core/src/core/contentGenerator.ts
這個文件是AI提供者抽象的核心代碼。通過實現這個接口,您可以支持不同的AI提供商。
export interface ContentGenerator {
generateContent(
request: GenerateContentParameters,
): Promise<GenerateContentResponse>;
generateContentStream(
request: GenerateContentParameters,
): AsyncIterable<GenerateContentResponse>;
}(2) 實現兼容OpenAI協議的ContentGenerator
/packages/core/src/core/openAICompatibleContentGenerator.ts
export class OpenAICompatibleContentGenerator implements ContentGenerator {
private endpoint: string;
private model: string;
constructor(config: { endpoint: string; model: string }) {
this.endpoint = config.endpoint;
this.model = config.model;
}
async generateContent(
request: GenerateContentParameters,
): Promise<GenerateContentResponse> {
const messages = this.convertToOpenAIMessages(request.contents);
const response = await fetch(`${this.endpoint}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: this.model,
messages,
temperature: request.generationConfig?.temperature,
max_tokens: request.generationConfig?.maxOutputTokens,
}),
});
//返回內容轉化處理
return new OpenAIGenerateContentResponse(data);
}
}(3) 修改創建者
/packages/core/src/core/contentGenerator.ts
export async function createContentGenerator(
config: ContentGeneratorConfig,
): Promise<ContentGenerator> {
// 使用本地OpenAI 接口
return new OpenAICompatibleContentGenerator({
endpoint: process.env.LOCAL_LLM_ENDPOINT || 'http://localhost:11434/v1',
model: process.env.LOCAL_LLM_MODEL || 'gemma3n:latest',
});
}(4) 添加身份驗證類型
/packages/core/src/core/contentGenerator.ts
export enum AuthType {
OAuthPersonal = 'oauth-personal',
OAuthServiceAccount = 'oauth-service-account',
GeminiApiKey = 'gemini-api-key',
USE_LOCAL_LLM = 'use-local-llm', // 新規追加
}(5) 更新身份驗證對話框
/packages/cli/src/ui/components/AuthDialog.tsx
const items = [
{ label: 'Local LLM (Ollama)', value: AuthType.USE_LOCAL_LLM },
//其他身份驗證選項(顯示但不使用)
];(6) 更新認證驗證代碼
/packages/cli/src/config/auth.ts
export async function validateAuthMethod(
authMethod: AuthType | undefined,
): Promise<string | null> {
if (authMethod === AuthType.USE_LOCAL_LLM) {
return null; //本地LLM不需要身份驗證
}
//驗證其他認證方法
}(7) 更改徽標(可有可無)
/packages/cli/src/ui/components/AsciiArt.ts
將ASCII藝術從Gemini更改為Gemma:
export const shortAsciiLogo = `
?█████████ ?████ ?███ ██ ███████████
?██ ?██????██ ?██?█ ██ ?██???????█
?██ ??██ ?██ ?██ ?█ ██ ?██
?██ ??██ ?██ ?██ ?█ ██ ?██████████
?██ ??██ ?██ ?██ ?█ ██ ?██??????
?██ ??██ ?██ ?██ ?███ ?██ ?█
?█████████ ??█████ ?██. ██ ███████████
?????????? ??????? ?????????? ???????????
`;3. 注意事項
(1) TypeScript的類型兼容性
Gemini響應格式和OpenAI格式不同,需要進行轉換處理
class OpenAIGenerateContentResponse {
constructor(private data: any) {}
get candidates() {
return [{
content: { parts: [{ text: this.data.choices[0].message.content }] },
finishReason: this.mapFinishReason(this.data.choices[0].finish_reason),
}];
}
}(2) 配置文件優先級
如果~/.gemini/settings.json存在,它可以優先于環境變量。如果要完全專用于本地LLM,則必須刪除該文件或對其進行適當配置。
4. 總結
通過對Gemini cli 的改造,可以了解到gemini非常優秀的架構設計。
優勢主要體現在:
- 開放、封閉原則:對擴展開放,對修改關閉
- 單一責任原則:每個模塊都有明確的責任
- 依賴反轉原則:依賴于接口而不是具體類
有賴于Gemini CLI優秀的架構設計以及采用了Apache-2.0開源許可,使其成為開源項目二次開發、擴展的理想選擇。

































