Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6866,6 +6866,27 @@ exports[`Registry Snapshots endpoint configurations snapshot 1`] = `
"*",
],
},
"glm-4.6:zai": {
"context": 128000,
"crossRegion": false,
"maxTokens": 4096,
"modelId": "glm-4-plus",
"parameters": [
"functions",
"max_tokens",
"response_format",
"stop",
"temperature",
"tool_choice",
"tools",
"top_p",
],
"provider": "zai",
"ptbEnabled": true,
"regions": [
"*",
],
},
"glm-4.7:baseten": {
"context": 200000,
"crossRegion": false,
Expand Down Expand Up @@ -7016,6 +7037,27 @@ exports[`Registry Snapshots endpoint configurations snapshot 1`] = `
"*",
],
},
"glm-4.7:zai": {
"context": 128000,
"crossRegion": false,
"maxTokens": 4096,
"modelId": "glm-4-plus",
"parameters": [
"functions",
"max_tokens",
"response_format",
"stop",
"temperature",
"tool_choice",
"tools",
"top_p",
],
"provider": "zai",
"ptbEnabled": true,
"regions": [
"*",
],
},
},
}
`;
Expand Down Expand Up @@ -7440,6 +7482,8 @@ exports[`Registry Snapshots model coverage snapshot 1`] = `
"fireworks",
"novita",
"novita",
"zai",
"zai",
],
}
`;
Expand Down Expand Up @@ -9572,6 +9616,13 @@ exports[`Registry Snapshots pricing snapshot 1`] = `
"threshold": 0,
},
],
"zai": [
{
"input": 0.00000714,
"output": 0.00000714,
"threshold": 0,
},
],
},
}
`;
Expand Down Expand Up @@ -9877,6 +9928,7 @@ exports[`Registry Snapshots verify registry state 1`] = `
"baseten",
"canopywave",
"novita",
"zai",
],
},
{
Expand All @@ -9887,6 +9939,7 @@ exports[`Registry Snapshots verify registry state 1`] = `
"cerebras",
"fireworks",
"novita",
"zai",
],
},
{
Expand Down Expand Up @@ -10522,6 +10575,10 @@ exports[`Registry Snapshots verify registry state 1`] = `
"modelCount": 8,
"provider": "xai",
},
{
"modelCount": 2,
"provider": "zai",
},
],
"ptbEnabledModels": [
"chatgpt-4o-latest",
Expand Down Expand Up @@ -10639,9 +10696,9 @@ exports[`Registry Snapshots verify registry state 1`] = `
"claude-3.5-haiku:anthropic:*",
],
"totalArchivedConfigs": 0,
"totalEndpoints": 317,
"totalModelProviderConfigs": 317,
"totalEndpoints": 319,
"totalModelProviderConfigs": 319,
"totalModelsWithPtb": 105,
"totalProviders": 21,
"totalProviders": 22,
}
`;
56 changes: 56 additions & 0 deletions packages/cost/models/authors/zai/glm-4/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,62 @@ export const endpoints = {
"*": {},
},
},
"glm-4.6:zai": {
providerModelId: "glm-4-plus",
provider: "zai",
author: "zai",
pricing: [
{
threshold: 0,
input: 0.00000714, // 0.05 CNY/1K tokens ≈ $0.00714/1K
output: 0.00000714,
},
],
contextLength: 128_000,
maxCompletionTokens: 4_096,
supportedParameters: [
"functions",
"tool_choice",
"tools",
"response_format",
"max_tokens",
"temperature",
"top_p",
"stop",
],
ptbEnabled: true,
endpointConfigs: {
"*": {},
},
},
"glm-4.7:zai": {
providerModelId: "glm-4-plus",
provider: "zai",
author: "zai",
pricing: [
{
threshold: 0,
input: 0.00000714, // 0.05 CNY/1K tokens ≈ $0.00714/1K
output: 0.00000714,
},
],
contextLength: 128_000,
maxCompletionTokens: 4_096,
supportedParameters: [
"functions",
"tool_choice",
"tools",
"response_format",
"max_tokens",
"temperature",
"top_p",
"stop",
],
ptbEnabled: true,
endpointConfigs: {
"*": {},
},
},
} satisfies Partial<
Record<
`${ZaiModelName}:${ModelProviderName}` | ZaiModelName,
Expand Down
13 changes: 13 additions & 0 deletions packages/cost/models/build-indexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export interface ModelIndexes {
providerModelIdToConfig: Map<string, ModelProviderConfig>;
providerModelIdAliasToConfig: Map<string, ModelProviderConfig>;
modelToArchivedEndpointConfigs: Map<string, ModelProviderConfig>;
// Reverse lookup: provider model ID -> canonical model ID (without needing to know the provider)
providerModelIdToCanonicalModelId: Map<string, ModelName>;
}

export function buildIndexes(
Expand Down Expand Up @@ -92,6 +94,7 @@ export function buildIndexes(
new Map();
const modelToArchivedEndpointConfigs: Map<string, ModelProviderConfig> =
new Map();
const providerModelIdToCanonicalModelId: Map<string, ModelName> = new Map();

for (const [configKey, config] of Object.entries(modelProviderConfigs)) {
const typedConfigKey = configKey as ModelProviderConfigId;
Expand All @@ -115,6 +118,15 @@ export function buildIndexes(
}
}

// Store reverse lookup: providerModelId -> canonical model ID
// This allows finding the canonical model from any provider model ID
providerModelIdToCanonicalModelId.set(config.providerModelId, modelName);
if (config.providerModelIdAliases) {
for (const alias of config.providerModelIdAliases) {
providerModelIdToCanonicalModelId.set(alias, modelName);
}
}

// Track provider to models mapping
if (!providerToModels.has(provider)) {
providerToModels.set(provider, new Set());
Expand Down Expand Up @@ -219,5 +231,6 @@ export function buildIndexes(
providerModelIdToConfig,
providerModelIdAliasToConfig,
modelToArchivedEndpointConfigs,
providerModelIdToCanonicalModelId,
};
}
5 changes: 4 additions & 1 deletion packages/cost/models/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { OpenRouterProvider } from "./openrouter";
import { PerplexityProvider } from "./perplexity";
import { VertexProvider } from "./vertex";
import { XAIProvider } from "./xai";
import { ZaiProvider } from "./zai";

// Create singleton instances (stateless, so safe to share)
export const providers = {
Expand All @@ -42,7 +43,8 @@ export const providers = {
openrouter: new OpenRouterProvider(),
perplexity: new PerplexityProvider(),
vertex: new VertexProvider(),
xai: new XAIProvider()
xai: new XAIProvider(),
zai: new ZaiProvider(),
} as const;

export type ModelProviderName = keyof typeof providers;
Expand Down Expand Up @@ -87,6 +89,7 @@ export const ResponsesAPIEnabledProviders: ModelProviderName[] = [
"xai",
"baseten",
"fireworks",
"zai",

// anthropic and chat completions provider
"vertex"
Expand Down
1 change: 1 addition & 0 deletions packages/cost/models/providers/priorities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const PROVIDER_PRIORITIES: Record<ModelProviderName, number> = {
perplexity: 4,
vertex: 4,
xai: 4,
zai: 4,

// Priority 5: Secondary primary providers
"google-ai-studio": 5,
Expand Down
14 changes: 14 additions & 0 deletions packages/cost/models/providers/zai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseProvider } from "./base";
import type { Endpoint, RequestParams } from "../types";

export class ZaiProvider extends BaseProvider {
readonly displayName = "ZhipuAI";
readonly baseUrl = "https://open.bigmodel.cn/";
readonly auth = "api-key" as const;
readonly pricingPages = ["https://open.bigmodel.cn/pricing"];
readonly modelPages = ["https://open.bigmodel.cn/dev/howuse/model"];

buildUrl(endpoint: Endpoint, requestParams: RequestParams): string {
return `${this.baseUrl}api/paas/v4/chat/completions`;
}
}
20 changes: 20 additions & 0 deletions packages/cost/models/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,25 @@ function getModelProviderConfigByVersion(
return ok(archivedConfig || null);
}

/**
* Find the canonical model ID from a provider model ID.
* This is useful when a request uses a provider-specific model ID (e.g., "zai-glm-4.7")
* and we need to find the canonical model ID (e.g., "glm-4.7").
*
* @param providerModelId - The provider-specific model ID (e.g., "zai-glm-4.7", "accounts/fireworks/models/glm-4p7")
* @returns The canonical model ID if found, null otherwise
*/
function findCanonicalModelId(providerModelId: string): string | null {
// First check if it's already a canonical model ID
if (allModels[providerModelId as keyof typeof allModels]) {
return providerModelId;
}

// Look up in the reverse mapping
const canonical = indexes.providerModelIdToCanonicalModelId.get(providerModelId);
return canonical ?? null;
}

export const registry = {
getAllModelIds,
getAllModelsWithIds,
Expand All @@ -294,4 +313,5 @@ export const registry = {
getModelProviderEntry,
getModelProviderConfigByVersion,
getAuthorByModel,
findCanonicalModelId,
};
1 change: 1 addition & 0 deletions packages/cost/usage/getUsageProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function getUsageProcessor(
case "fireworks":
case "cerebras":
case "perplexity":
case "zai":
return new OpenAIUsageProcessor();
case "anthropic":
return new AnthropicUsageProcessor();
Expand Down
10 changes: 10 additions & 0 deletions valhalla/jawn/src/controllers/public/modelRegistryController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ interface ModelRegistryResponse {
authors: string[];
capabilities: ModelCapability[];
};
// Map of provider model IDs to canonical model IDs
// Useful for resolving provider-specific model names (e.g., "zai-glm-4.7" -> "glm-4.7")
providerModelIdMap?: Record<string, string>;
}

@Route("/v1/public/model-registry")
Expand Down Expand Up @@ -400,6 +403,7 @@ export class ModelRegistryController extends Controller {
const availableProviders = new Set<string>();
const availableAuthors = new Set<string>();
const availableCapabilities = new Set<ModelCapability>();
const providerModelIdMap: Record<string, string> = {};

models.forEach((model) => {
availableAuthors.add(model.author);
Expand All @@ -421,6 +425,10 @@ export class ModelRegistryController extends Controller {
) {
availableCapabilities.add("caching");
}
// Build provider model ID to canonical model ID mapping
if (ep.endpoint?.providerModelId) {
providerModelIdMap[ep.endpoint.providerModelId] = model.id;
}
});
});
const providersWithDisplayNames = Array.from(availableProviders)
Expand All @@ -439,11 +447,13 @@ export class ModelRegistryController extends Controller {
authors: Array.from(availableAuthors).sort(),
capabilities: Array.from(availableCapabilities).sort(),
},
providerModelIdMap,
});
} catch (error) {
console.error("Error fetching model registry:", error);
this.setStatus(500);
return err("Internal server error while fetching model registry");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@ const PlaygroundHeader = ({
onDismissUnsupportedModelWarning,
}: PlaygroundHeaderProps) => {
const [modelListOpen, setModelListOpen] = useState<boolean>(false);
const { data: playgroundModels, isLoading: modelsLoading } =
const { data: modelRegistryData, isLoading: modelsLoading } =
useModelRegistry();
const playgroundModels = modelRegistryData?.models ?? [];

// Get display name for selected model
const selectedModelData = playgroundModels?.find(
const selectedModelData = playgroundModels.find(
(m) => m.id === selectedModel,
);
const displayName =
Expand Down
Loading
Loading