diff --git a/.github/workflows/update-readme.yml b/.github/workflows/update-readme.yml
index 6cc2dd3..b3e4389 100644
--- a/.github/workflows/update-readme.yml
+++ b/.github/workflows/update-readme.yml
@@ -37,6 +37,7 @@ jobs:
GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.auth.outputs.credentials_file_path }}
LAMBDA_API_KEY: ${{ secrets.LAMBDA_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
+ SCALEWAY_API_KEY: ${{ secrets.SCALEWAY_API_KEY }}
run: |
python -u src/pull_available_models.py
- name: Remove credentials
diff --git a/README.md b/README.md
index ac8e165..a7e533e 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ This lists various services that provide free access or credits towards API-base
| Mixtral 8x7B | 14,400 requests/day 5,000 tokens/minute |
| Whisper Large v3 | 7,200 audio-seconds/minute 2,000 requests/day |
| Whisper Large v3 Turbo | 7,200 audio-seconds/minute 2,000 requests/day |
-| OpenRouter | 20 requests/minute 200 requests/day | Gemini 2.0 Flash Experimental | |
+| OpenRouter | 20 requests/minute 200 requests/day | Gemini 2.0 Flash Experimental | |
| Gemini Experimental 1114 | |
| Gemini Experimental 1206 | |
| Gemma 2 9B Instruct | |
@@ -61,7 +61,6 @@ This lists various services that provide free access or credits towards API-base
| Qwen 2 7B Instruct | |
| Toppy M 7B | |
| Zephyr 7B Beta | |
-| google/gemini-2.0-flash-thinking-exp:free | |
| Google AI Studio |
Data is used for training (when used outside of the UK/CH/EEA/EU). |
@@ -178,6 +177,13 @@ This lists various services that provide free access or credits towards API-base
| Mistral Nemo 2407 | 12 requests/minute |
| Mixtral 8x22B Instruct | 12 requests/minute |
| Mixtral 8x7B Instruct | 12 requests/minute |
+| Scaleway Generative APIs (Free Beta) | | BGE-Multilingual-Gemma2 | 600 requests/minute 1,000,000 tokens/minute |
+| Llama 3.1 70B Instruct | 300 requests/minute 100,000 tokens/minute |
+| Llama 3.1 8B Instruct | 300 requests/minute 100,000 tokens/minute |
+| Mistral Nemo 2407 | 300 requests/minute 100,000 tokens/minute |
+| Pixtral 12B (2409) | 300 requests/minute 100,000 tokens/minute |
+| Qwen2.5 Coder 32B Instruct | |
+| sentence-t5-xxl | 600 requests/minute 1,000,000 tokens/minute |
| Cloudflare Workers AI | 10,000 tokens/day | Deepseek Coder 6.7B Base (AWQ) | |
| Deepseek Coder 6.7B Instruct (AWQ) | |
| Deepseek Math 7B Instruct | |
@@ -321,6 +327,7 @@ This lists various services that provide free access or credits towards API-base
| Llama 3.1 405B Base |
| Llama 3.1 405B Base (FP8) |
| Llama 3.1 405B Instruct |
+| Llama 3.1 405B Instruct Virtuals |
| Llama 3.1 70B Instruct |
| Llama 3.1 8B Instruct |
| Llama 3.2 3B Instruct |
@@ -331,7 +338,6 @@ This lists various services that provide free access or credits towards API-base
| Qwen2-VL 7B Instruct |
| Qwen2.5 72B Instruct |
| Qwen2.5 Coder 32B Instruct |
-| meta-llama/meta-llama-3.1-405b-instruct-virtuals |
| AI21 |
$10 for 3 months |
diff --git a/src/pull_available_models.py b/src/pull_available_models.py
index f961960..ef5ab36 100644
--- a/src/pull_available_models.py
+++ b/src/pull_available_models.py
@@ -3,6 +3,7 @@
from collections import defaultdict
import logging
import json
+from bs4 import BeautifulSoup
import requests
import os
from dotenv import load_dotenv
@@ -159,6 +160,13 @@ MODEL_TO_NAME_MAPPING = {
"llama-3.3-70b-specdec": "Llama 3.3 70B (Speculative Decoding)",
"@cf/meta/llama-3.3-70b-instruct-fp8-fast": "Llama 3.3 70B Instruct (FP8)",
"google/gemini-2.0-flash-exp:free": "Gemini 2.0 Flash Experimental",
+ "qwen2.5-coder-32b-instruct": "Qwen2.5 Coder 32B Instruct",
+ "bge-multilingual-gemma2": "BGE-Multilingual-Gemma2",
+ "pixtral-12b-2409": "Pixtral 12B (2409)",
+ "google/gemini-2.0-flash-thinking-exp:free": "Gemini 2.0 Flash Thinking Experimental",
+ "sentence-t5-xxl": "sentence-t5-xxl",
+ "meta-llama/meta-llama-3.1-405b-instruct-virtuals": "Llama 3.1 405B Instruct Virtuals",
+ "llama-3.1-8b-instruct": "Llama 3.1 8B Instruct",
}
@@ -184,6 +192,7 @@ OPENROUTER_IGNORED_MODELS = {
"google/gemini-exp-1114:free"
"google/gemini-exp-1206:free"
"google/gemini-2.0-flash-exp:free",
+ "google/gemini-2.0-flash-thinking-exp:free"
} # Ignore gemini experimental free models because rate limits mean they are unusable.
@@ -293,7 +302,7 @@ def fetch_openrouter_models(logger):
continue
if ":free" not in model["id"]:
continue
- if model["id"] in OPENROUTER_IGNORED_MODELS:
+ if model["id"].lower() in OPENROUTER_IGNORED_MODELS:
logger.debug(f"Ignoring model {model['id']}")
continue
ret_models.append(
@@ -637,6 +646,77 @@ ONLY OUTPUT JSON!""",
return ret_models
+def fetch_scaleway_models(logger):
+ logger.info("Fetching Scaleway models...")
+ r = requests.get(
+ "https://api.scaleway.ai/v1/models",
+ headers={"Authorization": f"Bearer {os.environ['SCALEWAY_API_KEY']}"},
+ )
+ r.raise_for_status()
+ models = r.json()["data"]
+ logger.info(f"Fetched {len(models)} models from Scaleway")
+ ret_models = []
+ for model in models:
+ ret_models.append(
+ {
+ "id": model["id"],
+ "name": get_model_name(model["id"]),
+ }
+ )
+ ret_models = sorted(ret_models, key=lambda x: x["name"])
+ logger.info("Fetching Scaleway rate limits")
+ r = requests.get(
+ "https://www.scaleway.com/en/docs/ai-data/generative-apis/reference-content/rate-limits/"
+ )
+ r.raise_for_status()
+ # Extract content
+ soup = BeautifulSoup(r.text, "html.parser")
+ body = str(soup.find("main"))
+ prompt = f"""
+Here is the web page to extract data from:
+```html
+{body}
+```
+ """
+ client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
+ logger.info("Extracting model rate limits from the provided web page...")
+ chat_response = client.chat.complete(
+ model="mistral-large-latest",
+ messages=[
+ {
+ "role": "system",
+ "content": """Extract the model rate limits as only integers from the provided web page into JSON of the following format:
+```json
+{
+ "model name here": {
+ "requests/minute": 10,
+ "tokens/minute": 100
+ }
+}
+```
+ONLY OUTPUT JSON!""",
+ },
+ {
+ "role": "user",
+ "content": prompt,
+ },
+ ],
+ response_format={
+ "type": "json_object",
+ },
+ temperature=0,
+ )
+ logger.info(chat_response.choices[0].message.content)
+ extracted_data = json.loads(chat_response.choices[0].message.content)
+ for model in extracted_data:
+ for m in ret_models:
+ if m["id"] == model:
+ m["limits"] = extracted_data[model]
+ break
+
+ return ret_models
+
+
def get_human_limits(model):
if "limits" not in model:
return ""
@@ -655,6 +735,7 @@ def main():
hyperbolic_logger = create_logger("Hyperbolic")
# lambda_logger = create_logger("Lambda Labs")
samba_logger = create_logger("SambaNova")
+ scaleway_logger = create_logger("Scaleway")
gemini_models = fetch_gemini_limits(google_ai_studio_logger)
openrouter_models = fetch_openrouter_models(openrouter_logger)
@@ -664,6 +745,7 @@ def main():
github_models = fetch_github_models(github_logger)
# lambda_models = fetch_lambda_models(lambda_logger)
samba_models = fetch_samba_models(samba_logger)
+ scaleway_models = fetch_scaleway_models(scaleway_logger)
groq_models = fetch_groq_models(groq_logger)
table = """
@@ -824,6 +906,17 @@ def main():
table += f"| {get_human_limits(model)} | "
table += "\n"
+ for idx, model in enumerate(scaleway_models):
+ table += ""
+ if idx == 0:
+ table += '| '
+ table += 'Scaleway Generative APIs (Free Beta)'
+ table += " | "
+ table += ' | '
+ table += f"{model['name']} | "
+ table += f"{get_human_limits(model)} | "
+ table += "
\n"
+
for idx, model in enumerate(cloudflare_models):
table += ""
if idx == 0:
diff --git a/src/requirements.txt b/src/requirements.txt
index 08fd926..532c7e0 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -2,3 +2,4 @@ requests
python-dotenv
google-cloud-quotas
mistralai
+beautifulsoup4
\ No newline at end of file