forked from niuniu/llm-intelligence
feat(intraday): monitor DeepSeek official page drift
This commit is contained in:
127
scripts/deepseek_news_signature_guard_lib.go
Normal file
127
scripts/deepseek_news_signature_guard_lib.go
Normal file
@@ -0,0 +1,127 @@
|
||||
//go:build llm_script
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type deepseekNewsSignatureGuardConfig struct {
|
||||
URL string
|
||||
Fixture string
|
||||
SnapshotDir string
|
||||
BaselinePath string
|
||||
Timeout time.Duration
|
||||
AllowBootstrap bool
|
||||
}
|
||||
|
||||
type deepseekNewsSignatureGuardResult struct {
|
||||
SnapshotPath string
|
||||
SignaturePath string
|
||||
BaselinePath string
|
||||
DriftDetected bool
|
||||
BaselineInitialized bool
|
||||
PreviousBaselineHash string
|
||||
CurrentSignature deepseekNewsStructureSignature
|
||||
}
|
||||
|
||||
const defaultDeepSeekNewsFetchURL = "https://api-docs.deepseek.com/news/news250120"
|
||||
|
||||
func runDeepSeekNewsSignatureGuard(cfg deepseekNewsSignatureGuardConfig, now time.Time) (deepseekNewsSignatureGuardResult, error) {
|
||||
snapshotDir := cfg.SnapshotDir
|
||||
if snapshotDir == "" {
|
||||
snapshotDir = filepath.Join("logs", "deepseek-news-snapshots")
|
||||
}
|
||||
if err := os.MkdirAll(snapshotDir, 0o755); err != nil {
|
||||
return deepseekNewsSignatureGuardResult{}, fmt.Errorf("mkdir snapshot dir: %w", err)
|
||||
}
|
||||
snapshotPath, signaturePath := resolveDeepSeekNewsSnapshotPaths("", "", snapshotDir, now)
|
||||
baselinePath := cfg.BaselinePath
|
||||
if baselinePath == "" {
|
||||
baselinePath = filepath.Join(snapshotDir, "baseline.signature.json")
|
||||
}
|
||||
client := &http.Client{Timeout: cfg.Timeout}
|
||||
raw, err := fetchSubscriptionPage(cfg.URL, cfg.Fixture, client)
|
||||
if err != nil {
|
||||
return deepseekNewsSignatureGuardResult{}, err
|
||||
}
|
||||
current, err := writeDeepSeekNewsSnapshotArtifacts(raw, cfg.URL, snapshotPath, signaturePath, now)
|
||||
if err != nil {
|
||||
return deepseekNewsSignatureGuardResult{}, err
|
||||
}
|
||||
result := deepseekNewsSignatureGuardResult{
|
||||
SnapshotPath: snapshotPath,
|
||||
SignaturePath: signaturePath,
|
||||
BaselinePath: baselinePath,
|
||||
CurrentSignature: current,
|
||||
}
|
||||
previous, err := readDeepSeekNewsStructureSignature(baselinePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if !cfg.AllowBootstrap {
|
||||
return result, fmt.Errorf("deepseek news baseline missing: %s", baselinePath)
|
||||
}
|
||||
if err := copyFileCommon(signaturePath, baselinePath); err != nil {
|
||||
return result, fmt.Errorf("initialize baseline: %w", err)
|
||||
}
|
||||
result.BaselineInitialized = true
|
||||
return result, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
result.PreviousBaselineHash = previous.StructureSHA256
|
||||
if previous.StructureSHA256 != current.StructureSHA256 {
|
||||
result.DriftDetected = true
|
||||
return result, fmt.Errorf(
|
||||
"deepseek news structure drift detected: baseline=%s current=%s baseline_path=%s signature_path=%s snapshot_path=%s",
|
||||
previous.StructureSHA256, current.StructureSHA256, baselinePath, signaturePath, snapshotPath,
|
||||
)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func formatDeepSeekNewsSignatureGuardSummary(result deepseekNewsSignatureGuardResult) string {
|
||||
return fmt.Sprintf(
|
||||
"source=deepseek-news-signature-guard drift=%t baseline_initialized=%t structure_sha256=%s previous_baseline_sha256=%s snapshot_out=%s signature_out=%s baseline_path=%s",
|
||||
result.DriftDetected,
|
||||
result.BaselineInitialized,
|
||||
result.CurrentSignature.StructureSHA256,
|
||||
emptyIfBlank(result.PreviousBaselineHash),
|
||||
result.SnapshotPath,
|
||||
result.SignaturePath,
|
||||
result.BaselinePath,
|
||||
)
|
||||
}
|
||||
|
||||
func buildDeepSeekNewsSignatureAuditRecord(cfg deepseekNewsSignatureGuardConfig, result deepseekNewsSignatureGuardResult, checkedAt time.Time, runErr error) officialImportSignatureAuditRecord {
|
||||
record := officialImportSignatureAuditRecord{
|
||||
SourceKey: "deepseek_news_signature",
|
||||
CheckedAt: checkedAt,
|
||||
Status: officialImportSignatureAuditStatus(result.DriftDetected, result.BaselineInitialized, runErr),
|
||||
DriftDetected: result.DriftDetected,
|
||||
BaselineInitialized: result.BaselineInitialized,
|
||||
SourceURL: strings.TrimSpace(cfg.URL),
|
||||
FixturePath: strings.TrimSpace(cfg.Fixture),
|
||||
SnapshotPath: strings.TrimSpace(result.SnapshotPath),
|
||||
SignaturePath: strings.TrimSpace(result.SignaturePath),
|
||||
BaselinePath: strings.TrimSpace(result.BaselinePath),
|
||||
StructureSHA256: strings.TrimSpace(result.CurrentSignature.StructureSHA256),
|
||||
PreviousStructureSHA256: strings.TrimSpace(result.PreviousBaselineHash),
|
||||
ByteSize: result.CurrentSignature.ByteSize,
|
||||
ErrorMessage: errorMessageText(runErr),
|
||||
}
|
||||
if hasDeepSeekNewsStructureSignature(result.CurrentSignature) {
|
||||
signatureCopy := result.CurrentSignature
|
||||
record.SignaturePayload = &signatureCopy
|
||||
}
|
||||
return record
|
||||
}
|
||||
|
||||
func persistDeepSeekNewsSignatureAuditIfConfigured(cfg deepseekNewsSignatureGuardConfig, result deepseekNewsSignatureGuardResult, checkedAt time.Time, runErr error) error {
|
||||
return persistOfficialImportSignatureAuditIfConfigured(buildDeepSeekNewsSignatureAuditRecord(cfg, result, checkedAt, runErr))
|
||||
}
|
||||
Reference in New Issue
Block a user