mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-07 07:58:09 +00:00
Response transformation crashed with TypeError when counting tokens for multimodal (dict-shaped) embedding inputs, since encoding.encode() was called directly on the dict instead of its text parts. Also removed a dead, equally-buggy duplicate of the same loop in _transform_response. Separately, the embeddings guardrail handler silently skipped multimodal dict inputs instead of scanning them, letting prohibited text/image content bypass the configured guardrail. It now extracts and scans the text parts while leaving image parts untouched.
187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
from prisma import Prisma
|
|
import csv
|
|
import json
|
|
import asyncio
|
|
from datetime import datetime
|
|
from typing import Optional, List, Dict, Any
|
|
|
|
import os
|
|
|
|
## VARIABLES
|
|
DATABASE_URL = "postgresql://postgres:postgres@localhost:5432/litellm"
|
|
CSV_FILE_PATH = "./path_to_csv.csv"
|
|
|
|
os.environ["DATABASE_URL"] = DATABASE_URL
|
|
|
|
|
|
async def parse_csv_value(value: str, field_type: str) -> Any:
|
|
"""Parse CSV values according to their expected types"""
|
|
if value == "NULL" or value == "" or value is None:
|
|
return None
|
|
|
|
if field_type == "boolean":
|
|
return value.lower() == "true"
|
|
elif field_type == "float":
|
|
return float(value)
|
|
elif field_type == "int":
|
|
return int(value) if value.isdigit() else None
|
|
elif field_type == "bigint":
|
|
return int(value) if value.isdigit() else None
|
|
elif field_type == "datetime":
|
|
try:
|
|
return datetime.fromisoformat(value.replace("Z", "+00:00"))
|
|
except:
|
|
return None
|
|
elif field_type == "json":
|
|
try:
|
|
return value if value else json.dumps({})
|
|
except:
|
|
return json.dumps({})
|
|
elif field_type == "string_array":
|
|
# Handle string arrays like {default-models}
|
|
if value.startswith("{") and value.endswith("}"):
|
|
content = value[1:-1] # Remove braces
|
|
if content:
|
|
return [item.strip() for item in content.split(",")]
|
|
else:
|
|
return []
|
|
return []
|
|
else:
|
|
return value
|
|
|
|
|
|
async def migrate_verification_tokens():
|
|
"""Main migration function"""
|
|
prisma = Prisma()
|
|
await prisma.connect()
|
|
|
|
try:
|
|
# Read CSV file
|
|
csv_file_path = CSV_FILE_PATH
|
|
|
|
with open(csv_file_path, "r", encoding="utf-8") as file:
|
|
csv_reader = csv.DictReader(file)
|
|
|
|
processed_count = 0
|
|
error_count = 0
|
|
|
|
for row in csv_reader:
|
|
try:
|
|
# Replace 'default-team' with the specified UUID
|
|
team_id = row.get("team_id")
|
|
if team_id == "NULL" or team_id == "":
|
|
team_id = None
|
|
|
|
# Prepare data for insertion
|
|
verification_token_data = {
|
|
"token": row["token"],
|
|
"key_name": await parse_csv_value(row["key_name"], "string"),
|
|
"key_alias": await parse_csv_value(row["key_alias"], "string"),
|
|
"soft_budget_cooldown": await parse_csv_value(
|
|
row["soft_budget_cooldown"], "boolean"
|
|
),
|
|
"spend": await parse_csv_value(row["spend"], "float"),
|
|
"expires": await parse_csv_value(row["expires"], "datetime"),
|
|
"models": await parse_csv_value(row["models"], "string_array"),
|
|
"aliases": await parse_csv_value(row["aliases"], "json"),
|
|
"config": await parse_csv_value(row["config"], "json"),
|
|
"user_id": await parse_csv_value(row["user_id"], "string"),
|
|
"team_id": team_id,
|
|
"permissions": await parse_csv_value(
|
|
row["permissions"], "json"
|
|
),
|
|
"max_parallel_requests": await parse_csv_value(
|
|
row["max_parallel_requests"], "int"
|
|
),
|
|
"metadata": await parse_csv_value(row["metadata"], "json"),
|
|
"tpm_limit": await parse_csv_value(row["tpm_limit"], "bigint"),
|
|
"rpm_limit": await parse_csv_value(row["rpm_limit"], "bigint"),
|
|
"max_budget": await parse_csv_value(row["max_budget"], "float"),
|
|
"budget_duration": await parse_csv_value(
|
|
row["budget_duration"], "string"
|
|
),
|
|
"budget_reset_at": await parse_csv_value(
|
|
row["budget_reset_at"], "datetime"
|
|
),
|
|
"allowed_cache_controls": await parse_csv_value(
|
|
row["allowed_cache_controls"], "string_array"
|
|
),
|
|
"model_spend": await parse_csv_value(
|
|
row["model_spend"], "json"
|
|
),
|
|
"model_max_budget": await parse_csv_value(
|
|
row["model_max_budget"], "json"
|
|
),
|
|
"budget_id": await parse_csv_value(row["budget_id"], "string"),
|
|
"blocked": await parse_csv_value(row["blocked"], "boolean"),
|
|
"created_at": await parse_csv_value(
|
|
row["created_at"], "datetime"
|
|
),
|
|
"updated_at": await parse_csv_value(
|
|
row["updated_at"], "datetime"
|
|
),
|
|
"allowed_routes": await parse_csv_value(
|
|
row["allowed_routes"], "string_array"
|
|
),
|
|
"object_permission_id": await parse_csv_value(
|
|
row["object_permission_id"], "string"
|
|
),
|
|
"created_by": await parse_csv_value(
|
|
row["created_by"], "string"
|
|
),
|
|
"updated_by": await parse_csv_value(
|
|
row["updated_by"], "string"
|
|
),
|
|
"organization_id": await parse_csv_value(
|
|
row["organization_id"], "string"
|
|
),
|
|
}
|
|
|
|
# Remove None values to use database defaults
|
|
verification_token_data = {
|
|
k: v
|
|
for k, v in verification_token_data.items()
|
|
if v is not None
|
|
}
|
|
|
|
# Check if token already exists
|
|
existing_token = await prisma.litellm_verificationtoken.find_unique(
|
|
where={"token": verification_token_data["token"]}
|
|
)
|
|
|
|
if existing_token:
|
|
print(
|
|
f"Token {verification_token_data['token']} already exists, skipping..."
|
|
)
|
|
continue
|
|
|
|
# Insert the record
|
|
await prisma.litellm_verificationtoken.create(
|
|
data=verification_token_data
|
|
)
|
|
|
|
processed_count += 1
|
|
print(
|
|
f"Successfully migrated token: {verification_token_data['token']}"
|
|
)
|
|
|
|
except Exception as e:
|
|
error_count += 1
|
|
print(
|
|
f"Error processing row with token {row.get('token', 'unknown')}: {str(e)}"
|
|
)
|
|
continue
|
|
|
|
print(f"\nMigration completed!")
|
|
print(f"Successfully processed: {processed_count} records")
|
|
print(f"Errors encountered: {error_count} records")
|
|
|
|
except Exception as e:
|
|
print(f"Migration failed: {str(e)}")
|
|
|
|
finally:
|
|
await prisma.disconnect()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(migrate_verification_tokens())
|