feat(monitoring): exclude qwen from content citation resolution

Skip article alias resolution and content-citation aggregates when the
platform is qwen, and hide the content-citation badge/meta in the
tracking detail view, since qwen's source URLs are not reliable enough
to map to brand articles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:48:28 +08:00
parent 19527cdf42
commit 4a7427a7f1
5 changed files with 114 additions and 38 deletions
@@ -2072,7 +2072,7 @@ func (s *MonitoringCallbackService) processTaskResult(ctx context.Context, task
return nil, err
}
if runStatus == "succeeded" {
facts, buildErr := s.buildCitationFacts(ctx, tx, task.TenantID, sourceInputs)
facts, buildErr := s.buildCitationFacts(ctx, tx, task.TenantID, task.AIPlatformID, sourceInputs)
if buildErr != nil {
return nil, buildErr
}
@@ -2385,37 +2385,42 @@ func shouldUseMonitoringLLMParse(req MonitoringTaskResultRequest) bool {
return !hasCompleteMonitoringParsePayload(req)
}
func (s *MonitoringCallbackService) buildCitationFacts(ctx context.Context, tx pgx.Tx, tenantID int64, inputs []MonitoringSourceItem) ([]monitoringCitationFact, error) {
func (s *MonitoringCallbackService) buildCitationFacts(ctx context.Context, tx pgx.Tx, tenantID int64, platformID string, inputs []MonitoringSourceItem) ([]monitoringCitationFact, error) {
if len(inputs) == 0 {
return nil, nil
}
normalizedURLs := make([]string, 0, len(inputs))
seenURLs := make(map[string]struct{}, len(inputs))
for _, item := range inputs {
key := strings.TrimSpace(monitoringStringValue(item.NormalizedURL))
if key == "" {
key = normalizeCitationURL(item.URL)
resolveContentCitations := monitoringPlatformResolvesContentCitations(platformID)
aliasMap := map[string]monitoringAliasResolution{}
if resolveContentCitations {
normalizedURLs := make([]string, 0, len(inputs))
seenURLs := make(map[string]struct{}, len(inputs))
for _, item := range inputs {
key := strings.TrimSpace(monitoringStringValue(item.NormalizedURL))
if key == "" {
key = normalizeCitationURL(item.URL)
}
if key == "" {
continue
}
if _, ok := seenURLs[key]; ok {
continue
}
seenURLs[key] = struct{}{}
normalizedURLs = append(normalizedURLs, key)
}
if key == "" {
continue
}
if _, ok := seenURLs[key]; ok {
continue
}
seenURLs[key] = struct{}{}
normalizedURLs = append(normalizedURLs, key)
}
aliasMap, err := s.loadAliasResolutions(ctx, tx, tenantID, normalizedURLs)
if err != nil {
return nil, err
var err error
aliasMap, err = s.loadAliasResolutions(ctx, tx, tenantID, normalizedURLs)
if err != nil {
return nil, err
}
}
result := make([]monitoringCitationFact, 0, len(inputs))
seenFacts := make(map[string]struct{}, len(inputs))
for _, input := range inputs {
fact, ok := buildMonitoringCitationFact(input, aliasMap)
fact, ok := buildMonitoringCitationFact(input, aliasMap, resolveContentCitations)
if !ok {
continue
}
@@ -2552,11 +2557,11 @@ func (s *MonitoringCallbackService) loadExistingRunSummary(ctx context.Context,
if err := s.monitoringPool.QueryRow(ctx, `
SELECT
COUNT(*)::int AS citation_source_count,
COUNT(*) FILTER (WHERE article_id IS NOT NULL)::int AS content_citation_count
COUNT(*) FILTER (WHERE article_id IS NOT NULL AND $3::text <> 'qwen')::int AS content_citation_count
FROM monitoring_citation_facts
WHERE tenant_id = $1
AND run_id = $2
`, task.TenantID, runID.Int64).Scan(&citationSourceCount, &contentCitationCount); err != nil {
`, task.TenantID, runID.Int64, normalizeMonitoringPlatformID(task.AIPlatformID)).Scan(&citationSourceCount, &contentCitationCount); err != nil {
return nil, 0, 0, response.ErrInternal(50041, "citation_lookup_failed", "failed to inspect existing citation facts")
}
@@ -2683,6 +2688,15 @@ func monitoringPlatformUsesDedicatedCitationPanel(platformID string) bool {
}
}
func monitoringPlatformResolvesContentCitations(platformID string) bool {
switch normalizeMonitoringPlatformID(platformID) {
case "qwen":
return false
default:
return true
}
}
func newMonitoringTaskResultEnvelope(task *monitoringCollectTask, installationID string, receivedAt time.Time, req MonitoringTaskResultRequest) monitoringTaskResultEnvelope {
return monitoringTaskResultEnvelope{
Version: "v1",
@@ -2741,7 +2755,7 @@ func extractMonitoringSourceItems(value interface{}) []MonitoringSourceItem {
return result
}
func buildMonitoringCitationFact(input MonitoringSourceItem, aliasMap map[string]monitoringAliasResolution) (monitoringCitationFact, bool) {
func buildMonitoringCitationFact(input MonitoringSourceItem, aliasMap map[string]monitoringAliasResolution, resolveContentCitations bool) (monitoringCitationFact, bool) {
rawURL := strings.TrimSpace(input.URL)
normalizedURL := strings.TrimSpace(monitoringStringValue(input.NormalizedURL))
if normalizedURL == "" {
@@ -2791,14 +2805,18 @@ func buildMonitoringCitationFact(input MonitoringSourceItem, aliasMap map[string
siteKey = registrableDomain
}
articleID := cloneInt64(input.ArticleID)
publishRecordID := cloneInt64(input.PublishRecordID)
if alias, ok := aliasMap[normalizedURL]; ok {
if articleID == nil {
articleID = cloneInt64(alias.ArticleID)
}
if publishRecordID == nil {
publishRecordID = cloneInt64(alias.PublishRecordID)
var articleID *int64
var publishRecordID *int64
if resolveContentCitations {
articleID = cloneInt64(input.ArticleID)
publishRecordID = cloneInt64(input.PublishRecordID)
if alias, ok := aliasMap[normalizedURL]; ok {
if articleID == nil {
articleID = cloneInt64(alias.ArticleID)
}
if publishRecordID == nil {
publishRecordID = cloneInt64(alias.PublishRecordID)
}
}
}