import os import requests import json import time from dotenv import load_dotenv load_dotenv("../.env.global") MAMMOUTH_APIKEY = os.getenv("MAMMOUTH_APIKEY") AIANALASYS_APIKEY = os.getenv("AIANALASYS_APIKEY") def get_mammouth_models(): # Retour au point d'accès OpenRouter compatible qui est plus stable url = "https://openrouter.ai/api/v1/models" headers = {"Authorization": f"Bearer {MAMMOUTH_APIKEY}"} try: response = requests.get(url, headers=headers) response.raise_for_status() return response.json().get('data', []) except Exception as e: print(f"Error fetching Mammouth models: {e}") return [] def get_aa_data(): url = "https://artificialanalysis.ai/api/v2/data/llms/models" headers = {"x-api-key": AIANALASYS_APIKEY} try: response = requests.get(url, headers=headers) response.raise_for_status() return response.json().get('data', []) except Exception as e: print(f"Error fetching Artificial Analysis data: {e}") return [] def generate_markdown(models_data): categories = {} for m in models_data: cat = m.get('category', 'General') if cat not in categories: categories[cat] = [] categories[cat].append(m) md = "# Table des Modèles Mammouth.ai\n\n" md += "*Mise à jour automatique via Artificial Analysis & Mammouth API*\n\n" md += f"Dernière mise à jour : {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n" order = ['Coding', 'Agents', 'General'] sorted_cats = sorted(categories.keys(), key=lambda x: order.index(x) if x in order else 99) for cat in sorted_cats: models = categories[cat] # Tri par score (desc) puis prix (asc) models.sort(key=lambda x: (x.get('score') or 0, -(x.get('price_in') or 999)), reverse=True) md += f"## {cat}\n\n" md += "| Modèle | Prix (In / Out / 1M) | Intelligence Index | Vitesse (TPS) |\n" md += "| :--- | :--- | :--- | :--- |\n" for m in models: p_in = f"${m['price_in']:.2f}" p_out = f"${m['price_out']:.2f}" score = f"**{m['score']:.1f}**" if m['score'] else "N/A" speed = f"{m['speed']:.1f}" if m['speed'] else "N/A" md += f"| {m['name']} | {p_in} / {p_out} | {score} | {speed} |\n" md += "\n" return md def main(): print("Fetching models...") mammouth_models = get_mammouth_models() aa_raw = get_aa_data() # Mapping AA : Priorité aux noms exacts aa_map_exact = {m.get('model_name', '').lower(): m for m in aa_raw} aa_map_id = {m.get('model_id', '').lower(): m for m in aa_raw} enriched_models = [] for m in mammouth_models: m_id = m.get('id', '') m_name = m.get('name', '').lower() short_id = m_id.split('/')[-1].lower() # Mapping plus strict pour éviter les scores identiques aa_info = aa_map_id.get(m_id.lower()) or aa_map_exact.get(m_name) or aa_map_id.get(short_id) # Si toujours pas de match, on ne fait PAS de recherche par sous-chaîne floue # pour éviter de polluer les données. On ne match que si le nom est très proche. if not aa_info: for name, info in aa_map_exact.items(): if name in m_name and len(name) > 0.8 * len(m_name): aa_info = info break pricing = m.get('pricing', {}) try: price_in = float(pricing.get('prompt', 0)) * 1000000 price_out = float(pricing.get('completion', 0)) * 1000000 except: price_in, price_out = 0, 0 score = None speed = None if aa_info: evals = aa_info.get('evaluations', {}) score = evals.get('artificial_analysis_intelligence_index') speed = aa_info.get('median_output_tokens_per_second') category = "General" m_lower = (m_id + m_name).lower() if any(x in m_lower for x in ['coding', 'code', 'starcoder', 'coder']): category = "Coding" elif any(x in m_lower for x in ['agent', 'hermes', 'tool', 'function']): category = "Agents" enriched_models.append({ 'name': m.get('name', m_id), 'price_in': price_in, 'price_out': price_out, 'score': score, 'speed': speed, 'category': category }) # Filtrer les modèles inutiles (prix nul et pas de score) final_list = [m for m in enriched_models if m['price_in'] > 0 or m['score'] is not None] with open("README.md", "w", encoding="utf-8") as f: f.write(generate_markdown(final_list)) print(f"Done! {len(final_list)} models processed.") if __name__ == "__main__": main()