//go:build llm_script package main import ( "fmt" "regexp" "strings" ) const defaultYoudaoPricingURL = "https://ai.youdao.com/new/model-service" var youdaoCardPattern = regexp.MustCompile(`(?s)([A-Za-z0-9.+\- ]+)\n([A-Za-z][A-Za-z0-9 ]+)\n.*?上下文长度\s*([0-9A-Za-z., ]+)\n.*?输入[::]?\s*¥?([\d.]+)\n.*?输出[::]?\s*¥?([\d.]+)\n.*?(查看详情|即将上线)`) func parseYoudaoPricingCatalog(raw string) ([]officialPricingRecord, error) { matches := youdaoCardPattern.FindAllStringSubmatch(raw, -1) if len(matches) == 0 { return nil, fmt.Errorf("unexpected youdao pricing content") } records := make([]officialPricingRecord, 0, len(matches)) for _, match := range matches { modelName := strings.TrimSpace(match[1]) providerName := normalizeYoudaoProvider(match[2]) if strings.TrimSpace(match[6]) != "查看详情" { continue } providerNameCn, providerCountry, providerWebsite := providerMetadata(providerName) record := officialPricingRecord{ ModelID: normalizeExternalID("youdao", modelName), ModelName: modelName, ProviderName: providerName, ProviderNameCn: providerNameCn, ProviderCountry: providerCountry, ProviderWebsite: providerWebsite, OperatorName: "Youdao Zhiyun MaaS", OperatorNameCn: "有道智云 MaaS", OperatorCountry: "CN", OperatorWebsite: "https://sf.163.com", OperatorType: "relay", Region: "CN", Currency: "CNY", InputPrice: mustParseSubscriptionPrice(match[4]), OutputPrice: mustParseSubscriptionPrice(match[5]), ContextLength: parseContextLengthCommon(match[3]), SourceURL: defaultYoudaoPricingURL, ModelSourceURL: defaultYoudaoPricingURL, DateConfidence: "unknown", DateSourceKind: "official_product_page", Modality: detectModality(modelName), } record.IsFree = record.InputPrice == 0 && record.OutputPrice == 0 records = append(records, record) } if len(records) == 0 { return nil, fmt.Errorf("no active youdao pricing cards found") } return records, nil } func normalizeYoudaoProvider(raw string) string { switch strings.ToLower(strings.TrimSpace(raw)) { case "deepseek": return "DeepSeek" case "qwen": return "Qwen" case "kimi": return "Moonshot AI" case "minimax": return "MiniMax" case "zhipu": return "Zhipu AI" default: return strings.TrimSpace(raw) } }