Intégration API Gemini : Connecter le SDK Google directement à la passerelle locale
Ce que vous pourrez faire après ce cours
- Intégrer vos clients en utilisant les points de terminaison natifs Gemini (
/v1beta/models/*) exposés par Antigravity Tools - Appeler la passerelle locale avec les chemins de style Google
:generateContent/:streamGenerateContent - Comprendre pourquoi
x-goog-api-keypeut être utilisé directement lorsque l'authentification Proxy est activée
Votre situation actuelle
Vous avez peut-être déjà démarré le proxy inverse local, mais vous bloquez dès que vous arrivez à Gemini :
- Le SDK Google appelle par défaut
generativelanguage.googleapis.com, comment le changer pour votre proprehttp://127.0.0.1:<port>? - Les chemins Gemini ont des deux-points (
models/<model>:generateContent), beaucoup de clients les concatènent et obtiennent 404 - Vous avez activé l'authentification du proxy, mais le client Google n'envoie pas
x-api-key, donc vous obtenez toujours 401
Quand utiliser cette approche
- Vous souhaitez utiliser le "protocole natif Gemini" plutôt que la couche de compatibilité OpenAI/Anthropic
- Vous disposez déjà de clients de style Google/tiers et souhaitez migrer vers la passerelle locale à moindre coût
🎒 Préparatifs avant de commencer
Conditions préalables
- Vous avez déjà ajouté au moins 1 compte dans l'application (sinon le backend ne peut pas obtenir le jeton d'accès en amont)
- Vous avez déjà démarré le service de proxy inverse local et connaissez le port d'écoute (par défaut
8045)
Idée principale
Antigravity Tools expose les chemins natifs Gemini sur le serveur Axum local :
- Liste :
GET /v1beta/models - Appel :
POST /v1beta/models/<model>:generateContent - Flux :
POST /v1beta/models/<model>:streamGenerateContent
Le backend enveloppera le corps de la requête native Gemini dans une structure v1internal (en injectant project, requestId, requestType, etc.), puis transférera vers le point de terminaison en amont v1internal de Google (en incluant le jeton d'accès du compte). (Code source : src-tauri/src/proxy/mappers/gemini/wrapper.rs, src-tauri/src/proxy/upstream/client.rs)
Pourquoi le base URL recommandé dans le tutoriel utilise-t-il 127.0.0.1 ?
L'exemple d'intégration rapide de l'application utilise 127.0.0.1 pour éviter les problèmes de délai de résolution IPv6 dans certains environnements. (Code source : src/pages/ApiProxy.tsx)
Suivez les étapes
Étape 1 : Vérifiez que la passerelle est en ligne (/healthz)
Pourquoi Confirmez d'abord que le service est en ligne, puis résolvez les problèmes de protocole/authentification pour gagner du temps.
curl -s "http://127.0.0.1:8045/healthz"Invoke-RestMethod "http://127.0.0.1:8045/healthz"Ce que vous devriez voir : Retourne JSON, contenant {"status":"ok"} (code source : src-tauri/src/proxy/server.rs).
Étape 2 : Listez les modèles Gemini (/v1beta/models)
Pourquoi Vous devez d'abord confirmer quel est "l'ID de modèle exposé", tous les <model> suivants seront basés sur ceci.
curl -s "http://127.0.0.1:8045/v1beta/models" | headCe que vous devriez voir : La réponse contient un tableau models, chaque élément a un name similaire à models/<id> (code source : src-tauri/src/proxy/handlers/gemini.rs).
Important
Quel champ utiliser pour l'ID de modèle ?
- ✅ Utilisez le champ
displayName(commegemini-2.0-flash) - ✅ Ou retirez le préfixe
models/du champname - ❌ Ne copiez pas directement la valeur complète du champ
name(cela entraînerait des erreurs de chemin)
Si vous copiez le champ name (comme models/gemini-2.0-flash) comme ID de modèle, le chemin de la requête deviendra /v1beta/models/models/gemini-2.0-flash:generateContent, ce qui est incorrect. (Code source : src-tauri/src/proxy/common/model_mapping.rs)
Important
L'actuel /v1beta/models est un retour "déguisant la liste dynamique de modèles locaux en liste de modèles Gemini", ce n'est pas une extraction en temps réel depuis l'amont. (Code source : src-tauri/src/proxy/handlers/gemini.rs)
Étape 3 : Appelez generateContent (chemin avec deux-points)
Pourquoi La clé de l'API REST native Gemini est :generateContent comme "action avec deux-points". Le backend analysera model:method dans la même route. (Code source : src-tauri/src/proxy/handlers/gemini.rs)
curl -s \
-H "Content-Type: application/json" \
-X POST "http://127.0.0.1:8045/v1beta/models/<modelId>:generateContent" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "Bonjour"}]}
]
}'Ce que vous devriez voir : La réponse JSON contient candidates (ou il y a response.candidates à l'extérieur, le proxy déballera).
Étape 4 : Appelez streamGenerateContent (SSE)
Pourquoi Le flux est plus stable pour les "longues sorties/grands modèles". Le proxy transférera le SSE en amont vers votre client et définira Content-Type: text/event-stream. (Code source : src-tauri/src/proxy/handlers/gemini.rs)
curl -N \
-H "Content-Type: application/json" \
-X POST "http://127.0.0.1:8045/v1beta/models/<modelId>:streamGenerateContent" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "Racontez-moi une courte histoire"}]}
]
}'Ce que vous devriez voir : Le terminal affiche en continu des lignes SSE au format data: {...}, dans des circonstances normales, data: [DONE] apparaîtra à la fin (indiquant la fin du flux).
Note
data: [DONE] est le marqueur de fin standard SSE, mais n'apparaît pas toujours :
- Si l'amont se termine normalement et envoie
[DONE], le proxy le transférera - Si l'amont se déconnecte anormalement, expire ou envoie d'autres signaux de fin, le proxy n'enverra pas
[DONE]
Le code client devrait gérer selon le standard SSE : rencontrer data: [DONE] ou la déconnexion de la connexion devrait être considéré comme la fin du flux. (Code source : src-tauri/src/proxy/handlers/gemini.rs)
Étape 5 : Connectez le SDK Google Python directement à la passerelle locale
Pourquoi C'est le chemin d'exemple "intégration rapide" donné dans l'interface du projet : utilisez le paquet Python Google Generative AI pour diriger api_endpoint vers votre adresse de proxy inverse locale. (Code source : src/pages/ApiProxy.tsx)
#Installation requise : pip install google-generativeai
import google.generativeai as genai
genai.configure(
api_key="YOUR_PROXY_API_KEY",
transport='rest',
client_options={'api_endpoint': 'http://127.0.0.1:8045'}
)
model = genai.GenerativeModel('<modelId>')
response = model.generate_content("Bonjour")
print(response.text)Ce que vous devriez voir : Le programme affiche un texte de réponse du modèle.
Point de contrôle ✅
/healthzpeut retourner{"status":"ok"}/v1beta/modelspeut lister les modèles (au moins 1):generateContentpeut retournercandidates:streamGenerateContentretourneContent-Type: text/event-streamet peut continuer à envoyer du flux
Pièges à éviter
- 401 persiste : si vous avez activé l'authentification mais que
proxy.api_keyest vide, le backend rejettera directement la requête. (Code source :src-tauri/src/proxy/middleware/auth.rs) - Quelle clé dans l'en-tête : le proxy reconnaîtra simultanément
Authorization,x-api-key,x-goog-api-key. Donc "les clients de style Google n'envoient quex-goog-api-key" fonctionnera aussi. (Code source :src-tauri/src/proxy/middleware/auth.rs) - countTokens retourne toujours 0 : l'actuel
POST /v1beta/models/<model>/countTokensretourne fixe{"totalTokens":0}, c'est une implémentation fictive. (Code source :src-tauri/src/proxy/handlers/gemini.rs)
Résumé du cours
- Vous devez vous connecter à
/v1beta/models/*, pas/v1/* - L'écriture clé du chemin est
models/<modelId>:generateContent/:streamGenerateContent - Lorsque l'authentification est activée,
x-goog-api-keyest un en-tête de requête explicitement supporté par le proxy
Prochain cours
Dans le prochain cours, nous apprenrons Génération d'images Imagen 3 : mappage automatique des paramètres size/quality de l'API OpenAI Images.
Annexe : Références du code source
Cliquez pour voir les emplacements du code source
Dernière mise à jour : 2026-01-23
| Fonctionnalité | Chemin du fichier | Lignes |
|---|---|---|
| Enregistrement des routes Gemini (/v1beta/models/*) | src-tauri/src/proxy/server.rs | 170-181 |
Analyse de l'ID de modèle et routage (pourquoi le préfixe models/ entraîne des erreurs de routage) | src-tauri/src/proxy/common/model_mapping.rs | 58-77 |
Analyse de model:method + logique principale generate/stream | src-tauri/src/proxy/handlers/gemini.rs | 14-337 |
Logique de sortie SSE (transférer [DONE] plutôt que renvoyer automatiquement) | src-tauri/src/proxy/handlers/gemini.rs | 161-183 |
Structure de retour /v1beta/models (fausse liste dynamique de modèles) | src-tauri/src/proxy/handlers/gemini.rs | 39-71 |
Implémentation fictive countTokens (fixe 0) | src-tauri/src/proxy/handlers/gemini.rs | 73-79 |
| --- | --- | --- |
Exemple Python du SDK Google (api_endpoint vers la passerelle locale) | src/pages/ApiProxy.tsx | 692-734 |
| Empreinte de session Gemini (adhérence/cache avec session_id) | src-tauri/src/proxy/session_manager.rs | 121-158 |
| Enveloppement v1internal de la requête Gemini (injection de project/requestId/requestType, etc.) | src-tauri/src/proxy/mappers/gemini/wrapper.rs | 5-160 |
| Point de terminaison en amont v1internal et fallback | src-tauri/src/proxy/upstream/client.rs | 8-182 |
Constantes clés :
MAX_RETRY_ATTEMPTS = 3: limite maximum de rotations pour les requêtes Gemini (code source :src-tauri/src/proxy/handlers/gemini.rs)