API résumé et gestion

생성일: 2025년 1월 17일

답변에 사용된 모델 OpenAI 01 by OpenAI01

질문

ce code peux ajouter une api import sys
import json
import requests

from groq import Groq

# Stockage en mémoire des APIs (à adapter au besoin)
apis_configurees = []

# Paramètre : longueur max avant de résumer
MAX_CHARS_DIRECT_ANALYSIS = 3000


# ---------------------------------------------------------------------------
# 1. Fonction de résumé (texte brut) si la doc est trop volumineuse
def summarizer_groq(long_text, groq_api_key="gsk_XXXXXXXXXXXXXXX"):
"""
Découpe la documentation en chunks et génère un résumé global en langage naturel.
Ceci n'utilise pas le mode JSON : on veut juste un résumé texte.
"""
client = Groq(api_key=groq_api_key)

chunk_size = 3000
chunks = []
start = 0
while start < len(long_text):
end = start + chunk_size
chunks.append(long_text[start:end])
start = end

summaries = []
for i, chunk_text in enumerate(chunks, start=1):
print(f"[INFO] Résumé du chunk {i}/{len(chunks)}...")
messages = [
{
"role": "system",
"content": (
"Tu es un assistant chargé de résumer la documentation d'API. "
"Retourne un résumé concis (en langage courant) du texte fourni. "
"Ne génère pas de JSON, pas de code, juste un texte résumé clair."
)
},
{
"role": "user",
"content": chunk_text
}
]
try:
completion = client.chat.completions.create(
messages=messages,
# Mixtral est conseillé pour la génération de JSON,
# mais convient également pour la génération de texte court.
model="llama-3.3-70b-versatile",
temperature=0.2,
max_completion_tokens=1024,
top_p=1,
stream=False
)
summary_text = completion.choices[0].message.content.strip()
summaries.append(summary_text)
except Exception as e:
print(f"[ERREUR] Impossible de résumer le chunk {i} : {e}")
# On concatène juste une chaîne vide si échec
summaries.append("")

combined_summary = "\n".join(summaries)
print(f"[INFO] Résumé global généré. Longueur du résumé : {len(combined_summary)} caractères.")
return combined_summary


# ---------------------------------------------------------------------------
# 2. Fonction d'analyse finale en JSON
def analyser_api_avec_groq(input_text, groq_api_key="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"):
"""
1) Si le texte est trop long, on génère un résumé texte via summarizer_groq.
2) On passe ensuite (ou directement) le texte final dans un prompt
qui demande un JSON strict, en utilisant la 'response_format={"type": "json_object"}'
pour forcer Groq à renvoyer un JSON valide.
"""
# 1) Résume si trop volumineux
text_for_analysis = input_text
if len(input_text) > MAX_CHARS_DIRECT_ANALYSIS:
print("[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.")
text_for_analysis = summarizer_groq(input_text, groq_api_key=groq_api_key)

# 2) Appel Chat Completion en mode JSON
client = Groq(api_key=groq_api_key)

# Prompt : nous exigeons un JSON strict
messages = [
{
"role": "system",
"content": (
"Tu es un assistant d'analyse d'API, tu dois répondre UNIQUEMENT en JSON valide, sans code superflu. "
"Respecte le schéma JSON suivant (toutes les clés doivent exister) :\n\n"
"{\n"
" \"api_type\": \"REST | GraphQL | SOAP\",\n"
" \"base_url\": \"string\",\n"
" \"auth_info\": {\n"
" \"type\": \"string (Bearer, Basic, etc.)\",\n"
" \"key_name\": \"string\",\n"
" \"required\": true/false\n"
" },\n"
" \"common_headers\": {\n"
" \"Header-Name\": \"Header-Value\"\n"
" },\n"
" \"endpoints\": [\n"
" {\n"
" \"name\": \"string\",\n"
" \"path\": \"string\",\n"
" \"method\": \"GET | POST | ...\",\n"
" \"required_params\": [\"param1\", \"param2\"],\n"
" \"optional_params\": [\"param1\", \"param2\"],\n"
" \"description\": \"string\"\n"
" }\n"
" ],\n"
" \"suggested_name\": \"string\",\n"
" \"rate_limit\": \"string\",\n"
" \"confidence_score\": 0.0\n"
"}\n\n"
"Analyse le texte ci-après et renvoie STRICTEMENT un JSON conforme, sans texte additionnel."
)
},
{
"role": "user",
"content": text_for_analysis
}
]

try:
chat_completion = client.chat.completions.create(
messages=messages,
model="llama-3.3-70b-versatile", # Meilleur pour JSON d'après la doc
temperature=0.0,
max_completion_tokens=1024,
top_p=1,
stream=False,
# Activation du mode JSON : Groq renverra un JSON strict ou renverra une erreur
response_format={"type": "json_object"}
)

# Puisque response_format={"type":"json_object"} est activé,
# le contenu renvoyé EST (en principe) déjà du JSON strict.
# On l'obtient via :
content = chat_completion.choices[0].message.content

# content est déjà une chaîne JSON validée par Groq, on peut la charger directement
data = json.loads(content)
return data

except Exception as e:
print(f"[ERREUR] Échec de la conversion en JSON : {e}")
print("[INFO] Nous allons retourner un squelette par défaut.")
return {
"api_type": None,
"base_url": None,
"auth_info": {
"type": None,
"key_name": None,
"required": False
},
"common_headers": {},
"endpoints": [],
"suggested_name": "API_Inconnue",
"rate_limit": None,
"confidence_score": 0.0
}


# ---------------------------------------------------------------------------
# 3. Fonctions du menu

def ajouter_api():
print("=== Ajout d’une nouvelle API ===")

coller_doc = input("Voulez-vous coller la documentation de l’API ? (o/n) : ")
doc_api = ""

print("Collez la documentation ci-dessous (finissez par un skibidi vide) :")
lignes_doc = ""
while True:
ligne = input()
if ligne == "skibidi":
break
lignes_doc += ligne + "\n"
doc_api = lignes_doc

url_ou_description = doc_api

texte_complet = ""
if doc_api.strip():
texte_complet += doc_api.strip()
if url_ou_description.strip():
texte_complet += "\n\n" + url_ou_description.strip()

if not texte_complet:
texte_complet = "Pas d'information sur l'API."

# Appel Groq pour analyse
resultats_analyse = analyser_api_avec_groq(texte_complet, groq_api_key="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")

confidence_score = resultats_analyse.get("confidence_score", 0.0)
if confidence_score < 0.5:
print(
"Le score de confiance de l’analyse est faible. "
"Les informations retournées peuvent être partielles ou incorrectes.\n"
)

# On lit les champs
api_type = resultats_analyse.get("api_type")
base_url = resultats_analyse.get("base_url")
auth_info = resultats_analyse.get("auth_info", {})
common_headers = resultats_analyse.get("common_headers", {})
endpoints = resultats_analyse.get("endpoints", [])
suggested_name = resultats_analyse.get("suggested_name", "NouvelleAPI")
rate_limit = resultats_analyse.get("rate_limit")

print(f"Nom suggéré pour l’API : {suggested_name}")
nom_api = input(f"Entrez le nom de l’API ({suggested_name}) : ")
if not nom_api.strip():
nom_api = suggested_name

# Si auth_info.required == True, on demande la clé
api_key_value = None
if auth_info.get("required", False):
api_key_value = input("Entrez la valeur de la clé API ou du token : ")

# Construction de la config
nouvelle_api = {
"name": nom_api,
"type": api_type,
"base_url": base_url,
"auth_info": auth_info,
"api_key_value": api_key_value,
"common_headers": common_headers,
"endpoints": endpoints,
"rate_limit": rate_limit
}

apis_configurees.append(nouvelle_api)
print(f"\n[OK] L’API '{nom_api}' a été ajoutée.")
print(f" - Type : {api_type}")
print(f" - URL de base : {base_url}\n")


def lister_apis():
print("=== Liste des API configurées ===")
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return

for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. Nom : {api['name']}")
print(f" URL de base : {api['base_url'] or 'Non renseignée'}")
print(f" Type : {api['type'] or 'Inconnu'}")
if api["rate_limit"]:
print(f" Limitation de débit : {api['rate_limit']}")
if api["endpoints"]:
print(" Endpoints :")
for ep in api["endpoints"]:
print(f" - {ep['name']} ({ep['method']} {ep['path']})")
else:
print(" Aucun endpoint configuré.")
print()
print()


def modifier_api():
print("=== Modification d’une API ===")
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return

for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. {api['name']}")
choix = input("Quelle API souhaitez-vous modifier ? (nom ou numéro) : ")

api_choisie = None
try:
idx = int(choix) - 1
if 0 <= idx < len(apis_configurees):
api_choisie = apis_configurees[idx]
except ValueError:
for a in apis_configurees:
if a["name"].lower() == choix.lower():
api_choisie = a
break

if not api_choisie:
print("API introuvable.\n")
return

print(f"\nAPI sélectionnée : {api_choisie['name']}")
print("Que voulez-vous modifier ? (ex: 'changer l'URL de base', 'changer la clé API', "
"'ajouter un endpoint', 'modifier un endpoint', 'supprimer un endpoint')")
action = input("> ").lower()

if "url" in action:
new_url = input("Nouvelle URL de base : ")
api_choisie["base_url"] = new_url
print("URL de base modifiée.\n")

if "clé" in action or "key" in action:
new_key = input("Nouvelle clé API : ")
api_choisie["api_key_value"] = new_key
print("Clé API modifiée.\n")

if "ajouter un endpoint" in action:
print("=== Ajout d'un endpoint ===")
nom_ep = input("Nom du nouvel endpoint : ")
path_ep = input("Chemin (ex: /playlists/{playlist_id}/tracks) : ")
methode = input("Méthode HTTP (GET, POST, etc.) : ")
params_req = [p.strip() for p in input("Paramètres requis (séparés par des virgules) : ").split(",") if p.strip()]
params_opt = [p.strip() for p in input("Paramètres optionnels (séparés par des virgules) : ").split(",") if p.strip()]

new_ep = {
"name": nom_ep,
"path": path_ep,
"method": methode.upper(),
"required_params": params_req,
"optional_params": params_opt,
"description": ""
}
api_choisie["endpoints"].append(new_ep)
print(f"Endpoint '{nom_ep}' ajouté.\n")

if "modifier un endpoint" in action:
print("=== Modification d'un endpoint ===")
for i, ep in enumerate(api_choisie["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")
choix_ep = input("Quel endpoint ? (numéro ou nom) : ")

ep_choisi = None
try:
eidx = int(choix_ep) - 1
if 0 <= eidx < len(api_choisie["endpoints"]):
ep_choisi = api_choisie["endpoints"][eidx]
except:
for ep in api_choisie["endpoints"]:
if ep["name"].lower() == choix_ep.lower():
ep_choisi = ep
break

if not ep_choisi:
print("Endpoint introuvable.")
return

print(f"Endpoint sélectionné : {ep_choisi['name']}")
modif_ep = input("Que voulez-vous faire ? (ex: 'ajouter un paramètre', 'changer la méthode', etc.) : ").lower()
if "ajouter un paramètre" in modif_ep:
nom_p = input("Nom du paramètre : ")
r_o = input("Paramètre requis ou optionnel ? (r/o) : ")
if r_o.lower() == 'r':
ep_choisi["required_params"].append(nom_p)
else:
ep_choisi["optional_params"].append(nom_p)
print(f"Paramètre '{nom_p}' ajouté.\n")

# Vous pouvez ajouter d’autres modifications au besoin (méthode, path, etc.)

if "supprimer un endpoint" in action:
print("=== Suppression d'un endpoint ===")
for i, ep in enumerate(api_choisie["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")
choix_ep = input("Quel endpoint supprimer ? (numéro ou nom) : ")

ep_asup = None
try:
eidx = int(choix_ep) - 1
if 0 <= eidx < len(api_choisie["endpoints"]):
ep_asup = api_choisie["endpoints"][eidx]
except:
for ep in api_choisie["endpoints"]:
if ep["name"].lower() == choix_ep.lower():
ep_asup = ep
break

if ep_asup:
api_choisie["endpoints"].remove(ep_asup)
print(f"Endpoint '{ep_asup['name']}' supprimé.")
else:
print("Endpoint introuvable.")

print("Modification(s) terminée(s).\n")


def supprimer_api():
print("=== Suppression d’une API ===")
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return

for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. {api['name']}")
choix = input("Quelle API supprimer ? (nom ou numéro) : ")

api_asup = None
try:
idx = int(choix) - 1
if 0 <= idx < len(apis_configurees):
api_asup = apis_configurees[idx]
except:
for a in apis_configurees:
if a["name"].lower() == choix.lower():
api_asup = a
break

if not api_asup:
print("API introuvable.\n")
return

confirm = input(f"Êtes-vous sûr de vouloir supprimer '{api_asup['name']}' ? (o/n) : ")
if confirm.lower() == 'o':
apis_configurees.remove(api_asup)
print(f"L’API '{api_asup['name']}' a été supprimée.\n")
else:
print("Opération annulée.\n")


def tester_endpoint():
print("=== Tester un endpoint ===")
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return

for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. {api['name']}")
choix = input("Sur quelle API tester un endpoint ? (nom ou numéro) : ")

api_choisie = None
try:
idx = int(choix) - 1
if 0 <= idx < len(apis_configurees):
api_choisie = apis_configurees[idx]
except:
for a in apis_configurees:
if a["name"].lower() == choix.lower():
api_choisie = a
break

if not api_choisie:
print("API introuvable.\n")
return

if not api_choisie["endpoints"]:
print("Cette API n’a aucun endpoint configuré.\n")
return

print(f"Endpoints disponibles pour {api_choisie['name']} :")
for i, ep in enumerate(api_choisie["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")
choix_ep = input("Quel endpoint tester ? (nom ou numéro) : ")

ep_choisi = None
try:
eidx = int(choix_ep) - 1
if 0 <= eidx < len(api_choisie["endpoints"]):
ep_choisi = api_choisie["endpoints"][eidx]
except:
for ep in api_choisie["endpoints"]:
if ep["name"].lower() == choix_ep.lower():
ep_choisi = ep
break

if not ep_choisi:
print("Endpoint introuvable.")
return

required_params = {}
for rp in ep_choisi.get("required_params", []):
required_params[rp] = input(f"Entrez la valeur pour '{rp}' : ")

optional_params = {}
for op in ep_choisi.get("optional_params", []):
val = input(f"Valeur pour '{op}' (laisser vide si aucun) : ")
if val:
optional_params[op] = val

base_url = api_choisie.get("base_url") or ""
path = ep_choisi["path"]
for k, v in required_params.items():
path = path.replace(f"{{{k}}}", v)

url = base_url + path

headers = dict(api_choisie.get("common_headers", {}))
auth_info = api_choisie.get("auth_info", {})
if auth_info.get("required") and api_choisie.get("api_key_value"):
# Si Bearer
if auth_info["type"] and "bearer" in auth_info["type"].lower():
key_name = auth_info.get("key_name", "Authorization")
headers[key_name] = f"Bearer {api_choisie['api_key_value']}"
else:
# Basic ou autre
key_name = auth_info.get("key_name", "Authorization")
headers[key_name] = api_choisie["api_key_value"]

method = ep_choisi["method"].upper()
params = optional_params

print(f"\nTest de l'endpoint : {method} {url}")
print(f"En-têtes : {headers}")
print(f"Paramètres : {params}\n")

try:
if method == "GET":
r = requests.get(url, headers=headers, params=params)
elif method == "POST":
r = requests.post(url, headers=headers, json=params)
elif method == "PUT":
r = requests.put(url, headers=headers, json=params)
elif method == "DELETE":
r = requests.delete(url, headers=headers, json=params)
else:
print("Méthode non gérée.")
return

print(f"Statut : {r.status_code}")
try:
print("Réponse JSON :")
print(json.dumps(r.json(), indent=2))
except:
print("Réponse brute :")
print(r.text)

except Exception as e:
print(f"Erreur lors de l’appel : {e}")


def main():
while True:
print("=== Menu Principal ===")
print("1. Ajouter une API (assisté par IA)")
print("2. Liste des API configurées")
print("3. Modifier une API")
print("4. Supprimer une API")
print("5. Tester un endpoint")
print("6. Quitter")

choix = input("Choisissez une option : ")
if choix == '1':
ajouter_api()
elif choix == '2':
lister_apis()
elif choix == '3':
modifier_api()
elif choix == '4':
supprimer_api()
elif choix == '5':
tester_endpoint()
elif choix == '6':
print("Au revoir.")
sys.exit(0)
else:
print("Choix invalide.\n")


if __name__ == "__main__":
main()

je veux que tu me l'ameliore pour qu'il marche mieux et que je n'est pas ce type de probleme

=== Menu Principal ===
1. Ajouter une API (assisté par IA)
2. Liste des API configurées
3. Modifier une API
4. Supprimer une API
5. Tester un endpoint
6. Quitter
Choisissez une option : 1
=== Ajout d’une nouvelle API ===
Voulez-vous coller la documentation de l’API ? (o/n) : salut
Collez la documentation ci-dessous (finissez par un skibidi vide) :
salut
slaut
U.S. flagAn official website of the United States government Here's how you know
Dot gov
The .gov means it's official.
Federal government websites often end in .gov or .mil. Before sharing sensitive information, make sure you're on a federal government site.

Https
The site is secure.
The https:// ensures that you are connecting to the official website and that any information you provide is encrypted and transmitted securely.

NASA logo{ APIs }
Overview

Generate API Key

Authentication

Recover API Key

Browse APIs
Search small
Search APIs
{ NASA APIs }
Welcome to the NASA API portal. The objective of this site is to make NASA data, including imagery, eminently accessible to application developers. This catalog focuses on broadly useful and user friendly APIs and does not hold every NASA API.

Get Started Browse APIs
Generate API Key
Your API key for [email protected] has been e-mailed to you. You can use your API key to begin making web service requests immediately.

If you don't receive your API Key via e-mail within a few minutes, please contact us.

For additional support, please contact us. When contacting us, please tell us what API you're accessing and provide the following account details so we can quickly find you:

Account Email: [email protected]
Account ID: be13d8b0-4c1c-47ff-9fb9-6392250058b6
Authentication
You do not need to authenticate in order to explore the NASA data. However, if you will be intensively using the APIs to, say, support a mobile application, then you should sign up for a NASA developer key.

Web Service Rate Limits
Limits are placed on the number of API requests you may make using your API key. Rate limits may vary by service, but the defaults are:

Hourly Limit: 1,000 requests per hour
For each API key, these limits are applied across all api.nasa.gov API requests. Exceeding these limits will lead to your API key being temporarily blocked from making further requests. The block will automatically be lifted by waiting an hour. If you need higher rate limits, contact us.

DEMO_KEY Rate Limits
In documentation examples, the special DEMO_KEY api key is used. This API key can be used for initially exploring APIs prior to signing up, but it has much lower rate limits, so you’re encouraged to signup for your own API key if you plan to use the API (signup is quick and easy). The rate limits for the DEMO_KEY are:

Hourly Limit: 30 requests per IP address per hour
Daily Limit: 50 requests per IP address per day
How Do I See My Current Usage?
Your can check your current rate limit and usage details by inspecting the X-RateLimit-Limit and X-RateLimit-Remaining HTTP headers that are returned on every API response. For example, if an API has the default hourly limit of 1,000 request, after making 2 requests, you will receive this HTTP header in the response of the second request:

X-RateLimit-Remaining: 998

The hourly counters for your API key reset on a rolling basis.

Example: If you made 500 requests at 10:15AM and 500 requests at 10:25AM, your API key would become temporarily blocked. This temporary block of your API key would cease at 11:15AM, at which point you could make 500 requests. At 11:25AM, you could then make another 500 requests.

Anyone can register for an api.nasa.gov key, which can be used to access data across federal agencies.
API Key Recovery
Please contact us for help recovering an old API keyInfo I Icon

Browse APIs
Search big
Search
APOD: Astronomy Picture of the Day
Asteroids NeoWs: Near Earth Object Web Service
Asteroids - NeoWs
NeoWs (Near Earth Object Web Service) is a RESTful web service for near earth Asteroid information. With NeoWs a user can: search for Asteroids based on their closest approach date to Earth, lookup a specific Asteroid with its NASA JPL small body id, as well as browse the overall data-set.

Data-set: All the data is from the NASA JPL Asteroid team (http://neo.jpl.nasa.gov/).

This API is maintained by SpaceRocks Team: David Greenfield, Arezu Sarvestani, Jason English and Peter Baunach.

Neo - Feed
Retrieve a list of Asteroids based on their closest approach date to Earth. GET https://api.nasa.gov/neo/rest/v1/feed?start_date=START_DATE&end_date=END_DATE&api_key=API_KEY

Query Parameters
Parameter Type Default Description
start_date YYYY-MM-DD none Starting date for asteroid search
end_date YYYY-MM-DD 7 days after start_date Ending date for asteroid search
api_key string DEMO_KEY api.nasa.gov key for expanded usage
Example query
https://api.nasa.gov/neo/rest/v1/feed?start_date=2015-09-07&end_date=2015-09-08&api_key=DEMO_KEY

Neo - Lookup
Lookup a specific Asteroid based on its NASA JPL small body (SPK-ID) ID GET https://api.nasa.gov/neo/rest/v1/neo/

Path Parameters
Parameter Type Default Description
asteroid_id int none Asteroid SPK-ID correlates to the NASA JPL small body
api_key string DEMO_KEY api.nasa.gov key for expanded usage
Example query
https://api.nasa.gov/neo/rest/v1/neo/3542519?api_key=DEMO_KEY

Neo - Browse
Browse the overall Asteroid data-set GET https://api.nasa.gov/neo/rest/v1/neo/browse/

Example query
https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=DEMO_KEY

DONKI: Space Weather Database Of Notifications, Knowledge, Information
Earth: Unlock the significant public investment in earth observation data
EONET: The Earth Observatory Natural Event Tracker
EPIC: Earth Polychromatic Imaging Camera
Exoplanet: Programmatic access to NASA's Exoplanet Archive database
Open Science Data Repository: Programmatic interface for the Open Science Data Repository website
Insight: Mars Weather Service API
Mars Rover Photos: Image data gathered by NASA's Curiosity, Opportunity, and Spirit rovers on Mars
NASA Image and Video Library: API to access the NASA Image and Video Library site at images.nasa.gov
TechTransfer: Patents, Software, and Tech Transfer Reports
Satellite Situation Center: System to cast geocentric spacecraft location information into a framework of (empirical) geophysical regions
SSD/CNEOS: Solar System Dynamics and Center for Near-Earth Object Studies
Techport: API to make NASA technology project data available in a machine-readable format
TLE API: Two line element data for earth-orbiting objects at a given point in time
Vesta/Moon/Mars Trek WMTS: A Web Map Tile Service for the Vesta, Moon, and Mars Trek imagery projects
If you find a bug, please note that this page acts as a central catalog and key service for public APIs. It does not hold the actual API code. For bugs in the APIs, please look for a link to the individual API pages and reach out there. For a problem in this page, please add an issue or pull request to the GitHub repository.

code.nasa.gov
data.nasa.gov
api.nasa.gov
Open Innovation Team
Privacy


Accessibility


FOIA

NASA Official: Nidhi Wahi

Twitter GitHub
Office of the Chief Information Officer
[email protected]


ok merci

c'est la clé 5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne

et c'est l'api de la nasa


merci
skibidi
[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.
[INFO] Résumé du chunk 1/5...
[INFO] Résumé du chunk 2/5...
[INFO] Résumé du chunk 3/5...
[INFO] Résumé du chunk 4/5...
[INFO] Résumé du chunk 5/5...
[INFO] Résumé global généré. Longueur du résumé : 5216 caractères.
Nom suggéré pour l’API : NASA API
Entrez le nom de l’API (NASA API) :
Entrez la valeur de la clé API ou du token : 5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne

[OK] L’API 'NASA API' a été ajoutée.
- Type : REST
- URL de base : https://api.nasa.gov

=== Menu Principal ===
1. Ajouter une API (assisté par IA)
2. Liste des API configurées
3. Modifier une API
4. Supprimer une API
5. Tester un endpoint
6. Quitter
Choisissez une option : 5
=== Tester un endpoint ===
1. NASA API
Sur quelle API tester un endpoint ? (nom ou numéro) : 1
Endpoints disponibles pour NASA API :
1. NeoWs (GET /neo/rest/v1/neo/browse)
2. DONKI (GET /donki)
3. EONET (GET /eonet)
4. EPIC (GET /epic)
5. Exoplanet (GET /exoplanet)
Quel endpoint tester ? (nom ou numéro) : 1
Entrez la valeur pour 'api_key' : 5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne

Test de l'endpoint : GET https://api.nasa.gov/neo/rest/v1/neo/browse
En-têtes : {'Accept': 'application/json', 'api_key': '5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne'}
Paramètres : {}

Statut : 403
Réponse JSON :
{
"error": {
"code": "API_KEY_MISSING",
"message": "No api_key was supplied. Get one at https://api.nasa.gov:443"
}
}
=== Menu Principal ===
1. Ajouter une API (assisté par IA)
2. Liste des API configurées
3. Modifier une API
4. Supprimer une API
5. Tester un endpoint
6. Quitter
Choisissez une option : 5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne
Choix invalide.

=== Menu Principal ===
1. Ajouter une API (assisté par IA)
2. Liste des API configurées
3. Modifier une API
4. Supprimer une API
5. Tester un endpoint
6. Quitter
Choisissez une option : 5
=== Tester un endpoint ===
1. NASA API
Sur quelle API tester un endpoint ? (nom ou numéro) : 1
Endpoints disponibles pour NASA API :
1. NeoWs (GET /neo/rest/v1/neo/browse)
2. DONKI (GET /donki)
3. EONET (GET /eonet)
4. EPIC (GET /epic)
5. Exoplanet (GET /exoplanet)
Quel endpoint tester ? (nom ou numéro) : 5
Entrez la valeur pour 'api_key' : 5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne

Test de l'endpoint : GET https://api.nasa.gov/exoplanet
En-têtes : {'Accept': 'application/json', 'api_key': '5xK9D97IiDTTCjEnNaSIGAivfKkPOqDipGjDetne'}
Paramètres : {}

Statut : 404
Réponse JSON :
Réponse brute :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'">
<title>Page not found &middot; GitHub Pages</title>
<style type="text/css" media="screen">
body {
background-color: #f1f1f1;
margin: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.container { margin: 50px auto 40px auto; width: 600px; text-align: center; }

a { color: #4183c4; text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { width: 800px; position:relative; left: -100px; letter-spacing: -1px; line-height: 60px; font-size: 60px; font-weight: 100; margin: 0px 0 50px 0; text-shadow: 0 1px 0 #fff; }
p { color: rgba(0, 0, 0, 0.5); margin: 20px 0; line-height: 1.6; }

ul { list-style: none; margin: 25px 0; padding: 0; }
li { display: table-cell; font-weight: bold; width: 1%; }

.logo { display: inline-block; margin-top: 35px; }
.logo-img-2x { display: none; }
@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min--moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
}

#suggestions {
margin-top: 35px;
color: #ccc;
}
#suggestions a {
color: #666666;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
}

</style>
</head>
<body>

<div class="container">

<h1>404</h1>
<p><strong>File not found</strong></p>

<p>
The site configured at this address does not
contain the requested file.
</p>

<p>
If this is your site, make sure that the filename case matches the URL
as well as any file permissions.<br>
For root URLs (like <code>http://example.com/</code>) you must provide an
<code>index.html</code> file.
</p>

<p>
<a href="https://help.github.com/pages/">Read the full documentation</a>
for more information about using <strong>GitHub Pages</strong>.
</p>

<div id="suggestions">
<a href="https://githubstatus.com">GitHub Status</a> &mdash;
<a href="https://twitter.com/githubstatus">@githubstatus</a>
</div>

<a href="/" class="logo logo-img-1x">
<img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTZCRDY3REIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTZCRDY3RUIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdCQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjdDQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SM9MCAAAA+5JREFUeNrEV11Ik1EY3s4+ddOp29Q5b0opCgKFsoKoi5Kg6CIhuwi6zLJLoYLopq4qsKKgi4i6CYIoU/q5iDAKs6syoS76IRWtyJ+p7cdt7sf1PGOD+e0c3dygAx/67ZzzPM95/877GYdHRg3ZjMXFxepQKNS6sLCwJxqNNuFpiMfjVs4ZjUa/pmmjeD6VlJS8NpvNT4QQ7mxwjSsJiEQim/1+/9lgMHgIr5ohuxG1WCw9Vqv1clFR0dCqBODElV6v90ogEDjGdYbVjXhpaendioqK07CIR7ZAqE49PT09BPL2PMgTByQGsYiZlQD4uMXtdr+JxWINhgINYhGT2MsKgMrm2dnZXgRXhaHAg5jEJodUAHxux4LudHJE9RdEdA+i3Juz7bGHe4mhE9FNrgwBCLirMFV9Okh5eflFh8PR5nK5nDabrR2BNJlKO0T35+Li4n4+/J+/JQCxhmu5h3uJoXNHPbmWZAHMshWB8l5/ipqammaAf0zPDDx1ONV3vurdidqwAQL+pEc8sLcAe1CCvQ3YHxIW8Pl85xSWNC1hADDIv0rIE/o4J0k3kww4xSlwIhcq3EFFOm7KN/hUGOQkt0CFa5WpNJlMvxBEz/IVQAxg/ZRZl9wiHA63yDYieM7DnLP5CiAGsC7I5sgtYKJGWe2A8seFqgFJrJjEPY1Cn3pJ8/9W1e5VWsFDTEmFrBcoDhZJEQkXuhICMyKpjhahqN21hRYATKfUOlDmkygrR4o4C0VOLGJKrOITKB4jijzdXygBKixyC5TDQdnk/Pz8qRw6oOWGlsTKGOQW6OH6FBWsyePxdOXLTgxiyebILZCjz+GLgMIKnXNzc49YMlcRdHXcSwxFVgTInQhC9G33UhNoJLuqq6t345p9y3eUy8OTk5PjAHuI9uo4b07FBaOhsu0A4Unc+T1TU1Nj3KsSSE5yJ65jqF2DDd8QqWYmAZrIM2VlZTdnZmb6AbpdV9V6ec9znf5Q7HjYumdRE0JOp3MjitO4SFa+cZz8Umqe3TCbSLvdfkR/kWDdNQl5InuTcysOcpFT35ZrbBxx4p3JAHlZVVW1D/634VRt+FvLBgK/v5LV9WS+10xMTEwtRw7XvqOL+e2Q8V3AYIOIAXQ26/heWVnZCVfcyKHg2CBgTpmPmjYM8l24GyaUHyaIh7XwfR9ErE8qHoDfn2LTNAVC0HX6MFcBIP8Bi+6F6cdW/DICkANRfx99fEYFQ7Nph5i/uQiA214gno7K+guhaiKg9gC62+M8eR7XsBsYJ4ilam60Fb7r7uAj8wFyuwM1oIOWgfmDy6RXEEQzJMPe23DXrVS7rtyD3Df8z/FPgAEAzWU5Ku59ZAUAAAAASUVORK5CYII=">
</a>

<a href="/" class="logo logo-img-2x">
<img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpEQUM1QkUxRUI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpEQUM1QkUxRkI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdGQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjgwQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+hfPRaQAAB6lJREFUeNrsW2mME2UYbodtt+2222u35QheoCCYGBQligIJgkZJNPzgigoaTEj8AdFEMfADfyABkgWiiWcieK4S+QOiHAYUj2hMNKgYlEujpNttu9vttbvdw+chU1K6M535pt3ubHCSyezR+b73eb73+t7vrfXsufOW4bz6+vom9/b23ovnNNw34b5xYGAgODg46Mbt4mesVmsWd1qSpHhdXd2fuP/Afcput5/A88xwymcdBgLqenp6FuRyuWV4zu/v759QyWBjxoz5t76+/gun09mK5xFyakoCAPSaTCazNpvNPoYVbh6O1YKGRF0u13sNDQ27QMzfpiAAKj0lnU6/gBVfAZW2WWpwwVzy0IgP3G73FpjI6REhAGA9qVRqA1b9mVoBVyIC2tDi8Xg24+dUzQiAbS/s7Ox8G2o/3mKCC+Zw0efzPQEfcVjYrARX3dbV1bUtHo8fMgt42f+Mp0yUTVQbdWsAHVsikdiHkHaPxcQXQufXgUBgMRxme9U0AAxfH4vFvjM7eF6UkbJS5qoQwEQGA57Ac5JllFyUVZZ5ckUEgMVxsK2jlSYzI+QXJsiyjzNEAJyJAzb/KQa41jJKL8pODMQiTEAymXw5n8/P0IjD3bh7Rgog59aanxiIRTVvV/oj0tnHca/WMrVwODwB3raTGxzkBg/gnZVapFV62Wy2n5AO70HM/5wbJ0QnXyQSaVPDIuNZzY0V3ntHMwxiwHA0Gj2Np7ecIBDgaDAYXKCQJM1DhrgJ3nhulcPbl8j4NmHe46X/g60fwbz3aewjkqFQaAqebWU1AOqyQwt8Id6qEHMc97zu7u7FGGsn7HAiVuosVw7P35C1nccdgSCxop1dHeZswmfHMnxBo6ZTk+jN8dl/vF7vWofDsa+MLN9oEUBMxOb3+1eoEsBVw6Zmua49r8YmhAKDiEPcMwBsxMiqQ+ixzPFxZyqRpXARG/YOr1ObFJ0gUskXBbamcR1OKmMUvDxHRAu8/LmY3jFLMUpFqz9HxG65smYJdyKyECOxDiEAe/p1gjF2oonivZAsxVgl2daa4EQWCW6J55qFAFFZiJWYLxNQy2qOSUzGRsyXCUDIeliwAHEO4WSlWQBRFoZakXcKmCXmyXAKs0Ve9vl8q42WoIYpJU4hV3hKcNs8m9gl7p/xQ73eF5kB4j5mNrWmTJRNwAzqiV1CxjVTZCIkEq+Z1bZFZSN2CenmVAFVy4Plz8xKAGWjjAKFk6lCBMDR/MJjLLMSQNm43xAiQKTaA+9/wewhDjL+JVI1kkTSSOTcKbMTwPqESAot6dn6Fr1gHwVJju6IRuyiByPuUUBAg5DGkAgBmxlvdgIEK9gDkohdY/BJo4CAG0R8miRSsGABkgVQs4KXu098IgUXSSRsFAoKZiVAVDY2WUiiPTjYRi41KwGisrGsLtlsth8Fiwnz2fBkQvWfRtlE3iF2yW63/yCacXZ1dW02GwGyTFaRd4idJnCKHRaCxYRHoG5LTKT6SyiToP1fJHbmAYPYRR0UnZQtMnA6s0zg+GZBlt0Gdo7EPHgpE3Q6nZ8YyLhc8Xj8MJh/aKTAY+5FPAKHLE7RdwuYJZmNwzyCMkBCYyKROJBMJl9B/PXXCjjmCmDOVzH3fiPpObEWGqoKe4EBl8v1hlqsdLvd23mkxHM9pc9kMpmno9HoeTii7ewbHEZPPx1ztLS1tV3AnGuMjiNjvbQFuHw6zDo5By7dTPAQNBgMLrRarTkSls1mnwT7uwp9virx9QzbW/HuV/j5d/b+6jniKlllP8lkeONJDk+dq9GsQTnC4fB1heO0K47Hwe7WdDr9nAKgXwOBwHI+C45Htj1d6sd429TUNEcmUdc+PRaLHcvn87dXW4ugzdsaGxufL94NFv9zi1J7GVbhlvb2dnaJ3SVrxfc+n2+NTsZ7/H7/Mr3g5XdSIHyJSH1PZ+7fToyl2+ErqilgZ4NaLYB9goVGaHjR93Hv1ZrU4XDsFT20kH3PObzbWk0CgG1jacVIUnAQb9F+VexyLMzkpcLv0IJV7AHQIOCAUYHx7v5qgScmYHtTqSAyZLEJTK22Bie4iq3xsqpm4SAf9Hq9a2DnJ4uLK3SEULcdRvp3i3zHySqpficxEdsQc1NrlYXXvR+O7qASSezXB+h1SuUomgg9LL8BUoV4749EIolKh+EiqWmqVEZlDgHks2pxHw7xTqUQw9J5NcAXOK10AGIoZ6Zli6JY6Z1Q461KoZ4NiKLHarW+KDsxlDUPHZ5zPQZqUVDPJsTqb5n9malbpAh8C2XXDLl62+WZIDFRUlNVOiwencnNU3aQEkL+cDMSoLvZo2fQB7AJssNAuFuvorlDVVkkg2I87+jo2K2QAVphDrfyViK5VqtO34OkaxXCp+7drdDBCAdubm6eidX+2WwqT5komwh4YQLk+H4aE93h8Xg2gvHekQZOGSgLZTLyDTLJ4Lx9/KZWKBSainT4Iy3FqQBfnUZR42PKQFksBr9QKVXCPusD3OiA/RkQ5kP8qV/Jl1WywAp/6+dcmPM2zL1UrUahe4JqfnWWKXIul3uUbfP8njAFLW1OFr3gdFtZ72cNH+PtQT7/brW+NXqJAHh0y9V8/U/A1U7AfwIMAD7mS3pCbuWJAAAAAElFTkSuQmCC">
</a>
</div>
</body>
</html>

=== Menu Principal ===
1. Ajouter une API (assisté par IA)
2. Liste des API configurées
3. Modifier une API
4. Supprimer une API
5. Tester un endpoint
6. Quitter

사고

Debugging the issue with API calls, I noticed the "api_key" should go into the query parameters, not the header. This tweak should prevent errors from wrongful endpoint or key issues.

Crafting the request

I’m thinking through how to adjust the API key location in headers or query parameters. The goal is to align the request with NASA's requirements to avoid 403 errors.

Allocating API key

I’m noting that unifying the API key's location to optional parameters ensures it’s always a query parameter, making it compatible with NASA's endpoint requirements.

Integrating API key

Aligning the API key with optional parameters for consistent query parameter inclusion, ensuring seamless integration with NASA's endpoints. This leads me to consider more efficient approaches.

Tweaking the approach

Merging parameters, excluding headers for API keys, and preserving 'Accept: application/json' headers. Considering fallback strategies for non-existent endpoints might be next on the agenda.

Refining parameter methods

I’m streamlining api_key handling, ensuring it’s a query parameter for NASA's endpoints. Also, I’m setting up unified parameter treatment and maintaining custom handling for api_key.

Thought about improving API integration pendant 28 secondes

답변

Voici une version améliorée du script qui prend en compte les spécificités de l’API de la NASA, notamment le fait que l’api_key doit être transmise sous forme de paramètre de requête (query parameter) et non dans les headers. J’ai également ajouté quelques garde-fous pour éviter que le menu principal ne plante si l’utilisateur saisit une valeur non prévue (par exemple taper la clé d’API au lieu d’un chiffre).

Principales améliorations apportées :

  1. Gestion de l'API key :

    • Si l’auth_info["key_name"] est "api_key", alors on force son utilisation en tant que paramètre de requête.
    • Si c’est "Authorization" (ou autre) et que auth_info["type"] contient "Bearer" ou "Basic", on la passe dans les headers.
    • Sinon, on l’enverra en header générique.
  2. Fusion des paramètres :

    • Les required_params et optional_params sont désormais tous envoyés en tant que paramètres de query si on ne les a pas remplacés dans le path. Ainsi, si un paramètre requis s’appelle api_key mais n’existe pas sous la forme /{api_key} dans l’URL, on le passera en query param.
  3. Robustesse du menu :

    • Quand l’utilisateur saisit un choix au menu principal, si ce n’est pas un entier ou si l’entier est hors plage, on affiche un message d’erreur puis on relance le menu.
    • Même chose pour le choix de l’API ou du n° d’endpoint.
  4. Affichage minimal quand on fait un test d’endpoint :

    • On sépare bien l’adresse finale et les paramètres envoyés.
  5. Optionnel : Ajout d’un header "Accept": "application/json" par défaut (peut être enlevé si non nécessaire).


import sys import json import requests from groq import Groq # Stockage en mémoire des APIs (à adapter au besoin) apis_configurees = [] # Paramètre : longueur max avant de résumer MAX_CHARS_DIRECT_ANALYSIS = 3000 # --------------------------------------------------------------------------- # 1. Fonction de résumé (texte brut) si la doc est trop volumineuse def summarizer_groq(long_text, groq_api_key="gsk_XXXXXXXXXXXXXXX"): """ Découpe la documentation en chunks et génère un résumé global en langage naturel. Ceci n'utilise pas le mode JSON : on veut juste un résumé texte. """ client = Groq(api_key=groq_api_key) chunk_size = 3000 chunks = [] start = 0 while start < len(long_text): end = start + chunk_size chunks.append(long_text[start:end]) start = end summaries = [] for i, chunk_text in enumerate(chunks, start=1): print(f"[INFO] Résumé du chunk {i}/{len(chunks)}...") messages = [ { "role": "system", "content": ( "Tu es un assistant chargé de résumer la documentation d'API. " "Retourne un résumé concis (en langage courant) du texte fourni. " "Ne génère pas de JSON, pas de code, juste un texte résumé clair." ) }, { "role": "user", "content": chunk_text } ] try: completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.2, max_completion_tokens=1024, top_p=1, stream=False ) summary_text = completion.choices[0].message.content.strip() summaries.append(summary_text) except Exception as e: print(f"[ERREUR] Impossible de résumer le chunk {i} : {e}") summaries.append("") combined_summary = "\n".join(summaries) print(f"[INFO] Résumé global généré. Longueur du résumé : {len(combined_summary)} caractères.") return combined_summary # --------------------------------------------------------------------------- # 2. Fonction d'analyse finale en JSON def analyser_api_avec_groq(input_text, groq_api_key="gsk_XXXXXXXXXXXXXXXXXXX"): """ 1) Si le texte est trop long, on génère un résumé texte via summarizer_groq. 2) On passe ensuite (ou directement) le texte final dans un prompt qui demande un JSON strict, avec le schéma suivant : { "api_type": "REST | GraphQL | SOAP", "base_url": "string", "auth_info": { "type": "string (Bearer, Basic, etc.)", "key_name": "string", "required": true/false }, "common_headers": { "Header-Name": "Header-Value" }, "endpoints": [ { "name": "string", "path": "string", "method": "GET | POST | ...", "required_params": ["param1", "param2"], "optional_params": ["param1", "param2"], "description": "string" } ], "suggested_name": "string", "rate_limit": "string", "confidence_score": 0.0 } """ # 1) Résume si trop volumineux text_for_analysis = input_text if len(input_text) > MAX_CHARS_DIRECT_ANALYSIS: print("[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.") text_for_analysis = summarizer_groq(input_text, groq_api_key=groq_api_key) # 2) Appel Chat Completion en mode JSON client = Groq(api_key=groq_api_key) messages = [ { "role": "system", "content": ( "Tu es un assistant d'analyse d'API, tu dois répondre UNIQUEMENT en JSON valide, sans code superflu. " "Respecte le schéma JSON suivant (toutes les clés doivent exister) :\n\n" "{\n" " \"api_type\": \"REST | GraphQL | SOAP\",\n" " \"base_url\": \"string\",\n" " \"auth_info\": {\n" " \"type\": \"string (Bearer, Basic, etc.)\",\n" " \"key_name\": \"string\",\n" " \"required\": true/false\n" " },\n" " \"common_headers\": {\n" " \"Header-Name\": \"Header-Value\"\n" " },\n" " \"endpoints\": [\n" " {\n" " \"name\": \"string\",\n" " \"path\": \"string\",\n" " \"method\": \"GET | POST | ...\",\n" " \"required_params\": [\"param1\", \"param2\"],\n" " \"optional_params\": [\"param1\", \"param2\"],\n" " \"description\": \"string\"\n" " }\n" " ],\n" " \"suggested_name\": \"string\",\n" " \"rate_limit\": \"string\",\n" " \"confidence_score\": 0.0\n" "}\n\n" "Analyse le texte ci-après et renvoie STRICTEMENT un JSON conforme, sans texte additionnel." ) }, { "role": "user", "content": text_for_analysis } ] try: chat_completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.0, max_completion_tokens=1024, top_p=1, stream=False, response_format={"type": "json_object"} ) content = chat_completion.choices[0].message.content data = json.loads(content) return data except Exception as e: print(f"[ERREUR] Échec de la conversion en JSON : {e}") print("[INFO] Nous allons retourner un squelette par défaut.") return { "api_type": None, "base_url": None, "auth_info": { "type": None, "key_name": None, "required": False }, "common_headers": {}, "endpoints": [], "suggested_name": "API_Inconnue", "rate_limit": None, "confidence_score": 0.0 } # --------------------------------------------------------------------------- # 3. Fonctions du menu def ajouter_api(): print("=== Ajout d’une nouvelle API ===") # On ne se sert pas de la réponse (o/n) ici, mais on le laisse par cohérence. _ = input("Voulez-vous coller la documentation de l’API ? (o/n) : ") print("Collez la documentation ci-dessous (finissez par un skibidi vide) :") lignes_doc = [] while True: ligne = input() if ligne == "skibidi": break lignes_doc.append(ligne) doc_api = "\n".join(lignes_doc) # Simple fallback si rien n’est fourni if not doc_api.strip(): doc_api = "Pas d'information sur l'API." # Appel Groq pour analyse resultats_analyse = analyser_api_avec_groq(doc_api, groq_api_key="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") confidence_score = resultats_analyse.get("confidence_score", 0.0) if confidence_score < 0.5: print( "Le score de confiance de l’analyse est faible. " "Les informations retournées peuvent être partielles ou incorrectes.\n" ) # On lit les champs api_type = resultats_analyse.get("api_type") base_url = resultats_analyse.get("base_url") auth_info = resultats_analyse.get("auth_info", {}) common_headers = resultats_analyse.get("common_headers", {}) endpoints = resultats_analyse.get("endpoints", []) suggested_name = resultats_analyse.get("suggested_name", "NouvelleAPI") rate_limit = resultats_analyse.get("rate_limit") print(f"Nom suggéré pour l’API : {suggested_name}") nom_api = input(f"Entrez le nom de l’API ({suggested_name}) : ") if not nom_api.strip(): nom_api = suggested_name # Si auth_info.required == True, on demande la clé api_key_value = None if auth_info.get("required", False): api_key_value = input("Entrez la valeur de la clé API ou du token : ") # Construction de la config nouvelle_api = { "name": nom_api, "type": api_type, "base_url": base_url, "auth_info": auth_info, "api_key_value": api_key_value, "common_headers": common_headers, "endpoints": endpoints, "rate_limit": rate_limit } apis_configurees.append(nouvelle_api) print(f"\n[OK] L’API '{nom_api}' a été ajoutée.") print(f" - Type : {api_type}") print(f" - URL de base : {base_url}\n") def lister_apis(): print("=== Liste des API configurées ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return for i, api in enumerate(apis_configurees, start=1): print(f"{i}. Nom : {api['name']}") print(f" URL de base : {api['base_url'] or 'Non renseignée'}") print(f" Type : {api['type'] or 'Inconnu'}") if api["rate_limit"]: print(f" Limitation de débit : {api['rate_limit']}") if api["endpoints"]: print(" Endpoints :") for ep in api["endpoints"]: print(f" - {ep['name']} ({ep['method']} {ep['path']})") else: print(" Aucun endpoint configuré.") print() print() def modifier_api(): print("=== Modification d’une API ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return # On affiche la liste for i, api in enumerate(apis_configurees, start=1): print(f"{i}. {api['name']}") choix = input("Quelle API souhaitez-vous modifier ? (nom ou numéro) : ") api_choisie = None # On tente un cast en int pour voir si c’est un numéro try: idx = int(choix) - 1 if 0 <= idx < len(apis_configurees): api_choisie = apis_configurees[idx] except ValueError: # Sinon, on tente par nom for a in apis_configurees: if a["name"].lower() == choix.lower(): api_choisie = a break if not api_choisie: print("API introuvable.\n") return print(f"\nAPI sélectionnée : {api_choisie['name']}") print("Que voulez-vous modifier ? (ex: 'changer l'URL de base', 'changer la clé API', " "'ajouter un endpoint', 'modifier un endpoint', 'supprimer un endpoint')") action = input("> ").lower() if "url" in action: new_url = input("Nouvelle URL de base : ") api_choisie["base_url"] = new_url print("URL de base modifiée.\n") if "clé" in action or "key" in action: new_key = input("Nouvelle clé API : ") api_choisie["api_key_value"] = new_key print("Clé API modifiée.\n") if "ajouter un endpoint" in action: print("=== Ajout d'un endpoint ===") nom_ep = input("Nom du nouvel endpoint : ") path_ep = input("Chemin (ex: /playlists/{playlist_id}/tracks) : ") methode = input("Méthode HTTP (GET, POST, etc.) : ") params_req = [p.strip() for p in input("Paramètres requis (séparés par des virgules) : ").split(",") if p.strip()] params_opt = [p.strip() for p in input("Paramètres optionnels (séparés par des virgules) : ").split(",") if p.strip()] new_ep = { "name": nom_ep, "path": path_ep, "method": methode.upper(), "required_params": params_req, "optional_params": params_opt, "description": "" } api_choisie["endpoints"].append(new_ep) print(f"Endpoint '{nom_ep}' ajouté.\n") if "modifier un endpoint" in action: print("=== Modification d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à modifier.") return for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = input("Quel endpoint ? (numéro ou nom) : ") ep_choisi = None try: eidx = int(choix_ep) - 1 if 0 <= eidx < len(api_choisie["endpoints"]): ep_choisi = api_choisie["endpoints"][eidx] except ValueError: for ep in api_choisie["endpoints"]: if ep["name"].lower() == choix_ep.lower(): ep_choisi = ep break if not ep_choisi: print("Endpoint introuvable.") return print(f"Endpoint sélectionné : {ep_choisi['name']}") modif_ep = input("Que voulez-vous faire ? (ex: 'ajouter un paramètre', 'changer la méthode', etc.) : ").lower() if "ajouter un paramètre" in modif_ep: nom_p = input("Nom du paramètre : ") r_o = input("Paramètre requis ou optionnel ? (r/o) : ") if r_o.lower() == 'r': ep_choisi["required_params"].append(nom_p) else: ep_choisi["optional_params"].append(nom_p) print(f"Paramètre '{nom_p}' ajouté.\n") # D’autres modifications possibles... if "supprimer un endpoint" in action: print("=== Suppression d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à supprimer.") return for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = input("Quel endpoint supprimer ? (numéro ou nom) : ") ep_asup = None try: eidx = int(choix_ep) - 1 if 0 <= eidx < len(api_choisie["endpoints"]): ep_asup = api_choisie["endpoints"][eidx] except ValueError: for ep in api_choisie["endpoints"]: if ep["name"].lower() == choix_ep.lower(): ep_asup = ep break if ep_asup: api_choisie["endpoints"].remove(ep_asup) print(f"Endpoint '{ep_asup['name']}' supprimé.") else: print("Endpoint introuvable.") print("Modification(s) terminée(s).\n") def supprimer_api(): print("=== Suppression d’une API ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return for i, api in enumerate(apis_configurees, start=1): print(f"{i}. {api['name']}") choix = input("Quelle API supprimer ? (nom ou numéro) : ") api_asup = None try: idx = int(choix) - 1 if 0 <= idx < len(apis_configurees): api_asup = apis_configurees[idx] except ValueError: for a in apis_configurees: if a["name"].lower() == choix.lower(): api_asup = a break if not api_asup: print("API introuvable.\n") return confirm = input(f"Êtes-vous sûr de vouloir supprimer '{api_asup['name']}' ? (o/n) : ") if confirm.lower() == 'o': apis_configurees.remove(api_asup) print(f"L’API '{api_asup['name']}' a été supprimée.\n") else: print("Opération annulée.\n") def tester_endpoint(): print("=== Tester un endpoint ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return for i, api in enumerate(apis_configurees, start=1): print(f"{i}. {api['name']}") choix = input("Sur quelle API tester un endpoint ? (nom ou numéro) : ") api_choisie = None try: idx = int(choix) - 1 if 0 <= idx < len(apis_configurees): api_choisie = apis_configurees[idx] except ValueError: for a in apis_configurees: if a["name"].lower() == choix.lower(): api_choisie = a break if not api_choisie: print("API introuvable.\n") return if not api_choisie["endpoints"]: print("Cette API n’a aucun endpoint configuré.\n") return print(f"Endpoints disponibles pour {api_choisie['name']} :") for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = input("Quel endpoint tester ? (nom ou numéro) : ") ep_choisi = None try: eidx = int(choix_ep) - 1 if 0 <= eidx < len(api_choisie["endpoints"]): ep_choisi = api_choisie["endpoints"][eidx] except ValueError: for ep in api_choisie["endpoints"]: if ep["name"].lower() == choix_ep.lower(): ep_choisi = ep break if not ep_choisi: print("Endpoint introuvable.") return # On va demander les valeurs pour chaque param requis required_params_values = {} for rp in ep_choisi.get("required_params", []): val = input(f"Entrez la valeur pour '{rp}' : ") required_params_values[rp] = val # On va demander les valeurs pour chaque param optionnel optional_params_values = {} for op in ep_choisi.get("optional_params", []): val = input(f"Valeur pour '{op}' (laisser vide si aucun) : ") if val: optional_params_values[op] = val # Préparation de l’URL base_url = api_choisie.get("base_url") or "" path = ep_choisi["path"] # Remplacement dans le path si on a des placeholders {param} # et retrait du param si on a pu le remplacer query_params = {} for k, v in required_params_values.items(): placeholder = f"{{{k}}}" if placeholder in path: path = path.replace(placeholder, v) else: # S'il n'y a pas de placeholder correspondant, on le mettra en query param query_params[k] = v # Tous les optionnels vont en query params query_params.update(optional_params_values) # Gestion de l’authentification headers = dict(api_choisie.get("common_headers", {})) # Ex : on force "Accept: application/json" par défaut (ou non) if "Accept" not in headers: headers["Accept"] = "application/json" auth_info = api_choisie.get("auth_info", {}) api_key_value = api_choisie.get("api_key_value") if auth_info.get("required") and api_key_value: # Exemple : si c’est un Bearer if auth_info["type"] and "bearer" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Bearer {api_key_value}" # Exemple : si c’est un Basic elif auth_info["type"] and "basic" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Basic {api_key_value}" else: # Si key_name = "api_key", NASA veut un query param "api_key=XXXX" if auth_info.get("key_name", "").lower() == "api_key": query_params["api_key"] = api_key_value else: # Sinon on le place dans un header key_name = auth_info.get("key_name", "X-API-Key") headers[key_name] = api_key_value # Construction de l'URL finale url = base_url + path method = ep_choisi["method"].upper() print(f"\nTest de l'endpoint : {method} {url}") print(f"En-têtes : {headers}") print(f"Paramètres : {query_params}\n") try: if method == "GET": r = requests.get(url, headers=headers, params=query_params) elif method == "POST": # On envoie ici en JSON, à adapter si l’API l’exige autrement r = requests.post(url, headers=headers, json=query_params) elif method == "PUT": r = requests.put(url, headers=headers, json=query_params) elif method == "DELETE": r = requests.delete(url, headers=headers, json=query_params) else: print("Méthode non gérée.") return print(f"Statut : {r.status_code}") # Tentative de parsing JSON try: print("Réponse JSON :") print(json.dumps(r.json(), indent=2)) except: print("Réponse brute :") print(r.text) except Exception as e: print(f"Erreur lors de l’appel : {e}") def main(): while True: print("=== Menu Principal ===") print("1. Ajouter une API (assisté par IA)") print("2. Liste des API configurées") print("3. Modifier une API") print("4. Supprimer une API") print("5. Tester un endpoint") print("6. Quitter") choix = input("Choisissez une option : ").strip() # On essaie de caster en int pour éviter l'erreur # s'il tape '5xK9...' par inadvertance try: choix_num = int(choix) except ValueError: print("Choix invalide.\n") continue if choix_num == 1: ajouter_api() elif choix_num == 2: lister_apis() elif choix_num == 3: modifier_api() elif choix_num == 4: supprimer_api() elif choix_num == 5: tester_endpoint() elif choix_num == 6: print("Au revoir.") sys.exit(0) else: print("Choix invalide.\n") if __name__ == "__main__": main()

Explications des points clés

  1. Transmission de la clé API NASA :

    • Dans l’exemple de la NASA, l’auth_info ressemble à :
      { "type": "", "key_name": "api_key", "required": true }
    • Lors de l’ajout, l’utilisateur a saisi la clé NASA. On la stocke dans api["api_key_value"].
    • Au moment de tester l’endpoint, on voit que key_name = "api_key". Donc on insère "api_key": "<LA_CLE>" dans query_params.
    • Résultat final : la requête se fera en GET avec ?api_key=<LA_CLE>.
  2. Placeholders dans le path (ex. "/neo/rest/v1/neo/{asteroid_id}") :

    • S’il y a un paramètre requis qui s’appelle asteroid_id, on remplace "{asteroid_id}" dans l’URL par la valeur saisie.
    • Si le placeholder n’existe pas dans le path, on l’envoie en paramètre de query.
  3. Robustesse du menu :

    • On fait un try/except ValueError pour s’assurer que la saisie est bien un entier. Si ce n’est pas le cas, on réaffiche le menu.
  4. En-tête Accept: application/json ajouté par défaut, pour faciliter le parsing des réponses JSON.

En l’état, ce script devrait mieux gérer le cas de la NASA (et d’autres APIs) et éviter l’erreur No api_key was supplied puisque la clé sera maintenant passée dans la query string.

질문

c'est censé être le point d'interogration mais ça ne me configure pas le bon type fait en sorte que la verificaztion des types soit plus poussé

사고

Enriching input validation

I'm thinking of enhancing input validation in the main menu by using regex to identify and manage non-integer or unclear inputs, like '?' or phrases in another language.

Validating input robustness

I’m outlining a Python function to sequentially trim input, check for help requests, and parse it as an integer. If the integer isn't within 1 to 6, an error message is shown.

Enhancing input robustness

Crafting a function to read user choices between 1 and 6, retrying if invalid or on help requests, ensures reliable input validation for various commands.

Thought about API type verification pendant 18 secondes

답변

Voici une version améliorée qui effectue une vérification plus stricte des choix dans le menu principal (et dans d’autres parties), notamment pour éviter qu’un simple point d’interrogation ou une saisie non numérique provoque une erreur ou soit interprété comme un entier.

Principaux changements

  1. Fonction lire_int_in_range :

    • Permet de lire un entier dans une plage définie [minval..maxval][min_val..max_val].
    • Affiche un message d'erreur et repose la question si la saisie n’est pas un entier ou si elle sort de la plage autorisée.
    • Permet de gérer les cas où l’utilisateur tape « ? » (ou un autre caractère) pour afficher un message d’aide ou simplement éviter l’erreur.
  2. Utilisation de lire_int_in_range :

    • Dans le menu principal (main()), au lieu de faire un simple input() + try/except ValueError, on appelle lire_int_in_range.
    • On peut faire la même chose pour le choix de l’API à modifier/supprimer ou le choix de l’endpoint à tester, afin d’éviter qu’un point d’interrogation ou tout autre texte ne casse la logique.
  3. Exemple d’aide si user_input == '?' :

    • Dans l’exemple ci-dessous, si l’utilisateur tape « ? » quand on lui demande un choix de menu, on affiche un petit texte d’aide (modifiable à volonté).
    • Vous pouvez adapter ce comportement : parfois on veut juste ignorer le « ? », ou proposer un menu d’aide plus riche.
  4. Validation du type d’API (optionnel) :

    • Vous pouvez également, si vous le souhaitez, vérifier que api_type est bien "REST", "GraphQL" ou "SOAP" quand Groq vous le fournit (ou quand vous le modifiez). Mais cela dépend de votre usage : ce n’est pas toujours nécessaire.

import sys import json import requests from groq import Groq # Stockage en mémoire des APIs (à adapter au besoin) apis_configurees = [] # Paramètre : longueur max avant de résumer MAX_CHARS_DIRECT_ANALYSIS = 3000 # --------------------------------------------------------------------------- # 1. Fonction de résumé (texte brut) si la doc est trop volumineuse def summarizer_groq(long_text, groq_api_key="gsk_XXXXXXXXXXXXXXX"): """ Découpe la documentation en chunks et génère un résumé global en langage naturel. Ceci n'utilise pas le mode JSON : on veut juste un résumé texte. """ client = Groq(api_key=groq_api_key) chunk_size = 3000 chunks = [] start = 0 while start < len(long_text): end = start + chunk_size chunks.append(long_text[start:end]) start = end summaries = [] for i, chunk_text in enumerate(chunks, start=1): print(f"[INFO] Résumé du chunk {i}/{len(chunks)}...") messages = [ { "role": "system", "content": ( "Tu es un assistant chargé de résumer la documentation d'API. " "Retourne un résumé concis (en langage courant) du texte fourni. " "Ne génère pas de JSON, pas de code, juste un texte résumé clair." ) }, { "role": "user", "content": chunk_text } ] try: completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.2, max_completion_tokens=1024, top_p=1, stream=False ) summary_text = completion.choices[0].message.content.strip() summaries.append(summary_text) except Exception as e: print(f"[ERREUR] Impossible de résumer le chunk {i} : {e}") summaries.append("") combined_summary = "\n".join(summaries) print(f"[INFO] Résumé global généré. Longueur du résumé : {len(combined_summary)} caractères.") return combined_summary # --------------------------------------------------------------------------- # 2. Fonction d'analyse finale en JSON def analyser_api_avec_groq(input_text, groq_api_key="gsk_XXXXXXXXXXXXXXXXXXX"): """ 1) Si le texte est trop long, on génère un résumé texte via summarizer_groq. 2) On passe ensuite (ou directement) le texte final dans un prompt qui demande un JSON strict (voir schéma ci-dessous). """ # 1) Résume si trop volumineux text_for_analysis = input_text if len(input_text) > MAX_CHARS_DIRECT_ANALYSIS: print("[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.") text_for_analysis = summarizer_groq(input_text, groq_api_key=groq_api_key) # 2) Appel Chat Completion en mode JSON client = Groq(api_key=groq_api_key) messages = [ { "role": "system", "content": ( "Tu es un assistant d'analyse d'API, tu dois répondre UNIQUEMENT en JSON valide, sans code superflu. " "Respecte le schéma JSON suivant (toutes les clés doivent exister) :\n\n" "{\n" " \"api_type\": \"REST | GraphQL | SOAP\",\n" " \"base_url\": \"string\",\n" " \"auth_info\": {\n" " \"type\": \"string (Bearer, Basic, etc.)\",\n" " \"key_name\": \"string\",\n" " \"required\": true/false\n" " },\n" " \"common_headers\": {\n" " \"Header-Name\": \"Header-Value\"\n" " },\n" " \"endpoints\": [\n" " {\n" " \"name\": \"string\",\n" " \"path\": \"string\",\n" " \"method\": \"GET | POST | ...\",\n" " \"required_params\": [\"param1\", \"param2\"],\n" " \"optional_params\": [\"param1\", \"param2\"],\n" " \"description\": \"string\"\n" " }\n" " ],\n" " \"suggested_name\": \"string\",\n" " \"rate_limit\": \"string\",\n" " \"confidence_score\": 0.0\n" "}\n\n" "Analyse le texte ci-après et renvoie STRICTEMENT un JSON conforme, sans texte additionnel." ) }, { "role": "user", "content": text_for_analysis } ] try: chat_completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.0, max_completion_tokens=1024, top_p=1, stream=False, response_format={"type": "json_object"} ) content = chat_completion.choices[0].message.content data = json.loads(content) return data except Exception as e: print(f"[ERREUR] Échec de la conversion en JSON : {e}") print("[INFO] Nous allons retourner un squelette par défaut.") return { "api_type": None, "base_url": None, "auth_info": { "type": None, "key_name": None, "required": False }, "common_headers": {}, "endpoints": [], "suggested_name": "API_Inconnue", "rate_limit": None, "confidence_score": 0.0 } # --------------------------------------------------------------------------- # 3. FONCTIONS D’OUTIL POUR L’INTERFACE def lire_int_in_range(prompt: str, min_val: int, max_val: int) -> int: """ Demande à l'utilisateur de saisir un entier dans la plage [min_val..max_val]. Si l'utilisateur saisit '?', on affiche un petit message d'aide (personnalisable). Répète la question tant que la valeur n'est pas un entier correct. Retourne l'entier validé. """ while True: saisie = input(prompt).strip() # Exemple de gestion d'un '?' ou autre commande spéciale if saisie == "?": print("Aide : veuillez saisir un entier compris entre " f"{min_val} et {max_val}.") print("Tapez un nombre valide, ou Ctrl+C pour annuler.") continue # Sinon, on tente la conversion try: val = int(saisie) if min_val <= val <= max_val: return val else: print(f"Choix invalide (doit être entre {min_val} et {max_val}).\n") except ValueError: print("Choix invalide (entrez un nombre). Réessayez.\n") def selectionner_api() -> dict: """ Affiche la liste des API configurées, demande à l'utilisateur d'en choisir une par numéro. Retourne le dict correspondant ou None si aucune API. """ if not apis_configurees: print("Aucune API n’est configurée.\n") return None print("=== Liste des APIs disponibles ===") for i, api in enumerate(apis_configurees, start=1): print(f"{i}. {api['name']}") # On lit un choix (numéro) dans la plage [1..len(apis_configurees)] choix_num = lire_int_in_range( prompt=f"Quelle API souhaitez-vous sélectionner ? [1..{len(apis_configurees)}] : ", min_val=1, max_val=len(apis_configurees) ) return apis_configurees[choix_num - 1] def selectionner_endpoint(api: dict) -> dict: """ Affiche la liste des endpoints pour l'API donnée, demande à l'utilisateur d'en choisir un par numéro. Retourne le dict correspondant ou None si aucun endpoint. """ if not api["endpoints"]: print("Cette API n’a aucun endpoint configuré.\n") return None print(f"Endpoints disponibles pour {api['name']} :") for i, ep in enumerate(api["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep_num = lire_int_in_range( prompt=f"Quel endpoint tester ? [1..{len(api['endpoints'])}] : ", min_val=1, max_val=len(api["endpoints"]) ) return api["endpoints"][choix_ep_num - 1] # --------------------------------------------------------------------------- # 4. Fonctions du menu def ajouter_api(): print("=== Ajout d’une nouvelle API ===") _ = input("Voulez-vous coller la documentation de l’API ? (o/n) : ") print("Collez la documentation ci-dessous (finissez par un skibidi vide) :") lignes_doc = [] while True: ligne = input() if ligne == "skibidi": break lignes_doc.append(ligne) doc_api = "\n".join(lignes_doc) if not doc_api.strip(): doc_api = "Pas d'information sur l'API." # Appel Groq pour analyse resultats_analyse = analyser_api_avec_groq(doc_api, groq_api_key="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") confidence_score = resultats_analyse.get("confidence_score", 0.0) if confidence_score < 0.5: print( "Le score de confiance de l’analyse est faible. " "Les informations retournées peuvent être partielles ou incorrectes.\n" ) # Champs retournés api_type = resultats_analyse.get("api_type") base_url = resultats_analyse.get("base_url") auth_info = resultats_analyse.get("auth_info", {}) common_headers = resultats_analyse.get("common_headers", {}) endpoints = resultats_analyse.get("endpoints", []) suggested_name = resultats_analyse.get("suggested_name", "NouvelleAPI") rate_limit = resultats_analyse.get("rate_limit") print(f"Nom suggéré pour l’API : {suggested_name}") nom_api = input(f"Entrez le nom de l’API ({suggested_name}) : ") if not nom_api.strip(): nom_api = suggested_name # Si auth_info.required == True, on demande la clé api_key_value = None if auth_info.get("required", False): api_key_value = input("Entrez la valeur de la clé API ou du token : ") # Construction de la config nouvelle_api = { "name": nom_api, "type": api_type, "base_url": base_url, "auth_info": auth_info, "api_key_value": api_key_value, "common_headers": common_headers, "endpoints": endpoints, "rate_limit": rate_limit } apis_configurees.append(nouvelle_api) print(f"\n[OK] L’API '{nom_api}' a été ajoutée.") print(f" - Type : {api_type}") print(f" - URL de base : {base_url}\n") def lister_apis(): print("=== Liste des API configurées ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return for i, api in enumerate(apis_configurees, start=1): print(f"{i}. Nom : {api['name']}") print(f" URL de base : {api['base_url'] or 'Non renseignée'}") print(f" Type : {api['type'] or 'Inconnu'}") if api["rate_limit"]: print(f" Limitation de débit : {api['rate_limit']}") if api["endpoints"]: print(" Endpoints :") for ep in api["endpoints"]: print(f" - {ep['name']} ({ep['method']} {ep['path']})") else: print(" Aucun endpoint configuré.") print() print() def modifier_api(): print("=== Modification d’une API ===") api_choisie = selectionner_api() if not api_choisie: return print(f"\nAPI sélectionnée : {api_choisie['name']}") print("Que voulez-vous modifier ? (ex: 'changer l'URL de base', 'changer la clé API', " "'ajouter un endpoint', 'modifier un endpoint', 'supprimer un endpoint')") action = input("> ").lower() if "url" in action: new_url = input("Nouvelle URL de base : ") api_choisie["base_url"] = new_url print("URL de base modifiée.\n") if "clé" in action or "key" in action: new_key = input("Nouvelle clé API : ") api_choisie["api_key_value"] = new_key print("Clé API modifiée.\n") if "ajouter un endpoint" in action: print("=== Ajout d'un endpoint ===") nom_ep = input("Nom du nouvel endpoint : ") path_ep = input("Chemin (ex: /playlists/{playlist_id}/tracks) : ") methode = input("Méthode HTTP (GET, POST, etc.) : ") params_req = [p.strip() for p in input("Paramètres requis (séparés par des virgules) : ").split(",") if p.strip()] params_opt = [p.strip() for p in input("Paramètres optionnels (séparés par des virgules) : ").split(",") if p.strip()] new_ep = { "name": nom_ep, "path": path_ep, "method": methode.upper(), "required_params": params_req, "optional_params": params_opt, "description": "" } api_choisie["endpoints"].append(new_ep) print(f"Endpoint '{nom_ep}' ajouté.\n") if "modifier un endpoint" in action: print("=== Modification d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à modifier.") return print("Liste des endpoints :") for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = lire_int_in_range( f"Quel endpoint modifier ? [1..{len(api_choisie['endpoints'])}] : ", 1, len(api_choisie["endpoints"]) ) ep_choisi = api_choisie["endpoints"][choix_ep - 1] print(f"Endpoint sélectionné : {ep_choisi['name']}") modif_ep = input("Que voulez-vous faire ? (ex: 'ajouter un paramètre', 'changer la méthode', etc.) : ").lower() if "ajouter un paramètre" in modif_ep: nom_p = input("Nom du paramètre : ") r_o = input("Paramètre requis ou optionnel ? (r/o) : ") if r_o.lower() == 'r': ep_choisi["required_params"].append(nom_p) else: ep_choisi["optional_params"].append(nom_p) print(f"Paramètre '{nom_p}' ajouté.\n") # D’autres modifications possibles... if "supprimer un endpoint" in action: print("=== Suppression d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à supprimer.") return print("Liste des endpoints :") for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = lire_int_in_range( f"Quel endpoint supprimer ? [1..{len(api_choisie['endpoints'])}] : ", 1, len(api_choisie["endpoints"]) ) ep_asup = api_choisie["endpoints"][choix_ep - 1] api_choisie["endpoints"].remove(ep_asup) print(f"Endpoint '{ep_asup['name']}' supprimé.") print("Modification(s) terminée(s).\n") def supprimer_api(): print("=== Suppression d’une API ===") api_choisie = selectionner_api() if not api_choisie: return confirm = input(f"Êtes-vous sûr de vouloir supprimer '{api_choisie['name']}' ? (o/n) : ") if confirm.lower() == 'o': apis_configurees.remove(api_choisie) print(f"L’API '{api_choisie['name']}' a été supprimée.\n") else: print("Opération annulée.\n") def tester_endpoint(): print("=== Tester un endpoint ===") api_choisie = selectionner_api() if not api_choisie: return ep_choisi = selectionner_endpoint(api_choisie) if not ep_choisi: return # On va demander les valeurs pour chaque param requis required_params_values = {} for rp in ep_choisi.get("required_params", []): val = input(f"Entrez la valeur pour '{rp}' : ") required_params_values[rp] = val # On va demander les valeurs pour chaque param optionnel optional_params_values = {} for op in ep_choisi.get("optional_params", []): val = input(f"Valeur pour '{op}' (laisser vide si aucun) : ") if val: optional_params_values[op] = val # Préparation de l’URL base_url = api_choisie.get("base_url") or "" path = ep_choisi["path"] # Remplacement dans le path si on a des placeholders {param} # et retrait du param si on a pu le remplacer query_params = {} for k, v in required_params_values.items(): placeholder = f"{{{k}}}" if placeholder in path: path = path.replace(placeholder, v) else: # S'il n'y a pas de placeholder correspondant, on le mettra en query param query_params[k] = v # Tous les optionnels vont en query params query_params.update(optional_params_values) # Gestion de l’authentification headers = dict(api_choisie.get("common_headers", {})) if "Accept" not in headers: headers["Accept"] = "application/json" auth_info = api_choisie.get("auth_info", {}) api_key_value = api_choisie.get("api_key_value") if auth_info.get("required") and api_key_value: # Exemple : si c’est un Bearer if auth_info["type"] and "bearer" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Bearer {api_key_value}" # Exemple : si c’est un Basic elif auth_info["type"] and "basic" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Basic {api_key_value}" else: # Si key_name = "api_key", NASA veut un query param "api_key=XXXX" if auth_info.get("key_name", "").lower() == "api_key": query_params["api_key"] = api_key_value else: # Sinon on le place dans un header key_name = auth_info.get("key_name", "X-API-Key") headers[key_name] = api_key_value # Construction de l'URL finale url = base_url + path method = ep_choisi["method"].upper() print(f"\nTest de l'endpoint : {method} {url}") print(f"En-têtes : {headers}") print(f"Paramètres : {query_params}\n") try: if method == "GET": r = requests.get(url, headers=headers, params=query_params) elif method == "POST": r = requests.post(url, headers=headers, json=query_params) elif method == "PUT": r = requests.put(url, headers=headers, json=query_params) elif method == "DELETE": r = requests.delete(url, headers=headers, json=query_params) else: print("Méthode non gérée.") return print(f"Statut : {r.status_code}") try: print("Réponse JSON :") print(json.dumps(r.json(), indent=2)) except: print("Réponse brute :") print(r.text) except Exception as e: print(f"Erreur lors de l’appel : {e}") # --------------------------------------------------------------------------- # 5. MAIN def main(): while True: print("=== Menu Principal ===") print("1. Ajouter une API (assisté par IA)") print("2. Liste des API configurées") print("3. Modifier une API") print("4. Supprimer une API") print("5. Tester un endpoint") print("6. Quitter") choix_num = lire_int_in_range("Choisissez une option [1..6] : ", 1, 6) if choix_num == 1: ajouter_api() elif choix_num == 2: lister_apis() elif choix_num == 3: modifier_api() elif choix_num == 4: supprimer_api() elif choix_num == 5: tester_endpoint() elif choix_num == 6: print("Au revoir.") sys.exit(0) if __name__ == "__main__": main()

Comment ça marche ?

  • Lecture sécurisée des choix : La fonction lire_int_in_range vous évite de devoir gérer manuellement les try/except partout. Elle boucle jusqu’à obtenir un entier valide dans la fourchette souhaitée.
  • Gestion du « ? » : Si l’utilisateur tape « ? » à la place d’un chiffre, on lui affiche un message d’aide puis on redemande la saisie. Vous pouvez modifier ce comportement (par exemple, afficher plus de détails).
  • Choix d’une API et Choix d’un endpoint : On utilise la même logique pour afficher la liste et demander un numéro (au lieu de laisser l’utilisateur saisir un nom ou un numéro indistinctement).
  • Robustesse globale : Toute valeur hors plage ou non numérique re-déclenche la demande plutôt qu’une exception.

De cette manière, si l’utilisateur tape un point d’interrogation ou une chaîne non prévue, on ne casse pas le programme : on l’informe juste que c’est invalide, et on le redirige vers une nouvelle saisie.

질문

fait en sorte que les apis que j'ajoute sois sauvegarder dans un json
import sys
import json
import requests

from groq import Groq

# Stockage en mémoire des APIs (à adapter au besoin)
apis_configurees = []

# Paramètre : longueur max avant de résumer
MAX_CHARS_DIRECT_ANALYSIS = 3000

# ---------------------------------------------------------------------------
# 1. Fonction de résumé (texte brut) si la doc est trop volumineuse
def summarizer_groq(long_text, groq_api_key="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"):
"""
Découpe la documentation en chunks et génère un résumé global en langage naturel.
Ceci n'utilise pas le mode JSON : on veut juste un résumé texte.
"""
client = Groq(api_key=groq_api_key)

chunk_size = 3000
chunks = []
start = 0
while start < len(long_text):
end = start + chunk_size
chunks.append(long_text[start:end])
start = end

summaries = []
for i, chunk_text in enumerate(chunks, start=1):
print(f"[INFO] Résumé du chunk {i}/{len(chunks)}...")
messages = [
{
"role": "system",
"content": (
"Tu es un assistant chargé de résumer la documentation d'API. "
"Retourne un résumé concis (en langage courant) du texte fourni. "
"Ne génère pas de JSON, pas de code, juste un texte résumé clair."
)
},
{
"role": "user",
"content": chunk_text
}
]
try:
completion = client.chat.completions.create(
messages=messages,
model="llama-3.3-70b-versatile",
temperature=0.2,
max_completion_tokens=1024,
top_p=1,
stream=False
)
summary_text = completion.choices[0].message.content.strip()
summaries.append(summary_text)
except Exception as e:
print(f"[ERREUR] Impossible de résumer le chunk {i} : {e}")
summaries.append("")

combined_summary = "\n".join(summaries)
print(f"[INFO] Résumé global généré. Longueur du résumé : {len(combined_summary)} caractères.")
return combined_summary


# ---------------------------------------------------------------------------
# 2. Fonction d'analyse finale en JSON
def analyser_api_avec_groq(input_text, groq_api_key="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"):
"""
1) Si le texte est trop long, on génère un résumé texte via summarizer_groq.
2) On passe ensuite (ou directement) le texte final dans un prompt
qui demande un JSON strict (voir schéma ci-dessous).
"""
# 1) Résume si trop volumineux
text_for_analysis = input_text
if len(input_text) > MAX_CHARS_DIRECT_ANALYSIS:
print("[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.")
text_for_analysis = summarizer_groq(input_text, groq_api_key=groq_api_key)

# 2) Appel Chat Completion en mode JSON
client = Groq(api_key=groq_api_key)

messages = [
{
"role": "system",
"content": (
"Tu es un assistant d'analyse d'API, tu dois répondre UNIQUEMENT en JSON valide, sans code superflu. "
"Respecte le schéma JSON suivant (toutes les clés doivent exister) :\n\n"
"{\n"
" \"api_type\": \"REST | GraphQL | SOAP\",\n"
" \"base_url\": \"string\",\n"
" \"auth_info\": {\n"
" \"type\": \"string (Bearer, Basic, etc.)\",\n"
" \"key_name\": \"string\",\n"
" \"required\": true/false\n"
" },\n"
" \"common_headers\": {\n"
" \"Header-Name\": \"Header-Value\"\n"
" },\n"
" \"endpoints\": [\n"
" {\n"
" \"name\": \"string\",\n"
" \"path\": \"string\",\n"
" \"method\": \"GET | POST | ...\",\n"
" \"required_params\": [\"param1\", \"param2\"],\n"
" \"optional_params\": [\"param1\", \"param2\"],\n"
" \"description\": \"string\"\n"
" }\n"
" ],\n"
" \"suggested_name\": \"string\",\n"
" \"rate_limit\": \"string\",\n"
" \"confidence_score\": 0.0\n"
"}\n\n"
"Analyse le texte ci-après et renvoie STRICTEMENT un JSON conforme, sans texte additionnel."
)
},
{
"role": "user",
"content": text_for_analysis
}
]

try:
chat_completion = client.chat.completions.create(
messages=messages,
model="llama-3.3-70b-versatile",
temperature=0.0,
max_completion_tokens=1024,
top_p=1,
stream=False,
response_format={"type": "json_object"}
)
content = chat_completion.choices[0].message.content
data = json.loads(content)
return data

except Exception as e:
print(f"[ERREUR] Échec de la conversion en JSON : {e}")
print("[INFO] Nous allons retourner un squelette par défaut.")
return {
"api_type": None,
"base_url": None,
"auth_info": {
"type": None,
"key_name": None,
"required": False
},
"common_headers": {},
"endpoints": [],
"suggested_name": "API_Inconnue",
"rate_limit": None,
"confidence_score": 0.0
}

# ---------------------------------------------------------------------------
# 3. FONCTIONS D’OUTIL POUR L’INTERFACE

def lire_int_in_range(prompt: str, min_val: int, max_val: int) -> int:
"""
Demande à l'utilisateur de saisir un entier dans la plage [min_val..max_val].
Si l'utilisateur saisit '?', on affiche un petit message d'aide (personnalisable).
Répète la question tant que la valeur n'est pas un entier correct.
Retourne l'entier validé.
"""
while True:
saisie = input(prompt).strip()

# Exemple de gestion d'un '?' ou autre commande spéciale
if saisie == "?":
print("Aide : veuillez saisir un entier compris entre "
f"{min_val} et {max_val}.")
print("Tapez un nombre valide, ou Ctrl+C pour annuler.")
continue

# Sinon, on tente la conversion
try:
val = int(saisie)
if min_val <= val <= max_val:
return val
else:
print(f"Choix invalide (doit être entre {min_val} et {max_val}).\n")
except ValueError:
print("Choix invalide (entrez un nombre). Réessayez.\n")


def selectionner_api() -> dict:
"""
Affiche la liste des API configurées, demande à l'utilisateur d'en choisir
une par numéro. Retourne le dict correspondant ou None si aucune API.
"""
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return None

print("=== Liste des APIs disponibles ===")
for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. {api['name']}")

# On lit un choix (numéro) dans la plage [1..len(apis_configurees)]
choix_num = lire_int_in_range(
prompt=f"Quelle API souhaitez-vous sélectionner ? [1..{len(apis_configurees)}] : ",
min_val=1,
max_val=len(apis_configurees)
)
return apis_configurees[choix_num - 1]


def selectionner_endpoint(api: dict) -> dict:
"""
Affiche la liste des endpoints pour l'API donnée, demande à l'utilisateur
d'en choisir un par numéro. Retourne le dict correspondant ou None si aucun endpoint.
"""
if not api["endpoints"]:
print("Cette API n’a aucun endpoint configuré.\n")
return None

print(f"Endpoints disponibles pour {api['name']} :")
for i, ep in enumerate(api["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")

choix_ep_num = lire_int_in_range(
prompt=f"Quel endpoint tester ? [1..{len(api['endpoints'])}] : ",
min_val=1,
max_val=len(api["endpoints"])
)
return api["endpoints"][choix_ep_num - 1]


# ---------------------------------------------------------------------------
# 4. Fonctions du menu

def ajouter_api():
print("=== Ajout d’une nouvelle API ===")

_ = input("Voulez-vous coller la documentation de l’API ? (o/n) : ")
print("Collez la documentation ci-dessous (finissez par un skibidi vide) :")

lignes_doc = []
while True:
ligne = input()
if ligne == "skibidi":
break
lignes_doc.append(ligne)
doc_api = "\n".join(lignes_doc)

if not doc_api.strip():
doc_api = "Pas d'information sur l'API."

# Appel Groq pour analyse
resultats_analyse = analyser_api_avec_groq(doc_api, groq_api_key="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")

confidence_score = resultats_analyse.get("confidence_score", 0.0)
if confidence_score < 0.5:
print(
"Le score de confiance de l’analyse est faible. "
"Les informations retournées peuvent être partielles ou incorrectes.\n"
)

# Champs retournés
api_type = resultats_analyse.get("api_type")
base_url = resultats_analyse.get("base_url")
auth_info = resultats_analyse.get("auth_info", {})
common_headers = resultats_analyse.get("common_headers", {})
endpoints = resultats_analyse.get("endpoints", [])
suggested_name = resultats_analyse.get("suggested_name", "NouvelleAPI")
rate_limit = resultats_analyse.get("rate_limit")

print(f"Nom suggéré pour l’API : {suggested_name}")
nom_api = input(f"Entrez le nom de l’API ({suggested_name}) : ")
if not nom_api.strip():
nom_api = suggested_name

# Si auth_info.required == True, on demande la clé
api_key_value = None
if auth_info.get("required", False):
api_key_value = input("Entrez la valeur de la clé API ou du token : ")

# Construction de la config
nouvelle_api = {
"name": nom_api,
"type": api_type,
"base_url": base_url,
"auth_info": auth_info,
"api_key_value": api_key_value,
"common_headers": common_headers,
"endpoints": endpoints,
"rate_limit": rate_limit
}

apis_configurees.append(nouvelle_api)
print(f"\n[OK] L’API '{nom_api}' a été ajoutée.")
print(f" - Type : {api_type}")
print(f" - URL de base : {base_url}\n")


def lister_apis():
print("=== Liste des API configurées ===")
if not apis_configurees:
print("Aucune API n’est configurée.\n")
return

for i, api in enumerate(apis_configurees, start=1):
print(f"{i}. Nom : {api['name']}")
print(f" URL de base : {api['base_url'] or 'Non renseignée'}")
print(f" Type : {api['type'] or 'Inconnu'}")
if api["rate_limit"]:
print(f" Limitation de débit : {api['rate_limit']}")
if api["endpoints"]:
print(" Endpoints :")
for ep in api["endpoints"]:
print(f" - {ep['name']} ({ep['method']} {ep['path']})")
else:
print(" Aucun endpoint configuré.")
print()
print()


def modifier_api():
print("=== Modification d’une API ===")
api_choisie = selectionner_api()
if not api_choisie:
return

print(f"\nAPI sélectionnée : {api_choisie['name']}")
print("Que voulez-vous modifier ? (ex: 'changer l'URL de base', 'changer la clé API', "
"'ajouter un endpoint', 'modifier un endpoint', 'supprimer un endpoint')")
action = input("> ").lower()

if "url" in action:
new_url = input("Nouvelle URL de base : ")
api_choisie["base_url"] = new_url
print("URL de base modifiée.\n")

if "clé" in action or "key" in action:
new_key = input("Nouvelle clé API : ")
api_choisie["api_key_value"] = new_key
print("Clé API modifiée.\n")

if "ajouter un endpoint" in action:
print("=== Ajout d'un endpoint ===")
nom_ep = input("Nom du nouvel endpoint : ")
path_ep = input("Chemin (ex: /playlists/{playlist_id}/tracks) : ")
methode = input("Méthode HTTP (GET, POST, etc.) : ")
params_req = [p.strip() for p in input("Paramètres requis (séparés par des virgules) : ").split(",") if p.strip()]
params_opt = [p.strip() for p in input("Paramètres optionnels (séparés par des virgules) : ").split(",") if p.strip()]

new_ep = {
"name": nom_ep,
"path": path_ep,
"method": methode.upper(),
"required_params": params_req,
"optional_params": params_opt,
"description": ""
}
api_choisie["endpoints"].append(new_ep)
print(f"Endpoint '{nom_ep}' ajouté.\n")

if "modifier un endpoint" in action:
print("=== Modification d'un endpoint ===")
if not api_choisie["endpoints"]:
print("Aucun endpoint à modifier.")
return

print("Liste des endpoints :")
for i, ep in enumerate(api_choisie["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")

choix_ep = lire_int_in_range(
f"Quel endpoint modifier ? [1..{len(api_choisie['endpoints'])}] : ",
1,
len(api_choisie["endpoints"])
)
ep_choisi = api_choisie["endpoints"][choix_ep - 1]

print(f"Endpoint sélectionné : {ep_choisi['name']}")
modif_ep = input("Que voulez-vous faire ? (ex: 'ajouter un paramètre', 'changer la méthode', etc.) : ").lower()
if "ajouter un paramètre" in modif_ep:
nom_p = input("Nom du paramètre : ")
r_o = input("Paramètre requis ou optionnel ? (r/o) : ")
if r_o.lower() == 'r':
ep_choisi["required_params"].append(nom_p)
else:
ep_choisi["optional_params"].append(nom_p)
print(f"Paramètre '{nom_p}' ajouté.\n")

# D’autres modifications possibles...

if "supprimer un endpoint" in action:
print("=== Suppression d'un endpoint ===")
if not api_choisie["endpoints"]:
print("Aucun endpoint à supprimer.")
return

print("Liste des endpoints :")
for i, ep in enumerate(api_choisie["endpoints"], start=1):
print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})")

choix_ep = lire_int_in_range(
f"Quel endpoint supprimer ? [1..{len(api_choisie['endpoints'])}] : ",
1,
len(api_choisie["endpoints"])
)
ep_asup = api_choisie["endpoints"][choix_ep - 1]
api_choisie["endpoints"].remove(ep_asup)
print(f"Endpoint '{ep_asup['name']}' supprimé.")

print("Modification(s) terminée(s).\n")


def supprimer_api():
print("=== Suppression d’une API ===")
api_choisie = selectionner_api()
if not api_choisie:
return

confirm = input(f"Êtes-vous sûr de vouloir supprimer '{api_choisie['name']}' ? (o/n) : ")
if confirm.lower() == 'o':
apis_configurees.remove(api_choisie)
print(f"L’API '{api_choisie['name']}' a été supprimée.\n")
else:
print("Opération annulée.\n")


def tester_endpoint():
print("=== Tester un endpoint ===")
api_choisie = selectionner_api()
if not api_choisie:
return

ep_choisi = selectionner_endpoint(api_choisie)
if not ep_choisi:
return

# On va demander les valeurs pour chaque param requis
required_params_values = {}
for rp in ep_choisi.get("required_params", []):
val = input(f"Entrez la valeur pour '{rp}' : ")
required_params_values[rp] = val

# On va demander les valeurs pour chaque param optionnel
optional_params_values = {}
for op in ep_choisi.get("optional_params", []):
val = input(f"Valeur pour '{op}' (laisser vide si aucun) : ")
if val:
optional_params_values[op] = val

# Préparation de l’URL
base_url = api_choisie.get("base_url") or ""
path = ep_choisi["path"]

# Remplacement dans le path si on a des placeholders {param}
# et retrait du param si on a pu le remplacer
query_params = {}
for k, v in required_params_values.items():
placeholder = f"{{{k}}}"
if placeholder in path:
path = path.replace(placeholder, v)
else:
# S'il n'y a pas de placeholder correspondant, on le mettra en query param
query_params[k] = v

# Tous les optionnels vont en query params
query_params.update(optional_params_values)

# Gestion de l’authentification
headers = dict(api_choisie.get("common_headers", {}))
if "Accept" not in headers:
headers["Accept"] = "application/json"

auth_info = api_choisie.get("auth_info", {})
api_key_value = api_choisie.get("api_key_value")

if auth_info.get("required") and api_key_value:
# Exemple : si c’est un Bearer
if auth_info["type"] and "bearer" in auth_info["type"].lower():
key_name = auth_info.get("key_name", "Authorization")
headers[key_name] = f"Bearer {api_key_value}"
# Exemple : si c’est un Basic
elif auth_info["type"] and "basic" in auth_info["type"].lower():
key_name = auth_info.get("key_name", "Authorization")
headers[key_name] = f"Basic {api_key_value}"
else:
# Si key_name = "api_key", NASA veut un query param "api_key=XXXX"
if auth_info.get("key_name", "").lower() == "api_key":
query_params["api_key"] = api_key_value
else:
# Sinon on le place dans un header
key_name = auth_info.get("key_name", "X-API-Key")
headers[key_name] = api_key_value

# Construction de l'URL finale
url = base_url + path

method = ep_choisi["method"].upper()
print(f"\nTest de l'endpoint : {method} {url}")
print(f"En-têtes : {headers}")
print(f"Paramètres : {query_params}\n")

try:
if method == "GET":
r = requests.get(url, headers=headers, params=query_params)
elif method == "POST":
r = requests.post(url, headers=headers, json=query_params)
elif method == "PUT":
r = requests.put(url, headers=headers, json=query_params)
elif method == "DELETE":
r = requests.delete(url, headers=headers, json=query_params)
else:
print("Méthode non gérée.")
return

print(f"Statut : {r.status_code}")
try:
print("Réponse JSON :")
print(json.dumps(r.json(), indent=2))
except:
print("Réponse brute :")
print(r.text)

except Exception as e:
print(f"Erreur lors de l’appel : {e}")

# ---------------------------------------------------------------------------
# 5. MAIN
def main():
while True:
print("=== Menu Principal ===")
print("1. Ajouter une API (assisté par IA)")
print("2. Liste des API configurées")
print("3. Modifier une API")
print("4. Supprimer une API")
print("5. Tester un endpoint")
print("6. Quitter")

choix_num = lire_int_in_range("Choisissez une option [1..6] : ", 1, 6)

if choix_num == 1:
ajouter_api()
elif choix_num == 2:
lister_apis()
elif choix_num == 3:
modifier_api()
elif choix_num == 4:
supprimer_api()
elif choix_num == 5:
tester_endpoint()
elif choix_num == 6:
print("Au revoir.")
sys.exit(0)


if __name__ == "__main__":
main()

사고

Mapping out JSON

I’m detailing steps to manage API configurations using a JSON file. I’m focusing on loading, modifying, and saving API data, ensuring persistence.

Ensuring persistence

To maintain data integrity, sauvegarder_apis() is invoked after each change to APIs or endpoints. Initially, charger_apis() loads configuration, and import os, pathlib is considered for file paths.

Thought about API storage in JSON pendant 15 secondes

답변

Voici une version améliorée du script qui sauvegarde la liste des APIs dans un fichier JSON (par exemple apis_configurees.json). À chaque fois qu’on ajoute, modifie ou supprime une API, on met à jour ce fichier. Ainsi, même si le script est relancé, on retrouve les APIs déjà configurées.

Principaux changements

  1. Fichier de configuration :

    • Ajout de deux fonctions : charger_apis() et sauvegarder_apis().
    • Le fichier par défaut est apis_configurees.json (vous pouvez changer son nom au besoin).
  2. Chargement au démarrage :

    • Au tout début de main(), on essaie de charger la liste des APIs depuis le fichier.
    • S’il n’existe pas, on laisse la liste apis_configurees vide.
  3. Sauvegarde après chaque opération :

    • À la fin de ajouter_api(), modifier_api(), supprimer_api(), on appelle sauvegarder_apis().
    • Ainsi, toutes les modifications sont persistées dans le JSON.
  4. Format du JSON :

    • Le fichier JSON contiendra simplement la liste apis_configurees. Chaque élément est un dictionnaire décrivant l’API, incluant endpoints, etc.

import sys import json import os import requests from groq import Groq # Nom du fichier où l'on stocke les APIs FICHIER_APIS = "apis_configurees.json" # Stockage en mémoire des APIs apis_configurees = [] # Paramètre : longueur max avant de résumer MAX_CHARS_DIRECT_ANALYSIS = 3000 # --------------------------------------------------------------------------- # 1. Fonctions d'IO pour sauvegarder/charger les APIs def sauvegarder_apis(): """Sauvegarde la liste des APIs dans FICHIER_APIS au format JSON.""" try: with open(FICHIER_APIS, "w", encoding="utf-8") as f: json.dump(apis_configurees, f, indent=2, ensure_ascii=False) print(f"[INFO] Liste des APIs sauvegardée dans {FICHIER_APIS}.") except Exception as e: print(f"[ERREUR] Impossible de sauvegarder dans {FICHIER_APIS} : {e}") def charger_apis(): """Charge la liste des APIs depuis FICHIER_APIS (si présent).""" global apis_configurees if os.path.exists(FICHIER_APIS): try: with open(FICHIER_APIS, "r", encoding="utf-8") as f: apis_configurees = json.load(f) print(f"[INFO] {len(apis_configurees)} API(s) chargée(s) depuis {FICHIER_APIS}.") except Exception as e: print(f"[ERREUR] Impossible de lire {FICHIER_APIS} : {e}") apis_configurees = [] else: apis_configurees = [] # --------------------------------------------------------------------------- # 2. Fonction de résumé (texte brut) si la doc est trop volumineuse def summarizer_groq(long_text, groq_api_key="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"): """ Découpe la documentation en chunks et génère un résumé global en langage naturel. Ceci n'utilise pas le mode JSON : on veut juste un résumé texte. """ client = Groq(api_key=groq_api_key) chunk_size = 3000 chunks = [] start = 0 while start < len(long_text): end = start + chunk_size chunks.append(long_text[start:end]) start = end summaries = [] for i, chunk_text in enumerate(chunks, start=1): print(f"[INFO] Résumé du chunk {i}/{len(chunks)}...") messages = [ { "role": "system", "content": ( "Tu es un assistant chargé de résumer la documentation d'API. " "Retourne un résumé concis (en langage courant) du texte fourni. " "Ne génère pas de JSON, pas de code, juste un texte résumé clair." ) }, { "role": "user", "content": chunk_text } ] try: completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.2, max_completion_tokens=1024, top_p=1, stream=False ) summary_text = completion.choices[0].message.content.strip() summaries.append(summary_text) except Exception as e: print(f"[ERREUR] Impossible de résumer le chunk {i} : {e}") summaries.append("") combined_summary = "\n".join(summaries) print(f"[INFO] Résumé global généré. Longueur du résumé : {len(combined_summary)} caractères.") return combined_summary # --------------------------------------------------------------------------- # 3. Fonction d'analyse finale en JSON def analyser_api_avec_groq(input_text, groq_api_key="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"): """ 1) Si le texte est trop long, on génère un résumé texte via summarizer_groq. 2) On passe ensuite (ou directement) le texte final dans un prompt qui demande un JSON strict (voir schéma ci-dessous). """ # 1) Résume si trop volumineux text_for_analysis = input_text if len(input_text) > MAX_CHARS_DIRECT_ANALYSIS: print("[INFO] La documentation est trop volumineuse, on génère un résumé d’abord.") text_for_analysis = summarizer_groq(input_text, groq_api_key=groq_api_key) # 2) Appel Chat Completion en mode JSON client = Groq(api_key=groq_api_key) messages = [ { "role": "system", "content": ( "Tu es un assistant d'analyse d'API, tu dois répondre UNIQUEMENT en JSON valide, sans code superflu. " "Respecte le schéma JSON suivant (toutes les clés doivent exister) :\n\n" "{\n" " \"api_type\": \"REST | GraphQL | SOAP\",\n" " \"base_url\": \"string\",\n" " \"auth_info\": {\n" " \"type\": \"string (Bearer, Basic, etc.)\",\n" " \"key_name\": \"string\",\n" " \"required\": true/false\n" " },\n" " \"common_headers\": {\n" " \"Header-Name\": \"Header-Value\"\n" " },\n" " \"endpoints\": [\n" " {\n" " \"name\": \"string\",\n" " \"path\": \"string\",\n" " \"method\": \"GET | POST | ...\",\n" " \"required_params\": [\"param1\", \"param2\"],\n" " \"optional_params\": [\"param1\", \"param2\"],\n" " \"description\": \"string\"\n" " }\n" " ],\n" " \"suggested_name\": \"string\",\n" " \"rate_limit\": \"string\",\n" " \"confidence_score\": 0.0\n" "}\n\n" "Analyse le texte ci-après et renvoie STRICTEMENT un JSON conforme, sans texte additionnel." ) }, { "role": "user", "content": text_for_analysis } ] try: chat_completion = client.chat.completions.create( messages=messages, model="llama-3.3-70b-versatile", temperature=0.0, max_completion_tokens=1024, top_p=1, stream=False, response_format={"type": "json_object"} ) content = chat_completion.choices[0].message.content data = json.loads(content) return data except Exception as e: print(f"[ERREUR] Échec de la conversion en JSON : {e}") print("[INFO] Nous allons retourner un squelette par défaut.") return { "api_type": None, "base_url": None, "auth_info": { "type": None, "key_name": None, "required": False }, "common_headers": {}, "endpoints": [], "suggested_name": "API_Inconnue", "rate_limit": None, "confidence_score": 0.0 } # --------------------------------------------------------------------------- # 4. FONCTIONS D’OUTIL POUR L’INTERFACE def lire_int_in_range(prompt: str, min_val: int, max_val: int) -> int: """ Demande à l'utilisateur de saisir un entier dans la plage [min_val..max_val]. Si l'utilisateur saisit '?', on affiche un petit message d'aide (personnalisable). Répète la question tant que la valeur n'est pas un entier correct. Retourne l'entier validé. """ while True: saisie = input(prompt).strip() # Exemple de gestion d'un '?' ou autre commande spéciale if saisie == "?": print("Aide : veuillez saisir un entier compris entre " f"{min_val} et {max_val}.") print("Tapez un nombre valide, ou Ctrl+C pour annuler.") continue # Sinon, on tente la conversion try: val = int(saisie) if min_val <= val <= max_val: return val else: print(f"Choix invalide (doit être entre {min_val} et {max_val}).\n") except ValueError: print("Choix invalide (entrez un nombre). Réessayez.\n") def selectionner_api() -> dict: """ Affiche la liste des API configurées, demande à l'utilisateur d'en choisir une par numéro. Retourne le dict correspondant ou None si aucune API. """ if not apis_configurees: print("Aucune API n’est configurée.\n") return None print("=== Liste des APIs disponibles ===") for i, api in enumerate(apis_configurees, start=1): print(f"{i}. {api['name']}") # On lit un choix (numéro) dans la plage [1..len(apis_configurees)] choix_num = lire_int_in_range( prompt=f"Quelle API souhaitez-vous sélectionner ? [1..{len(apis_configurees)}] : ", min_val=1, max_val=len(apis_configurees) ) return apis_configurees[choix_num - 1] def selectionner_endpoint(api: dict) -> dict: """ Affiche la liste des endpoints pour l'API donnée, demande à l'utilisateur d'en choisir un par numéro. Retourne le dict correspondant ou None si aucun endpoint. """ if not api["endpoints"]: print("Cette API n’a aucun endpoint configuré.\n") return None print(f"Endpoints disponibles pour {api['name']} :") for i, ep in enumerate(api["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep_num = lire_int_in_range( prompt=f"Quel endpoint tester ? [1..{len(api['endpoints'])}] : ", min_val=1, max_val=len(api["endpoints"]) ) return api["endpoints"][choix_ep_num - 1] # --------------------------------------------------------------------------- # 5. Fonctions du menu def ajouter_api(): print("=== Ajout d’une nouvelle API ===") _ = input("Voulez-vous coller la documentation de l’API ? (o/n) : ") print("Collez la documentation ci-dessous (finissez par un skibidi vide) :") lignes_doc = [] while True: ligne = input() if ligne == "skibidi": break lignes_doc.append(ligne) doc_api = "\n".join(lignes_doc) if not doc_api.strip(): doc_api = "Pas d'information sur l'API." # Appel Groq pour analyse resultats_analyse = analyser_api_avec_groq(doc_api, groq_api_key="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") confidence_score = resultats_analyse.get("confidence_score", 0.0) if confidence_score < 0.5: print( "Le score de confiance de l’analyse est faible. " "Les informations retournées peuvent être partielles ou incorrectes.\n" ) # Champs retournés api_type = resultats_analyse.get("api_type") base_url = resultats_analyse.get("base_url") auth_info = resultats_analyse.get("auth_info", {}) common_headers = resultats_analyse.get("common_headers", {}) endpoints = resultats_analyse.get("endpoints", []) suggested_name = resultats_analyse.get("suggested_name", "NouvelleAPI") rate_limit = resultats_analyse.get("rate_limit") print(f"Nom suggéré pour l’API : {suggested_name}") nom_api = input(f"Entrez le nom de l’API ({suggested_name}) : ") if not nom_api.strip(): nom_api = suggested_name # Si auth_info.required == True, on demande la clé api_key_value = None if auth_info.get("required", False): api_key_value = input("Entrez la valeur de la clé API ou du token : ") # Construction de la config nouvelle_api = { "name": nom_api, "type": api_type, "base_url": base_url, "auth_info": auth_info, "api_key_value": api_key_value, "common_headers": common_headers, "endpoints": endpoints, "rate_limit": rate_limit } apis_configurees.append(nouvelle_api) print(f"\n[OK] L’API '{nom_api}' a été ajoutée.") print(f" - Type : {api_type}") print(f" - URL de base : {base_url}\n") # On sauvegarde dans le fichier JSON sauvegarder_apis() def lister_apis(): print("=== Liste des API configurées ===") if not apis_configurees: print("Aucune API n’est configurée.\n") return for i, api in enumerate(apis_configurees, start=1): print(f"{i}. Nom : {api['name']}") print(f" URL de base : {api['base_url'] or 'Non renseignée'}") print(f" Type : {api['type'] or 'Inconnu'}") if api["rate_limit"]: print(f" Limitation de débit : {api['rate_limit']}") if api["endpoints"]: print(" Endpoints :") for ep in api["endpoints"]: print(f" - {ep['name']} ({ep['method']} {ep['path']})") else: print(" Aucun endpoint configuré.") print() print() def modifier_api(): print("=== Modification d’une API ===") api_choisie = selectionner_api() if not api_choisie: return print(f"\nAPI sélectionnée : {api_choisie['name']}") print("Que voulez-vous modifier ? (ex: 'changer l'URL de base', 'changer la clé API', " "'ajouter un endpoint', 'modifier un endpoint', 'supprimer un endpoint')") action = input("> ").lower() if "url" in action: new_url = input("Nouvelle URL de base : ") api_choisie["base_url"] = new_url print("URL de base modifiée.\n") if "clé" in action or "key" in action: new_key = input("Nouvelle clé API : ") api_choisie["api_key_value"] = new_key print("Clé API modifiée.\n") if "ajouter un endpoint" in action: print("=== Ajout d'un endpoint ===") nom_ep = input("Nom du nouvel endpoint : ") path_ep = input("Chemin (ex: /playlists/{playlist_id}/tracks) : ") methode = input("Méthode HTTP (GET, POST, etc.) : ") params_req = [p.strip() for p in input("Paramètres requis (séparés par des virgules) : ").split(",") if p.strip()] params_opt = [p.strip() for p in input("Paramètres optionnels (séparés par des virgules) : ").split(",") if p.strip()] new_ep = { "name": nom_ep, "path": path_ep, "method": methode.upper(), "required_params": params_req, "optional_params": params_opt, "description": "" } api_choisie["endpoints"].append(new_ep) print(f"Endpoint '{nom_ep}' ajouté.\n") if "modifier un endpoint" in action: print("=== Modification d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à modifier.") return print("Liste des endpoints :") for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = lire_int_in_range( f"Quel endpoint modifier ? [1..{len(api_choisie['endpoints'])}] : ", 1, len(api_choisie["endpoints"]) ) ep_choisi = api_choisie["endpoints"][choix_ep - 1] print(f"Endpoint sélectionné : {ep_choisi['name']}") modif_ep = input("Que voulez-vous faire ? (ex: 'ajouter un paramètre', 'changer la méthode', etc.) : ").lower() if "ajouter un paramètre" in modif_ep: nom_p = input("Nom du paramètre : ") r_o = input("Paramètre requis ou optionnel ? (r/o) : ") if r_o.lower() == 'r': ep_choisi["required_params"].append(nom_p) else: ep_choisi["optional_params"].append(nom_p) print(f"Paramètre '{nom_p}' ajouté.\n") # D’autres modifications possibles... if "supprimer un endpoint" in action: print("=== Suppression d'un endpoint ===") if not api_choisie["endpoints"]: print("Aucun endpoint à supprimer.") return print("Liste des endpoints :") for i, ep in enumerate(api_choisie["endpoints"], start=1): print(f"{i}. {ep['name']} ({ep['method']} {ep['path']})") choix_ep = lire_int_in_range( f"Quel endpoint supprimer ? [1..{len(api_choisie['endpoints'])}] : ", 1, len(api_choisie["endpoints"]) ) ep_asup = api_choisie["endpoints"][choix_ep - 1] api_choisie["endpoints"].remove(ep_asup) print(f"Endpoint '{ep_asup['name']}' supprimé.") print("Modification(s) terminée(s).\n") # On sauvegarde les modifications sauvegarder_apis() def supprimer_api(): print("=== Suppression d’une API ===") api_choisie = selectionner_api() if not api_choisie: return confirm = input(f"Êtes-vous sûr de vouloir supprimer '{api_choisie['name']}' ? (o/n) : ") if confirm.lower() == 'o': apis_configurees.remove(api_choisie) print(f"L’API '{api_choisie['name']}' a été supprimée.\n") sauvegarder_apis() else: print("Opération annulée.\n") def tester_endpoint(): print("=== Tester un endpoint ===") api_choisie = selectionner_api() if not api_choisie: return ep_choisi = selectionner_endpoint(api_choisie) if not ep_choisi: return # On va demander les valeurs pour chaque param requis required_params_values = {} for rp in ep_choisi.get("required_params", []): val = input(f"Entrez la valeur pour '{rp}' : ") required_params_values[rp] = val # On va demander les valeurs pour chaque param optionnel optional_params_values = {} for op in ep_choisi.get("optional_params", []): val = input(f"Valeur pour '{op}' (laisser vide si aucun) : ") if val: optional_params_values[op] = val # Préparation de l’URL base_url = api_choisie.get("base_url") or "" path = ep_choisi["path"] # Remplacement dans le path si on a des placeholders {param} # et retrait du param si on a pu le remplacer query_params = {} for k, v in required_params_values.items(): placeholder = f"{{{k}}}" if placeholder in path: path = path.replace(placeholder, v) else: # S'il n'y a pas de placeholder correspondant, on le mettra en query param query_params[k] = v # Tous les optionnels vont en query params query_params.update(optional_params_values) # Gestion de l’authentification headers = dict(api_choisie.get("common_headers", {})) if "Accept" not in headers: headers["Accept"] = "application/json" auth_info = api_choisie.get("auth_info", {}) api_key_value = api_choisie.get("api_key_value") if auth_info.get("required") and api_key_value: # Exemple : si c’est un Bearer if auth_info["type"] and "bearer" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Bearer {api_key_value}" # Exemple : si c’est un Basic elif auth_info["type"] and "basic" in auth_info["type"].lower(): key_name = auth_info.get("key_name", "Authorization") headers[key_name] = f"Basic {api_key_value}" else: # Si key_name = "api_key", NASA veut un query param "api_key=XXXX" if auth_info.get("key_name", "").lower() == "api_key": query_params["api_key"] = api_key_value else: # Sinon on le place dans un header key_name = auth_info.get("key_name", "X-API-Key") headers[key_name] = api_key_value # Construction de l'URL finale url = base_url + path method = ep_choisi["method"].upper() print(f"\nTest de l'endpoint : {method} {url}") print(f"En-têtes : {headers}") print(f"Paramètres : {query_params}\n") try: if method == "GET": r = requests.get(url, headers=headers, params=query_params) elif method == "POST": r = requests.post(url, headers=headers, json=query_params) elif method == "PUT": r = requests.put(url, headers=headers, json=query_params) elif method == "DELETE": r = requests.delete(url, headers=headers, json=query_params) else: print("Méthode non gérée.") return print(f"Statut : {r.status_code}") try: print("Réponse JSON :") print(json.dumps(r.json(), indent=2)) except: print("Réponse brute :") print(r.text) except Exception as e: print(f"Erreur lors de l’appel : {e}") # --------------------------------------------------------------------------- # 6. MAIN def main(): # On charge la liste des APIs en début de programme charger_apis() while True: print("=== Menu Principal ===") print("1. Ajouter une API (assisté par IA)") print("2. Liste des API configurées") print("3. Modifier une API") print("4. Supprimer une API") print("5. Tester un endpoint") print("6. Quitter") choix_num = lire_int_in_range("Choisissez une option [1..6] : ", 1, 6) if choix_num == 1: ajouter_api() elif choix_num == 2: lister_apis() elif choix_num == 3: modifier_api() elif choix_num == 4: supprimer_api() elif choix_num == 5: tester_endpoint() elif choix_num == 6: print("Au revoir.") sys.exit(0) if __name__ == "__main__": main()

Explications finales

  • FICHIER_APIS : c’est le nom du fichier (par défaut apis_configurees.json) où sont stockées les informations sur les APIs.
  • charger_apis() : appelé au lancement du script, il charge (si présent) le fichier JSON dans la variable globale apis_configurees.
  • sauvegarder_apis() : à chaque fois qu’on apporte une modification (ajout, édition ou suppression), on appelle cette fonction pour réécrire le fichier JSON.
  • Structure du JSON : c’est simplement un tableau (liste Python) d’objets. Chaque objet (API) contient les clés "name", "base_url", "type", "auth_info", "endpoints", etc.

Ainsi, lorsque vous relancerez votre script, il relira automatiquement le fichier apis_configurees.json et vous retrouverez vos APIs.

이 Q&A 공유하기