diff --git a/.circleci/config.yml b/.circleci/config.yml index 7a982d74cb..a8ccfcf710 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -657,7 +657,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2108,7 +2108,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2250,7 +2250,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2390,7 +2390,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2551,7 +2551,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2664,7 +2664,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -2800,7 +2800,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -3032,7 +3032,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 @@ -3549,7 +3549,7 @@ jobs: docker run -d \ --name postgres-db \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_PASSWORD=test-postgres \ -e POSTGRES_DB=circle_test \ -p 5432:5432 \ postgres:14 diff --git a/.gitguardian.yaml b/.gitguardian.yaml new file mode 100644 index 0000000000..861dd6e6d6 --- /dev/null +++ b/.gitguardian.yaml @@ -0,0 +1,84 @@ +version: 2 + +secret: + # Exclude files and paths by globbing + ignored_paths: + - "**/*.whl" + - "**/*.pyc" + - "**/__pycache__/**" + - "**/node_modules/**" + - "**/dist/**" + - "**/build/**" + - "**/.git/**" + - "**/venv/**" + - "**/.venv/**" + + # Large data/metadata files that don't need scanning + - "**/model_prices_and_context_window*.json" + - "**/*_metadata/*.txt" + - "**/tokenizers/*.json" + - "**/tokenizers/*" + - "miniconda.sh" + + # Build outputs and static assets + - "litellm/proxy/_experimental/out/**" + - "ui/litellm-dashboard/public/**" + - "**/swagger/*.js" + - "**/*.woff" + - "**/*.woff2" + - "**/*.avif" + - "**/*.webp" + + # Test data files + - "**/tests/**/data_map.txt" + - "tests/**/*.txt" + + # Documentation and other non-code files + - "docs/**" + - "**/*.md" + - "**/*.lock" + - "poetry.lock" + - "package-lock.json" + + # Ignore security incidents with the SHA256 of the occurrence (false positives) + ignored_matches: + # === Current detected false positives (SHA-based) === + + # gcs_pub_sub_body - folder name, not a password + - name: GCS pub/sub test folder name + match: 75f377c456eede69e5f6e47399ccee6016a2a93cc5dd11db09cc5b1359ae569a + + # os.environ/APORIA_API_KEY_1 - environment variable reference + - name: Environment variable reference APORIA_API_KEY_1 + match: e2ddeb8b88eca97a402559a2be2117764e11c074d86159ef9ad2375dea188094 + + # os.environ/APORIA_API_KEY_2 - environment variable reference + - name: Environment variable reference APORIA_API_KEY_2 + match: 09aa39a29e050b86603aa55138af1ff08fb86a4582aa965c1bd0672e1575e052 + + # oidc/circleci_v2/ - test authentication path, not a secret + - name: OIDC CircleCI test path + match: feb3475e1f89a65b7b7815ac4ec597e18a9ec1847742ad445c36ca617b536e15 + + # text-davinci-003 - OpenAI model identifier, not a secret + - name: OpenAI model identifier text-davinci-003 + match: c489000cf6c7600cee0eefb80ad0965f82921cfb47ece880930eb7e7635cf1f1 + + # === Preventive patterns for test keys (pattern-based) === + + # Test API keys (124 instances across 45 files) + - name: Test API keys with sk-test prefix + match: sk-test- + + # Mock API keys + - name: Mock API keys with sk-mock prefix + match: sk-mock- + + # Fake API keys + - name: Fake API keys with sk-fake prefix + match: sk-fake- + + # Generic test API key patterns + - name: Test API key patterns + match: test-api-key + diff --git a/.github/workflows/locustfile.py b/.github/workflows/locustfile.py index 36dbeee9c4..65d0d56b3a 100644 --- a/.github/workflows/locustfile.py +++ b/.github/workflows/locustfile.py @@ -8,7 +8,7 @@ class MyUser(HttpUser): def chat_completion(self): headers = { "Content-Type": "application/json", - "Authorization": "Bearer sk-8N1tLOOyH8TIxwOLahhIVg", + "Authorization": "Bearer sk-test-load-test-key-123", # Include any additional headers you may need for authentication, etc. } diff --git a/.github/workflows/publish-migrations.yml b/.github/workflows/publish-migrations.yml index 8e5a67bcf8..a81a64ab46 100644 --- a/.github/workflows/publish-migrations.yml +++ b/.github/workflows/publish-migrations.yml @@ -20,7 +20,7 @@ jobs: env: POSTGRES_DB: temp_db POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres + POSTGRES_PASSWORD: test-postgres ports: - 5432:5432 options: >- @@ -35,7 +35,7 @@ jobs: env: POSTGRES_DB: shadow_db POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres + POSTGRES_PASSWORD: test-postgres ports: - 5433:5432 options: >- diff --git a/ci_cd/TEST_KEY_PATTERNS.md b/ci_cd/TEST_KEY_PATTERNS.md new file mode 100644 index 0000000000..bd59f58283 --- /dev/null +++ b/ci_cd/TEST_KEY_PATTERNS.md @@ -0,0 +1,40 @@ +# Test Key Patterns Standard + +Standard patterns for test/mock keys and credentials in the LiteLLM codebase to avoid triggering secret detection. + +## How GitGuardian Works + +GitGuardian uses **machine learning and entropy analysis**, not just pattern matching: +- **Low entropy** values (like `sk-1234`, `postgres`) are automatically ignored +- **High entropy** values (realistic-looking secrets) trigger detection +- **Context-aware** detection understands code syntax like `os.environ["KEY"]` + +## Recommended Test Key Patterns + +### Option 1: Low Entropy Values (Simplest) +These won't trigger GitGuardian's ML detector: + +```python +api_key = "sk-1234" +api_key = "sk-12345" +database_password = "postgres" +token = "test123" +``` + +### Option 2: High Entropy with Test Prefixes +If you need realistic-looking test keys with high entropy, use these prefixes: + +```python +api_key = "sk-test-abc123def456ghi789..." # OpenAI-style test key +api_key = "sk-mock-1234567890abcdef1234..." # Mock key +api_key = "sk-fake-xyz789uvw456rst123..." # Fake key +token = "test-api-key-with-high-entropy" +``` + +## Configured Ignore Patterns + +These patterns are in `.gitguardian.yaml` for high-entropy test keys: +- `sk-test-*` - OpenAI-style test keys +- `sk-mock-*` - Mock API keys +- `sk-fake-*` - Fake API keys +- `test-api-key` - Generic test tokens diff --git a/cookbook/LiteLLM_PromptLayer.ipynb b/cookbook/LiteLLM_PromptLayer.ipynb index 3552636011..8fd5494102 100644 --- a/cookbook/LiteLLM_PromptLayer.ipynb +++ b/cookbook/LiteLLM_PromptLayer.ipynb @@ -39,7 +39,7 @@ "import os\n", "os.environ['OPENAI_API_KEY'] = \"\"\n", "os.environ['REPLICATE_API_TOKEN'] = \"\"\n", - "os.environ['PROMPTLAYER_API_KEY'] = \"pl_4ea2bb00a4dca1b8a70cebf2e9e11564\"\n", + "os.environ['PROMPTLAYER_API_KEY'] = \"test-promptlayer-key-123\"\n", "\n", "# Set Promptlayer as a success callback\n", "litellm.success_callback =['promptlayer']\n", diff --git a/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb b/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb index 39677ed2a8..740e7c7a4c 100644 --- a/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb +++ b/cookbook/Migrating_to_LiteLLM_Proxy_from_OpenAI_Azure_OpenAI.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "kccfk0mHZ4Ad" + }, "source": [ "# Migrating to LiteLLM Proxy from OpenAI/Azure OpenAI\n", "\n", @@ -32,29 +21,26 @@ "To pass provider-specific args, [go here](https://docs.litellm.ai/docs/completion/provider_specific_params#proxy-usage)\n", "\n", "To drop unsupported params (E.g. frequency_penalty for bedrock with librechat), [go here](https://docs.litellm.ai/docs/completion/drop_params#openai-proxy-usage)\n" - ], - "metadata": { - "id": "kccfk0mHZ4Ad" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "nmSClzCPaGH6" + }, "source": [ "## /chat/completion\n", "\n" - ], - "metadata": { - "id": "nmSClzCPaGH6" - } + ] }, { "cell_type": "markdown", - "source": [ - "### OpenAI Python SDK" - ], "metadata": { "id": "_vqcjwOVaKpO" - } + }, + "source": [ + "### OpenAI Python SDK" + ] }, { "cell_type": "code", @@ -94,15 +80,20 @@ }, { "cell_type": "markdown", - "source": [ - "## Function Calling" - ], "metadata": { "id": "AqkyKk9Scxgj" - } + }, + "source": [ + "## Function Calling" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "wDg10VqLczE1" + }, + "outputs": [], "source": [ "from openai import OpenAI\n", "client = OpenAI(\n", @@ -139,24 +130,24 @@ ")\n", "\n", "print(completion)\n" - ], - "metadata": { - "id": "wDg10VqLczE1" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Azure OpenAI Python SDK" - ], "metadata": { "id": "YYoxLloSaNWW" - } + }, + "source": [ + "### Azure OpenAI Python SDK" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "yA1XcgowaSRy" + }, + "outputs": [], "source": [ "import openai\n", "client = openai.AzureOpenAI(\n", @@ -184,24 +175,24 @@ ")\n", "\n", "print(response)" - ], - "metadata": { - "id": "yA1XcgowaSRy" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Langchain Python" - ], "metadata": { "id": "yl9qhDvnaTpL" - } + }, + "source": [ + "### Langchain Python" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "5MUZgSquaW5t" + }, + "outputs": [], "source": [ "from langchain.chat_models import ChatOpenAI\n", "from langchain.prompts.chat import (\n", @@ -239,24 +230,22 @@ "response = chat(messages)\n", "\n", "print(response)" - ], - "metadata": { - "id": "5MUZgSquaW5t" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Curl" - ], "metadata": { "id": "B9eMgnULbRaz" - } + }, + "source": [ + "### Curl" + ] }, { "cell_type": "markdown", + "metadata": { + "id": "VWCCk5PFcmhS" + }, "source": [ "\n", "\n", @@ -280,22 +269,24 @@ "}'\n", "```\n", "\n" - ], - "metadata": { - "id": "VWCCk5PFcmhS" - } + ] }, { "cell_type": "markdown", - "source": [ - "### LlamaIndex" - ], "metadata": { "id": "drBAm2e1b6xe" - } + }, + "source": [ + "### LlamaIndex" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "d0bZcv8fb9mL" + }, + "outputs": [], "source": [ "import os, dotenv\n", "\n", @@ -326,24 +317,24 @@ "query_engine = index.as_query_engine()\n", "response = query_engine.query(\"What did the author do growing up?\")\n", "print(response)\n" - ], - "metadata": { - "id": "d0bZcv8fb9mL" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Langchain JS" - ], "metadata": { "id": "xypvNdHnb-Yy" - } + }, + "source": [ + "### Langchain JS" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "R55mK2vCcBN2" + }, + "outputs": [], "source": [ "import { ChatOpenAI } from \"@langchain/openai\";\n", "\n", @@ -359,24 +350,24 @@ "const message = await model.invoke(\"Hi there!\");\n", "\n", "console.log(message);\n" - ], - "metadata": { - "id": "R55mK2vCcBN2" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### OpenAI JS" - ], "metadata": { "id": "nC4bLifCcCiW" - } + }, + "source": [ + "### OpenAI JS" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "MICH8kIMcFpg" + }, + "outputs": [], "source": [ "const { OpenAI } = require('openai');\n", "\n", @@ -398,24 +389,24 @@ "}\n", "\n", "main();\n" - ], - "metadata": { - "id": "MICH8kIMcFpg" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Anthropic SDK" - ], "metadata": { "id": "D1Q07pEAcGTb" - } + }, + "source": [ + "### Anthropic SDK" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "qBjFcAvgcI3t" + }, + "outputs": [], "source": [ "import os\n", "\n", @@ -423,7 +414,7 @@ "\n", "client = Anthropic(\n", " base_url=\"http://localhost:4000\", # proxy endpoint\n", - " api_key=\"sk-s4xN1IiLTCytwtZFJaYQrA\", # litellm proxy virtual key\n", + " api_key=\"sk-test-proxy-key-123\", # litellm proxy virtual key (example)\n", ")\n", "\n", "message = client.messages.create(\n", @@ -437,33 +428,33 @@ " model=\"claude-3-opus-20240229\",\n", ")\n", "print(message.content)" - ], - "metadata": { - "id": "qBjFcAvgcI3t" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "## /embeddings" - ], "metadata": { "id": "dFAR4AJGcONI" - } + }, + "source": [ + "## /embeddings" + ] }, { "cell_type": "markdown", - "source": [ - "### OpenAI Python SDK" - ], "metadata": { "id": "lgNoM281cRzR" - } + }, + "source": [ + "### OpenAI Python SDK" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "NY3DJhPfcQhA" + }, + "outputs": [], "source": [ "import openai\n", "from openai import OpenAI\n", @@ -478,24 +469,24 @@ ")\n", "\n", "print(response)\n" - ], - "metadata": { - "id": "NY3DJhPfcQhA" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Langchain Embeddings" - ], "metadata": { "id": "hmbg-DW6cUZs" - } + }, + "source": [ + "### Langchain Embeddings" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lX2S8Nl1cWVP" + }, + "outputs": [], "source": [ "from langchain.embeddings import OpenAIEmbeddings\n", "\n", @@ -526,24 +517,22 @@ "\n", "print(f\"TITAN EMBEDDINGS\")\n", "print(query_result[:5])" - ], - "metadata": { - "id": "lX2S8Nl1cWVP" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Curl Request" - ], "metadata": { "id": "oqGbWBCQcYfd" - } + }, + "source": [ + "### Curl Request" + ] }, { "cell_type": "markdown", + "metadata": { + "id": "7rkIMV9LcdwQ" + }, "source": [ "\n", "\n", @@ -556,10 +545,21 @@ " }'\n", "```\n", "\n" - ], - "metadata": { - "id": "7rkIMV9LcdwQ" - } + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/my-website/docs/oidc.md b/docs/my-website/docs/oidc.md index 3db4b6ecdc..b541329aa3 100644 --- a/docs/my-website/docs/oidc.md +++ b/docs/my-website/docs/oidc.md @@ -106,7 +106,7 @@ model_list: aws_region_name: us-west-2 aws_session_name: "my-test-session" aws_role_name: "arn:aws:iam::335785316107:role/litellm-github-unit-tests-circleci" - aws_web_identity_token: "oidc/circleci_v2/" + aws_web_identity_token: "oidc/example-provider/" ``` #### Amazon IAM Role Configuration for CircleCI v2 -> Bedrock diff --git a/docs/my-website/docs/proxy/alerting.md b/docs/my-website/docs/proxy/alerting.md index 4cbcd0cffc..38d6d47be4 100644 --- a/docs/my-website/docs/proxy/alerting.md +++ b/docs/my-website/docs/proxy/alerting.md @@ -215,16 +215,16 @@ general_settings: alerting: ["slack"] alerting_threshold: 0.0001 # (Seconds) set an artificially low threshold for testing alerting alert_to_webhook_url: { - "llm_exceptions": "https://hooks.slack.com/services/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", - "llm_too_slow": "https://hooks.slack.com/services/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", - "llm_requests_hanging": "https://hooks.slack.com/services/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", - "budget_alerts": "https://hooks.slack.com/services/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", - "db_exceptions": "https://hooks.slack.com/services/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", - "daily_reports": "https://hooks.slack.com/services/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", - "spend_reports": "https://hooks.slack.com/services/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", - "cooldown_deployment": "https://hooks.slack.com/services/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", - "new_model_added": "https://hooks.slack.com/services/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", - "outage_alerts": "https://hooks.slack.com/services/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", + "llm_exceptions": "example-slack-webhook-url", + "llm_too_slow": "example-slack-webhook-url", + "llm_requests_hanging": "example-slack-webhook-url", + "budget_alerts": "example-slack-webhook-url", + "db_exceptions": "example-slack-webhook-url", + "daily_reports": "example-slack-webhook-url", + "spend_reports": "example-slack-webhook-url", + "cooldown_deployment": "example-slack-webhook-url", + "new_model_added": "example-slack-webhook-url", + "outage_alerts": "example-slack-webhook-url", } litellm_settings: @@ -399,7 +399,7 @@ curl -X GET --location 'http://0.0.0.0:4000/health/services?service=webhook' \ { "spend": 1, # the spend for the 'event_group' "max_budget": 0, # the 'max_budget' set for the 'event_group' - "token": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "token": "example-api-key-123", "user_id": "default_user_id", "team_id": null, "user_email": null, diff --git a/docs/my-website/docs/proxy/cost_tracking.md b/docs/my-website/docs/proxy/cost_tracking.md index 019cd62c62..26a4920c09 100644 --- a/docs/my-website/docs/proxy/cost_tracking.md +++ b/docs/my-website/docs/proxy/cost_tracking.md @@ -722,7 +722,7 @@ curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end ```shell [ { - "api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "api_key": "example-api-key-123", "total_cost": 0.3201286305151999, "total_input_tokens": 36.0, "total_output_tokens": 1593.0, @@ -766,7 +766,7 @@ curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end ```shell [ { - "api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "api_key": "example-api-key-123", "total_cost": 0.00013132, "total_input_tokens": 105.0, "total_output_tokens": 872.0, @@ -1151,7 +1151,7 @@ curl -X GET "http://0.0.0.0:4000/spend/logs?request_id= str: """Generate a new key for the team and return it""" url = "http://0.0.0.0:4000/key/generate" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": "Bearer sk-test-1234", "Content-Type": "application/json", } data = { @@ -326,7 +339,7 @@ async def get_team_info(session: aiohttp.ClientSession, team_id: str) -> Dict[st """Fetch team info and return the response""" url = f"http://0.0.0.0:4000/team/info?team_id={team_id}" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": "Bearer sk-test-1234", } async with session.get(url, headers=headers) as response: @@ -415,7 +428,7 @@ async def create_test_key_with_budget( """Generate a new key with budget constraints and return it""" url = "http://0.0.0.0:4000/key/generate" headers = { - "Authorization": "Bearer sk-1234", + "Authorization": "Bearer sk-test-1234", "Content-Type": "application/json", } print("budget_data", budget_data) diff --git a/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py b/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py index 581f1d1979..97a1f2eecc 100644 --- a/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py +++ b/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py @@ -105,7 +105,7 @@ def test_create_anthropic_response_logging_payload(mock_logging_obj, metadata_pa kwargs={ "litellm_params": { "metadata": { - "user_api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "user_api_key": "sk-test-mock-api-key-123", "user_api_key_user_id": "default_user_id", "user_api_key_team_id": None, "user_api_key_end_user_id": ("test" if metadata_params else ""), diff --git a/tests/proxy_unit_tests/test_db_schema_migration.py b/tests/proxy_unit_tests/test_db_schema_migration.py index b317818375..a8fa324212 100644 --- a/tests/proxy_unit_tests/test_db_schema_migration.py +++ b/tests/proxy_unit_tests/test_db_schema_migration.py @@ -21,7 +21,7 @@ def test_aaaasschema_migration_check(schema_setup, monkeypatch): """Test to check if schema requires migration""" # Set test database URL test_db_url = f"postgresql://{schema_setup.info.user}:@{schema_setup.info.host}:{schema_setup.info.port}/{schema_setup.info.dbname}" - # test_db_url = "postgresql://neondb_owner:npg_JiZPS0DAhRn4@ep-delicate-wave-a55cvbuc.us-east-2.aws.neon.tech/neondb?sslmode=require" + # test_db_url = "postgresql://test-user:test-password@test-host.example.com/test-db?sslmode=require" monkeypatch.setenv("DATABASE_URL", test_db_url) deploy_dir = Path("./litellm-proxy-extras/litellm_proxy_extras") diff --git a/tests/proxy_unit_tests/test_jwt.py b/tests/proxy_unit_tests/test_jwt.py index 5743499397..2af61aa265 100644 --- a/tests/proxy_unit_tests/test_jwt.py +++ b/tests/proxy_unit_tests/test_jwt.py @@ -1266,7 +1266,7 @@ def test_user_api_key_auth_jwt_hashing(): from litellm.proxy.auth.handle_jwt import JWTHandler # Test with a JWT token (3 parts separated by dots) - jwt_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + jwt_token = "test-jwt-token-header.payload.signature" # Create UserAPIKeyAuth instance with JWT user_auth = UserAPIKeyAuth(api_key=jwt_token) @@ -1303,7 +1303,7 @@ def test_jwt_handler_is_jwt_static_method(): from litellm.proxy.auth.handle_jwt import JWTHandler # Test with valid JWT format - valid_jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + valid_jwt = "test-jwt-token-header.payload.signature" assert JWTHandler.is_jwt(valid_jwt) == True # Test with invalid JWT format (only 2 parts) diff --git a/tests/proxy_unit_tests/test_proxy_utils.py b/tests/proxy_unit_tests/test_proxy_utils.py index c88efe2ebe..2e5cfff8bf 100644 --- a/tests/proxy_unit_tests/test_proxy_utils.py +++ b/tests/proxy_unit_tests/test_proxy_utils.py @@ -238,7 +238,7 @@ def test_dynamic_logging_metadata_key_and_team_metadata(callback_vars): proxy_config = ProxyConfig() user_api_key_dict = UserAPIKeyAuth( - token="6f8688eaff1d37555bb9e9a6390b6d7032b3ab2526ba0152da87128eab956432", + token="sk-test-mock-token-789", key_name="sk-...63Fg", key_alias=None, spend=0.000111, @@ -287,7 +287,7 @@ def test_dynamic_logging_metadata_key_and_team_metadata(callback_vars): end_user_rpm_limit=None, end_user_max_budget=None, last_refreshed_at=1726101560.967527, - api_key="7c305cc48fe72272700dc0d67dc691c2d1f2807490ef5eb2ee1d3a3ca86e12b1", + api_key="sk-test-mock-api-key-202", user_role=LitellmUserRoles.INTERNAL_USER, allowed_model_region=None, parent_otel_span=None, @@ -320,7 +320,7 @@ def test_dynamic_turn_off_message_logging(callback_vars): proxy_config = ProxyConfig() user_api_key_dict = UserAPIKeyAuth( - token="6f8688eaff1d37555bb9e9a6390b6d7032b3ab2526ba0152da87128eab956432", + token="sk-test-mock-token-789", key_name="sk-...63Fg", key_alias=None, spend=0.000111, @@ -368,7 +368,7 @@ def test_dynamic_turn_off_message_logging(callback_vars): end_user_rpm_limit=None, end_user_max_budget=None, last_refreshed_at=1726101560.967527, - api_key="7c305cc48fe72272700dc0d67dc691c2d1f2807490ef5eb2ee1d3a3ca86e12b1", + api_key="sk-test-mock-api-key-202", user_role=LitellmUserRoles.INTERNAL_USER, allowed_model_region=None, parent_otel_span=None, @@ -1267,7 +1267,7 @@ def test_litellm_verification_token_view_response_with_budget_table( from litellm.proxy._types import LiteLLM_VerificationTokenView args: Dict[str, Any] = { - "token": "78b627d4d14bc3acf5571ae9cb6834e661bc8794d1209318677387add7621ce1", + "token": "sk-test-mock-token-303", "key_name": "sk-...if_g", "key_alias": None, "soft_budget_cooldown": False, diff --git a/tests/proxy_unit_tests/test_user_api_key_auth.py b/tests/proxy_unit_tests/test_user_api_key_auth.py index ec61c7305b..72d13aadad 100644 --- a/tests/proxy_unit_tests/test_user_api_key_auth.py +++ b/tests/proxy_unit_tests/test_user_api_key_auth.py @@ -696,7 +696,7 @@ def test_is_allowed_route(): "request": request, "request_data": {"input": ["hello world"], "model": "embedding-small"}, "valid_token": UserAPIKeyAuth( - token="9644159bc181998825c44c788b1526341ed2e825d1b6f562e23173759e14bb86", + token="sk-test-mock-token-101", key_name="sk-...CJjQ", key_alias=None, spend=0.0, diff --git a/tests/test_callbacks_on_proxy.py b/tests/test_callbacks_on_proxy.py index 831ca449f8..3bc07da8db 100644 --- a/tests/test_callbacks_on_proxy.py +++ b/tests/test_callbacks_on_proxy.py @@ -26,7 +26,7 @@ async def config_update(session, routing_strategy=None): }, "general_settings": { "alert_to_webhook_url": { - "llm_exceptions": "https://hooks.slack.com/services/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" + "llm_exceptions": "example-slack-webhook-url" }, "alert_types": ["llm_exceptions", "db_exceptions"], }, diff --git a/tests/test_litellm/integrations/cloudzero/test_cloudzero.py b/tests/test_litellm/integrations/cloudzero/test_cloudzero.py index 586ab43350..e45db8df10 100644 --- a/tests/test_litellm/integrations/cloudzero/test_cloudzero.py +++ b/tests/test_litellm/integrations/cloudzero/test_cloudzero.py @@ -46,7 +46,7 @@ class TestCloudZeroHourlyExport: { "team_id": ["a3d6b0bb-098f-4260-81d6-fabae695b622"], "key_alias": ["key_1"], - "token": ["c1465c9a821f420927b3d81972323fb516745bc93a4a54ceca0ce6ddf6100c39"], + "token": ["sk-test-cloudzero-token-010"], } ) diff --git a/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py b/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py index 4a06e9ea1a..1f0f3346c2 100644 --- a/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py +++ b/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py @@ -193,7 +193,7 @@ def test_vertex_ai_bge_psc_endpoint_url_construction(): client = HTTPHandler() def mock_auth_token(*args, **kwargs): - return "fake-token", "gen-lang-client-0682925754" + return "test-token-123", "test-gcp-project-id-123" with patch.object(client, "post") as mock_post, patch( "litellm.llms.vertex_ai.vertex_embeddings.embedding_handler.VertexEmbedding._ensure_access_token", @@ -212,7 +212,7 @@ def test_vertex_ai_bge_psc_endpoint_url_construction(): model="vertex_ai/bge/378943383978115072", input=["The food was delicious and the waiter.."], api_base="http://10.128.16.2", - vertex_project="gen-lang-client-0682925754", + vertex_project="test-gcp-project-id-123", vertex_location="us-central1", client=client, use_psc_endpoint_format=True # Enable PSC endpoint format for this test @@ -239,7 +239,7 @@ def test_vertex_ai_bge_psc_endpoint_url_construction(): print("="*50 + "\n") # Verify the URL is constructed correctly - expected_url = "http://10.128.16.2/v1/projects/gen-lang-client-0682925754/locations/us-central1/endpoints/378943383978115072:predict" + expected_url = "http://10.128.16.2/v1/projects/test-gcp-project-id-123/locations/us-central1/endpoints/378943383978115072:predict" assert api_url_called == expected_url, f"Expected URL: {expected_url}, Got: {api_url_called}" # Verify bge/ prefix is NOT in the URL diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py b/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py index 21782f4218..e1e4b3a8b6 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py @@ -332,7 +332,7 @@ class TestMCPRequestHandler: async def mock_user_api_key_auth(api_key, request): return UserAPIKeyAuth( token=( - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + "test-token-sha256-empty-hash" if api_key else None ), @@ -691,7 +691,7 @@ class TestMCPCustomHeaderName: # Create an async mock for user_api_key_auth async def mock_user_api_key_auth(api_key, request): return UserAPIKeyAuth( - token="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + token="test-token-sha256-empty-hash", api_key=api_key, user_id="test-user-id", team_id="test-team-id", @@ -866,7 +866,7 @@ class TestMCPAccessGroupsE2E: # Create an async mock for user_api_key_auth async def mock_user_api_key_auth(api_key, request): return UserAPIKeyAuth( - token="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + token="test-token-sha256-empty-hash", api_key=api_key, user_id="test-user-id", team_id="test-team-id", @@ -917,7 +917,7 @@ class TestMCPAccessGroupsE2E: # Create an async mock for user_api_key_auth async def mock_user_api_key_auth(api_key, request): return UserAPIKeyAuth( - token="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + token="test-token-sha256-empty-hash", api_key=api_key, user_id="test-user-id", team_id="test-team-id", diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py index eeae0ece02..f3de89d6d6 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py @@ -43,8 +43,8 @@ def mock_user_api_key_dict(): team_id="test-team", team_alias=None, user_role=None, - api_key="88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", - token="88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + api_key="a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456", + token="a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456", permissions={}, models=[], spend=0.0, @@ -71,7 +71,7 @@ def mock_request_data_input(): ], "litellm_call_id": "test-call-id", "metadata": { - "user_api_key_hash": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "user_api_key_hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456", "user_api_key_user_id": "default_user_id", "user_api_key_user_email": "test@example.com", "user_api_key_team_id": "test-team", @@ -197,7 +197,7 @@ class TestMetadataExtraction: # Verify metadata was extracted from request_data["metadata"] assert ( request_metadata["user_api_key_hash"] - == "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b" + == "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456" ) assert request_metadata["user_api_key_user_id"] == "default_user_id" assert request_metadata["user_api_key_user_email"] == "test@example.com" diff --git a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py index a08fc2cba6..fa8157ff65 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py +++ b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py @@ -2050,7 +2050,7 @@ class TestProcessSSOJWTAccessToken: @pytest.fixture def sample_jwt_token(self): """Create a sample JWT token string""" - return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + return "test-jwt-token-header.payload.signature" @pytest.fixture def sample_jwt_payload(self): diff --git a/tests/test_litellm/proxy/test_proxy_cli.py b/tests/test_litellm/proxy/test_proxy_cli.py index 90d958e711..5f03ef1817 100644 --- a/tests/test_litellm/proxy/test_proxy_cli.py +++ b/tests/test_litellm/proxy/test_proxy_cli.py @@ -180,7 +180,7 @@ class TestProxyInitializationHelpers: test_env = { "DATABASE_HOST": "localhost:5432", "DATABASE_USERNAME": "user@with+special", - "DATABASE_PASSWORD": "pass&word!@#$%", + "DATABASE_PASSWORD": "test-password-special-chars", "DATABASE_NAME": "db_name/test", } @@ -205,7 +205,7 @@ class TestProxyInitializationHelpers: database_url = f"postgresql://{database_username_enc}:{database_password_enc}@{database_host}/{database_name_enc}" # Assert the correct URL was constructed with properly escaped characters - expected_url = "postgresql://user%40with%2Bspecial:pass%26word%21%40%23%24%25@localhost:5432/db_name%2Ftest" + expected_url = "postgresql://user%40with%2Bspecial:test-password-special-chars@localhost:5432/db_name%2Ftest" assert database_url == expected_url # Test appending query parameters @@ -381,13 +381,13 @@ class TestProxyInitializationHelpers: test_env_special = { "DATABASE_HOST": "localhost:5432", "DATABASE_USERNAME": "user@with+special", - "DATABASE_PASSWORD": "pass&word!@#$%", + "DATABASE_PASSWORD": "test-password-special-chars", "DATABASE_NAME": "db_name/test", } with patch.dict(os.environ, test_env_special): result = construct_database_url_from_env_vars() - expected_url = "postgresql://user%40with%2Bspecial:pass%26word%21%40%23%24%25@localhost:5432/db_name%2Ftest" + expected_url = "postgresql://user%40with%2Bspecial:test-password-special-chars@localhost:5432/db_name%2Ftest" assert result == expected_url # Test without password (should still work) diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index 1f81026b53..6b8342968a 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -559,7 +559,7 @@ async def test_aaaproxy_startup_master_key(mock_prisma, monkeypatch, tmp_path): assert master_key == test_master_key # Test Case 2: Master key from environment variable - test_env_master_key = "sk-67890" + test_env_master_key = "sk-test-67890" # Create empty config empty_config = {"general_settings": {}} diff --git a/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py b/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py index b98354032f..f697ad9abb 100644 --- a/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py +++ b/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py @@ -644,7 +644,7 @@ class TestIsAllowedToCallVectorStoreEndpoint: mock_request.method = "GET" mock_request.url.path = "/azure_ai/indexes/dall-e-4/docs/search" mock_user_api_key = UserAPIKeyAuth( - token="b637312ebffb9745321224644430ba9e4916a291c8281f293d21182c5e80bc5a", + token="sk-test-mock-token-404", key_name="sk-...plNQ", metadata={ "allowed_vector_store_indexes": [ diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py b/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py index bd6bab9d61..b0a232a7bf 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py @@ -27,7 +27,7 @@ async def test_get_chat_completion_message_history_for_previous_response_id(): { "request_id": "chatcmpl-935b8dad-fdc2-466e-a8ca-e26e5a8a21bb", "call_type": "aresponses", - "api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "api_key": "sk-test-mock-api-key-123", "spend": 0.004803, "total_tokens": 329, "prompt_tokens": 11, @@ -68,7 +68,7 @@ async def test_get_chat_completion_message_history_for_previous_response_id(): { "request_id": "chatcmpl-370760c9-39fa-4db7-b034-d1f8d933c935", "call_type": "aresponses", - "api_key": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b", + "api_key": "sk-test-mock-api-key-123", "spend": 0.010437, "total_tokens": 967, "prompt_tokens": 339, diff --git a/tests/test_litellm/test_cost_calculator.py b/tests/test_litellm/test_cost_calculator.py index c26801ac3f..69e0f04e5e 100644 --- a/tests/test_litellm/test_cost_calculator.py +++ b/tests/test_litellm/test_cost_calculator.py @@ -855,7 +855,7 @@ def test_azure_image_generation_cost_calculator(): ImageObject( b64_json=None, revised_prompt="A futuristic, techno-inspired green duck wearing cool modern sunglasses. The duck has a sleek, metallic appearance with glowing neon green accents, standing on a high-tech urban background with holographic billboards and illuminated city lights in the distance. The duck's feathers have a glossy, high-tech sheen, resembling a robotic design but still maintaining its avian features. The scene has a vibrant, cyberpunk aesthetic with a neon color palette.", - url="https://dalleprodsec.blob.core.windows.net/private/images/caa17dc4-357d-4257-8938-eeea9baa8d0a/generated_00.png?se=2025-10-31T00%3A47%3A59Z&sig=KHRjLz3vMahbw94JtxL02S6t2AueeRMaiqj4z35HKDM%3D&ske=2025-11-05T00%3A26%3A20Z&skoid=e52d5ed7-0657-4f62-bc12-7e5dbb260a96&sks=b&skt=2025-10-29T00%3A26%3A20Z&sktid=33e01921-4d64-4f8c-a055-5bdaffd5e33d&skv=2020-10-02&sp=r&spr=https&sr=b&sv=2020-10-02", + url="test-azure-blob-url-with-sas-token", ) ], output_format=None, diff --git a/tests/test_spend_logs.py b/tests/test_spend_logs.py index 80dd8c9bcc..8aec1d5cc6 100644 --- a/tests/test_spend_logs.py +++ b/tests/test_spend_logs.py @@ -198,7 +198,7 @@ async def get_predict_spend_logs(session): { "date": "2024-03-09", "spend": 200000, - "api_key": "f19bdeb945164278fc11c1020d8dfd70465bffd931ed3cb2e1efa6326225b8b7", + "api_key": "sk-test-mock-api-key-456", } ] } diff --git a/ui/litellm-dashboard/src/components/cache_dashboard.tsx b/ui/litellm-dashboard/src/components/cache_dashboard.tsx index 38c0f1a8f4..65f02874cf 100644 --- a/ui/litellm-dashboard/src/components/cache_dashboard.tsx +++ b/ui/litellm-dashboard/src/components/cache_dashboard.tsx @@ -162,13 +162,13 @@ const CacheDashboard: React.FC = ({ accessToken, token, userRole /* Data looks like this - [{"api_key":"147dba2181f28914eea90eb484926c293cdcf7f5b5c9c3dd6a004d9e0f9fdb21","call_type":"acompletion","model":"llama3-8b-8192","total_rows":13,"cache_hit_true_rows":0}, - {"api_key":"8c23f021d0535c2e59abb7d83d0e03ccfb8db1b90e231ff082949d95df419e86","call_type":"None","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, - {"api_key":"88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b","call_type":"acompletion","model":"gpt-3.5-turbo","total_rows":19,"cache_hit_true_rows":0}, - {"api_key":"88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b","call_type":"aimage_generation","model":"","total_rows":3,"cache_hit_true_rows":0}, - {"api_key":"0ad4b3c03dcb6de0b5b8f761db798c6a8ae80be3fd1e2ea30c07ce6d5e3bf870","call_type":"None","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, - {"api_key":"034224b36e9769bc50e2190634abc3f97cad789b17ca80ac43b82f46cd5579b3","call_type":"","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, - {"api_key":"4f9c71cce0a2bb9a0b62ce6f0ebb3245b682702a8851d26932fa7e3b8ebfc755","call_type":"","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, + [{"api_key":"sk-test-mock-key-001","call_type":"acompletion","model":"llama3-8b-8192","total_rows":13,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-002","call_type":"None","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-123","call_type":"acompletion","model":"gpt-3.5-turbo","total_rows":19,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-123","call_type":"aimage_generation","model":"","total_rows":3,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-003","call_type":"None","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-004","call_type":"","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, + {"api_key":"sk-test-mock-key-005","call_type":"","model":"chatgpt-v-2","total_rows":1,"cache_hit_true_rows":0}, */ // What data we need for bar chat