Files
llm-intelligence/scripts/perplexity_pricing_lib.go

151 lines
4.1 KiB
Go
Raw Normal View History

//go:build llm_script
package main
import (
"fmt"
"regexp"
"strings"
)
const (
defaultPerplexityPricingFetchURL = "https://docs.perplexity.ai/docs/agent-api/models.md"
defaultPerplexityPricingSourceURL = "https://docs.perplexity.ai/docs/agent-api/models"
)
var markdownLinkPattern = regexp.MustCompile(`\[(.*?)\]\((https://[^)]+)\)`)
func parsePerplexityPricingCatalog(raw string) ([]officialPricingRecord, error) {
lines := strings.Split(raw, "\n")
records := make([]officialPricingRecord, 0)
header := []string(nil)
modelIndex := -1
inputIndex := -1
outputIndex := -1
docIndex := -1
for _, line := range lines {
line = strings.TrimSpace(line)
if !strings.HasPrefix(line, "|") {
continue
}
parts := splitMarkdownTableRow(line)
if len(parts) == 0 {
continue
}
if header == nil {
header = parts
modelIndex, inputIndex, outputIndex, docIndex = detectPerplexityTableColumns(parts)
continue
}
if isMarkdownTableSeparator(parts) {
continue
}
if modelIndex < 0 || inputIndex < 0 || outputIndex < 0 || modelIndex >= len(parts) || inputIndex >= len(parts) || outputIndex >= len(parts) {
continue
}
modelPath := strings.Trim(parts[modelIndex], "`")
inputCell := parts[inputIndex]
outputCell := parts[outputIndex]
inputPrice, ok := firstDollarPrice(inputCell)
if !ok {
continue
}
outputPrice, ok := firstDollarPrice(outputCell)
if !ok {
continue
}
sourceURL := defaultPerplexityPricingSourceURL
if docIndex >= 0 && docIndex < len(parts) {
if matches := markdownLinkPattern.FindStringSubmatch(parts[docIndex]); len(matches) == 3 {
sourceURL = matches[2]
}
}
providerName := providerFromModelPath(modelPath)
providerNameCn, providerCountry, providerWebsite := providerMetadata(providerName)
record := officialPricingRecord{
ModelID: normalizeExternalID("perplexity", modelPath),
ModelName: modelPath,
ProviderName: providerName,
ProviderNameCn: providerNameCn,
ProviderCountry: providerCountry,
ProviderWebsite: providerWebsite,
OperatorName: "Perplexity API",
OperatorNameCn: "Perplexity API",
OperatorCountry: "US",
OperatorWebsite: "https://docs.perplexity.ai",
OperatorType: "relay",
Region: "global",
Currency: "USD",
InputPrice: inputPrice,
OutputPrice: outputPrice,
SourceURL: defaultPerplexityPricingSourceURL,
ModelSourceURL: sourceURL,
DateConfidence: "unknown",
DateSourceKind: "official_pricing",
Modality: detectModality(modelPath),
}
record.IsFree = record.InputPrice == 0 && record.OutputPrice == 0
records = append(records, record)
}
if len(records) == 0 {
return nil, fmt.Errorf("unexpected perplexity pricing content")
}
return records, nil
}
func splitMarkdownTableRow(line string) []string {
trimmed := strings.TrimSpace(line)
trimmed = strings.TrimPrefix(trimmed, "|")
trimmed = strings.TrimSuffix(trimmed, "|")
if trimmed == "" {
return nil
}
parts := strings.Split(trimmed, "|")
result := make([]string, 0, len(parts))
for _, part := range parts {
result = append(result, strings.TrimSpace(part))
}
return result
}
func detectPerplexityTableColumns(header []string) (int, int, int, int) {
modelIndex := -1
inputIndex := -1
outputIndex := -1
docIndex := -1
for i, col := range header {
lower := strings.ToLower(strings.TrimSpace(col))
switch {
case strings.Contains(lower, "model") && modelIndex == -1:
modelIndex = i
case strings.Contains(lower, "input") && strings.Contains(lower, "price") && inputIndex == -1:
inputIndex = i
case strings.Contains(lower, "output") && strings.Contains(lower, "price") && outputIndex == -1:
outputIndex = i
case (strings.Contains(lower, "documentation") || strings.Contains(lower, "docs")) && docIndex == -1:
docIndex = i
}
}
return modelIndex, inputIndex, outputIndex, docIndex
}
func isMarkdownTableSeparator(parts []string) bool {
if len(parts) == 0 {
return false
}
for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed == "" {
return false
}
for _, ch := range trimmed {
if ch != '-' && ch != ':' {
return false
}
}
}
return true
}