396 lines
20 KiB
Go
396 lines
20 KiB
Go
//go:build llm_script
|
||
|
||
package main
|
||
|
||
import (
|
||
"database/sql"
|
||
"log"
|
||
"os"
|
||
"strings"
|
||
"time"
|
||
|
||
_ "github.com/lib/pq"
|
||
)
|
||
|
||
type ModelPricing struct {
|
||
ModelID string
|
||
ModelName string
|
||
ProviderName string
|
||
ProviderCountry string
|
||
OperatorName string
|
||
OperatorType string
|
||
Region string
|
||
Currency string
|
||
InputPrice float64
|
||
OutputPrice float64
|
||
ContextLength int
|
||
IsFree bool
|
||
SourceURL string
|
||
ModelSourceURL string
|
||
ReleaseDate string
|
||
DateConfidence string
|
||
DateSourceKind string
|
||
Modality string
|
||
SceneTags []string
|
||
}
|
||
|
||
func releaseDateValue(raw string) any {
|
||
if raw == "" {
|
||
return nil
|
||
}
|
||
parsed, err := time.Parse("2006-01-02", raw)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
return parsed
|
||
}
|
||
|
||
type zhipuModelMetadata struct {
|
||
Prefix string
|
||
ReleaseDate string
|
||
ModelSourceURL string
|
||
DateConfidence string
|
||
DateSourceKind string
|
||
}
|
||
|
||
var zhipuModelMetadataRules = []zhipuModelMetadata{
|
||
{
|
||
Prefix: "glm-5-turbo",
|
||
ReleaseDate: "2026-03-15",
|
||
ModelSourceURL: "https://www.zhipuai.cn/en/research/155",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-5.1",
|
||
ReleaseDate: "2026-04-07",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/research",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-5",
|
||
ReleaseDate: "2026-02-11",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/research/154",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-4.7-flash",
|
||
ReleaseDate: "2026-01-19",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/news/148",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-4.7",
|
||
ReleaseDate: "2025-12-21",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/research",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-4.6v",
|
||
ReleaseDate: "2025-12-07",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/research/144",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-tts",
|
||
ReleaseDate: "2025-12-10",
|
||
ModelSourceURL: "https://www.zhipuai.cn/zh/research",
|
||
DateConfidence: "official_primary",
|
||
DateSourceKind: "official_announcement",
|
||
},
|
||
{
|
||
Prefix: "glm-4.5-air",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4.5v",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4-air",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4-long",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4v",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "chatglm3",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4-9b",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4-0520",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-realtime",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-asr",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
{
|
||
Prefix: "glm-4-voice",
|
||
DateConfidence: "unknown",
|
||
DateSourceKind: "catalog_backfill",
|
||
},
|
||
}
|
||
|
||
func enrichZhipuModelMetadata(model ModelPricing) ModelPricing {
|
||
for _, metadata := range zhipuModelMetadataRules {
|
||
if strings.HasPrefix(model.ModelID, metadata.Prefix) {
|
||
if metadata.ReleaseDate != "" {
|
||
model.ReleaseDate = metadata.ReleaseDate
|
||
}
|
||
if metadata.ModelSourceURL != "" {
|
||
model.ModelSourceURL = metadata.ModelSourceURL
|
||
}
|
||
if metadata.DateConfidence != "" {
|
||
model.DateConfidence = metadata.DateConfidence
|
||
}
|
||
if metadata.DateSourceKind != "" {
|
||
model.DateSourceKind = metadata.DateSourceKind
|
||
}
|
||
return model
|
||
}
|
||
}
|
||
if model.ModelSourceURL == "" {
|
||
model.ModelSourceURL = model.SourceURL
|
||
}
|
||
if model.DateConfidence == "" {
|
||
model.DateConfidence = "unknown"
|
||
}
|
||
if model.DateSourceKind == "" {
|
||
model.DateSourceKind = "unknown"
|
||
}
|
||
return model
|
||
}
|
||
|
||
func hasExplicitModelMetadata(model ModelPricing) bool {
|
||
return strings.TrimSpace(model.ReleaseDate) != "" ||
|
||
firstNonEmpty(model.ModelSourceURL) != "" && model.ModelSourceURL != model.SourceURL ||
|
||
strings.TrimSpace(model.DateConfidence) != "" && model.DateConfidence != "unknown" ||
|
||
strings.TrimSpace(model.DateSourceKind) != "" && model.DateSourceKind != "unknown"
|
||
}
|
||
|
||
func main() {
|
||
dsn := os.Getenv("DATABASE_URL")
|
||
if dsn == "" {
|
||
dsn = "postgres://long@/llm_intelligence?host=/var/run/postgresql"
|
||
}
|
||
|
||
db, err := sql.Open("postgres", dsn)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
// 智谱AI定价数据(从第一次无头浏览器抓取中提取)
|
||
prices := []ModelPricing{
|
||
// GLM-5.1系列
|
||
{ModelID: "glm-5.1", ModelName: "GLM-5.1", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 6.0, OutputPrice: 24.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理", "代码"}},
|
||
{ModelID: "glm-5.1-32k", ModelName: "GLM-5.1 (32K+)", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 8.0, OutputPrice: 28.0, ContextLength: 200000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理", "代码"}},
|
||
|
||
// GLM-5-Turbo
|
||
{ModelID: "glm-5-turbo", ModelName: "GLM-5-Turbo", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 5.0, OutputPrice: 22.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理"}},
|
||
{ModelID: "glm-5-turbo-32k", ModelName: "GLM-5-Turbo (32K+)", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 7.0, OutputPrice: 26.0, ContextLength: 200000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理"}},
|
||
|
||
// GLM-5
|
||
{ModelID: "glm-5", ModelName: "GLM-5", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 4.0, OutputPrice: 18.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理"}},
|
||
{ModelID: "glm-5-32k", ModelName: "GLM-5 (32K+)", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 6.0, OutputPrice: 22.0, ContextLength: 200000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理"}},
|
||
|
||
// GLM-4.7
|
||
{ModelID: "glm-4.7", ModelName: "GLM-4.7", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 2.0, OutputPrice: 8.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理", "代码"}},
|
||
{ModelID: "glm-4.7-32k", ModelName: "GLM-4.7 (32K+)", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 4.0, OutputPrice: 16.0, ContextLength: 200000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理", "代码"}},
|
||
|
||
// GLM-4.5-Air
|
||
{ModelID: "glm-4.5-air", ModelName: "GLM-4.5-Air", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.8, OutputPrice: 2.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
{ModelID: "glm-4.5-air-32k", ModelName: "GLM-4.5-Air (32K+)", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 1.2, OutputPrice: 8.0, ContextLength: 128000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
|
||
// GLM-4.7-FlashX
|
||
{ModelID: "glm-4.7-flashx", ModelName: "GLM-4.7-FlashX", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.5, OutputPrice: 3.0, ContextLength: 200000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
|
||
// GLM-4.7-Flash (Free)
|
||
{ModelID: "glm-4.7-flash", ModelName: "GLM-4.7-Flash", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0, OutputPrice: 0, ContextLength: 200000, IsFree: true, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
|
||
// GLM-4.6V (Vision)
|
||
{ModelID: "glm-4.6v", ModelName: "GLM-4.6V", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 2.0, OutputPrice: 6.0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "multimodal", SceneTags: []string{"视觉", "对话"}},
|
||
|
||
// GLM-4.6V-FlashX
|
||
{ModelID: "glm-4.6v-flashx", ModelName: "GLM-4.6V-FlashX", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.15, OutputPrice: 1.5, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "multimodal", SceneTags: []string{"视觉", "对话"}},
|
||
|
||
// GLM-4.5V
|
||
{ModelID: "glm-4.5v", ModelName: "GLM-4.5V", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 2.0, OutputPrice: 6.0, ContextLength: 32000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "multimodal", SceneTags: []string{"视觉", "对话"}},
|
||
|
||
// GLM-4系列 (Legacy)
|
||
{ModelID: "glm-4-0520", ModelName: "GLM-4-0520", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 100.0, OutputPrice: 50.0, ContextLength: 128000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "推理"}},
|
||
{ModelID: "glm-4-air", ModelName: "GLM-4-Air", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.5, OutputPrice: 0.25, ContextLength: 128000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
{ModelID: "glm-4-airx", ModelName: "GLM-4-AirX", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 10.0, OutputPrice: 10.0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "极速"}},
|
||
{ModelID: "glm-4-long", ModelName: "GLM-4-Long", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 1.0, OutputPrice: 0.5, ContextLength: 1000000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话", "长文本"}},
|
||
|
||
// GLM-4V (Vision Legacy)
|
||
{ModelID: "glm-4v-plus", ModelName: "GLM-4V-Plus", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 4.0, OutputPrice: 4.0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "multimodal", SceneTags: []string{"视觉", "对话"}},
|
||
{ModelID: "glm-4v", ModelName: "GLM-4V", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 50.0, OutputPrice: 50.0, ContextLength: 2000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "multimodal", SceneTags: []string{"视觉", "对话"}},
|
||
|
||
// ChatGLM3
|
||
{ModelID: "chatglm3-6b", ModelName: "ChatGLM3-6B", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0, OutputPrice: 0, ContextLength: 8000, IsFree: true, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
|
||
// GLM-4-9B
|
||
{ModelID: "glm-4-9b", ModelName: "GLM-4-9B", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0, OutputPrice: 0, ContextLength: 8000, IsFree: true, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "text", SceneTags: []string{"对话"}},
|
||
|
||
// GLM-Realtime
|
||
{ModelID: "glm-realtime-flash", ModelName: "GLM-Realtime-Flash", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.18, OutputPrice: 0.18, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"实时", "音视频"}},
|
||
{ModelID: "glm-realtime-air", ModelName: "GLM-Realtime-Air", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 0.3, OutputPrice: 0.3, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"实时", "音视频"}},
|
||
|
||
// GLM-TTS
|
||
{ModelID: "glm-tts", ModelName: "GLM-TTS", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 2.0, OutputPrice: 0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"语音合成"}},
|
||
{ModelID: "glm-tts-clone", ModelName: "GLM-TTS-Clone", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 6.0, OutputPrice: 0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"音色克隆"}},
|
||
|
||
// GLM-ASR
|
||
{ModelID: "glm-asr-2512", ModelName: "GLM-ASR-2512", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 16.0, OutputPrice: 0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"语音识别"}},
|
||
|
||
// GLM-4-Voice
|
||
{ModelID: "glm-4-voice", ModelName: "GLM-4-Voice", ProviderName: "Zhipu AI", ProviderCountry: "CN", OperatorName: "Zhipu", OperatorType: "official", Region: "CN", Currency: "CNY", InputPrice: 80.0, OutputPrice: 80.0, ContextLength: 8000, SourceURL: "https://open.bigmodel.cn/pricing", Modality: "audio", SceneTags: []string{"语音模型"}},
|
||
}
|
||
batchID := "manual-seed"
|
||
|
||
log.Printf("Importing %d Zhipu AI models...", len(prices))
|
||
|
||
// Save to database
|
||
for _, rawPricing := range prices {
|
||
p := enrichZhipuModelMetadata(rawPricing)
|
||
// Find or create provider
|
||
var providerID int64
|
||
err := db.QueryRow("SELECT id FROM model_provider WHERE name = $1", p.ProviderName).Scan(&providerID)
|
||
if err == sql.ErrNoRows {
|
||
err = db.QueryRow(
|
||
"INSERT INTO model_provider (name, country, website, status) VALUES ($1, $2, $3, 'active') RETURNING id",
|
||
p.ProviderName, p.ProviderCountry, "",
|
||
).Scan(&providerID)
|
||
}
|
||
if err != nil {
|
||
log.Printf("Provider error: %v", err)
|
||
continue
|
||
}
|
||
|
||
// Find or create operator
|
||
var operatorID int64
|
||
err = db.QueryRow("SELECT id FROM operator WHERE name = $1", p.OperatorName).Scan(&operatorID)
|
||
if err == sql.ErrNoRows {
|
||
err = db.QueryRow(
|
||
"INSERT INTO operator (name, country, status) VALUES ($1, $2, 'active') RETURNING id",
|
||
p.OperatorName, p.ProviderCountry,
|
||
).Scan(&operatorID)
|
||
}
|
||
if err != nil {
|
||
log.Printf("Operator error: %v", err)
|
||
continue
|
||
}
|
||
|
||
// Find or create model
|
||
var modelID int64
|
||
err = db.QueryRow("SELECT id FROM models WHERE external_id = $1", p.ModelID).Scan(&modelID)
|
||
if err == sql.ErrNoRows {
|
||
err = db.QueryRow(
|
||
`INSERT INTO models (external_id, name, provider_id, modality, context_length, status, source, batch_id, source_url, release_date, date_confidence, date_source_kind)
|
||
VALUES ($1, $2, $3, $4, $5, 'active', $6, $7, $8, $9, $10, $11) RETURNING id`,
|
||
p.ModelID, p.ModelName, providerID, p.Modality, p.ContextLength, p.OperatorName, batchID, firstNonEmpty(p.ModelSourceURL, p.SourceURL), releaseDateValue(p.ReleaseDate), p.DateConfidence, p.DateSourceKind,
|
||
).Scan(&modelID)
|
||
}
|
||
if err != nil {
|
||
log.Printf("Model error for %s: %v", p.ModelID, err)
|
||
continue
|
||
}
|
||
if _, err := db.Exec(
|
||
`UPDATE models
|
||
SET source_url = CASE
|
||
WHEN $4 THEN $2
|
||
ELSE COALESCE(NULLIF(source_url, ''), $2)
|
||
END,
|
||
release_date = CASE
|
||
WHEN $4 THEN $3::date
|
||
ELSE COALESCE(release_date, $3::date)
|
||
END,
|
||
date_confidence = CASE
|
||
WHEN $4 THEN $5
|
||
ELSE COALESCE(NULLIF(date_confidence, ''), $5, 'unknown')
|
||
END,
|
||
date_source_kind = CASE
|
||
WHEN $4 THEN $6
|
||
ELSE COALESCE(NULLIF(date_source_kind, ''), $6, 'unknown')
|
||
END,
|
||
updated_at = CURRENT_TIMESTAMP
|
||
WHERE id = $1`,
|
||
modelID, firstNonEmpty(p.ModelSourceURL, p.SourceURL), releaseDateValue(p.ReleaseDate), hasExplicitModelMetadata(p), p.DateConfidence, p.DateSourceKind,
|
||
); err != nil {
|
||
log.Printf("Model metadata update error for %s: %v", p.ModelID, err)
|
||
}
|
||
|
||
// Insert pricing
|
||
sourceType := p.OperatorType
|
||
freeQuota := ""
|
||
freeLimitations := "[]"
|
||
rateLimit := "{}"
|
||
if p.IsFree {
|
||
sourceType = "free_tier"
|
||
freeQuota = "Imported free-tier pricing entry"
|
||
freeLimitations = `["See source_url for current quota and policy"]`
|
||
}
|
||
_, err = db.Exec(
|
||
`INSERT INTO region_pricing
|
||
(model_id, operator_id, region, currency, input_price_per_mtok, output_price_per_mtok, is_free, effective_date, source_url, source_type, free_quota, free_limitations, rate_limit)
|
||
VALUES ($1, $2, $3, $4, $5, $6, $7, CURRENT_DATE, $8, $9, $10, $11, $12)
|
||
ON CONFLICT (model_id, operator_id, region, currency, effective_date)
|
||
DO UPDATE SET input_price_per_mtok = EXCLUDED.input_price_per_mtok,
|
||
output_price_per_mtok = EXCLUDED.output_price_per_mtok,
|
||
is_free = EXCLUDED.is_free,
|
||
source_type = EXCLUDED.source_type,
|
||
free_quota = EXCLUDED.free_quota,
|
||
free_limitations = EXCLUDED.free_limitations,
|
||
rate_limit = EXCLUDED.rate_limit,
|
||
updated_at = CURRENT_TIMESTAMP`,
|
||
modelID, operatorID, p.Region, p.Currency, p.InputPrice, p.OutputPrice, p.IsFree, p.SourceURL,
|
||
sourceType, freeQuota, freeLimitations, rateLimit,
|
||
)
|
||
if err != nil {
|
||
log.Printf("Pricing error for %s: %v", p.ModelID, err)
|
||
continue
|
||
}
|
||
}
|
||
|
||
log.Printf("Successfully imported %d Zhipu AI models", len(prices))
|
||
}
|
||
|
||
func firstNonEmpty(values ...string) string {
|
||
for _, value := range values {
|
||
if value != "" {
|
||
return value
|
||
}
|
||
}
|
||
return ""
|
||
}
|