Commit 9b956985525d5185a4f0c93fd2811f641bb25b24

Authored by tangwang
1 parent 6c35aff8

调试工具展示优化

config/config.yaml
@@ -219,8 +219,8 @@ query_config: @@ -219,8 +219,8 @@ query_config:
219 knn_text_k_long: 300 219 knn_text_k_long: 300
220 knn_text_num_candidates_long: 720 220 knn_text_num_candidates_long: 720
221 221
222 - knn_image_k: 300  
223 - knn_image_num_candidates: 720 222 + knn_image_k: 3000
  223 + knn_image_num_candidates: 7200
224 224
225 # Function Score配置(ES层打分规则) 225 # Function Score配置(ES层打分规则)
226 function_score: 226 function_score:
frontend/static/css/style.css
@@ -350,6 +350,25 @@ body { @@ -350,6 +350,25 @@ body {
350 flex-shrink: 0; 350 flex-shrink: 0;
351 } 351 }
352 352
  353 +/* Per-result multilingual debug (title/brief/vendor) under image, price, title */
  354 +.product-main-multilingual {
  355 + margin-top: 8px;
  356 + font-family: Menlo, Consolas, "Courier New", monospace;
  357 + font-size: 11px;
  358 + color: #555;
  359 + width: 100%;
  360 +}
  361 +
  362 +.product-main-multilingual .debug-details {
  363 + margin-top: 6px;
  364 +}
  365 +
  366 +.product-main-multilingual .debug-json-pre {
  367 + max-height: 180px;
  368 + font-size: 10px;
  369 + padding: 8px;
  370 +}
  371 +
353 .product-debug { 372 .product-debug {
354 flex: 1; 373 flex: 1;
355 font-family: Menlo, Consolas, "Courier New", monospace; 374 font-family: Menlo, Consolas, "Courier New", monospace;
@@ -472,29 +491,34 @@ body { @@ -472,29 +491,34 @@ body {
472 font-size: 11px; 491 font-size: 11px;
473 } 492 }
474 493
  494 +/* Stage cards + query context: one key:value per line, no per-field boxes */
475 .debug-metrics { 495 .debug-metrics {
476 - display: grid;  
477 - grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));  
478 - gap: 8px; 496 + display: flex;
  497 + flex-direction: column;
  498 + gap: 1px 0;
  499 + margin-top: 6px;
  500 + font-size: 11px;
  501 + line-height: 1.4;
479 } 502 }
480 503
481 -.debug-metric {  
482 - padding: 8px 9px;  
483 - background: #f7f7f7;  
484 - border-radius: 6px;  
485 - border: 1px solid #efefef; 504 +.debug-metric-line {
  505 + display: block;
  506 + word-break: break-word;
486 } 507 }
487 508
488 -.debug-metric-label {  
489 - font-size: 11px;  
490 - color: #777;  
491 - margin-bottom: 2px; 509 +.debug-metric-k {
  510 + color: #666;
  511 + font-weight: 500;
492 } 512 }
493 513
494 -.debug-metric-value {  
495 - color: #222; 514 +.debug-metric-sep {
  515 + color: #aaa;
  516 + margin: 0 3px 0 1px;
  517 +}
  518 +
  519 +.debug-metric-v {
  520 + color: #111;
496 font-weight: 600; 521 font-weight: 600;
497 - word-break: break-word;  
498 } 522 }
499 523
500 .debug-score-pills { 524 .debug-score-pills {
frontend/static/js/app.js
@@ -436,7 +436,7 @@ function displayResults(data) { @@ -436,7 +436,7 @@ function displayResults(data) {
436 <div class="product-title"> 436 <div class="product-title">
437 ${escapeHtml(title)} 437 ${escapeHtml(title)}
438 </div> 438 </div>
439 - 439 + ${debug ? buildMultilingualFieldsHtml(debug) : ''}
440 <div class="product-meta"> 440 <div class="product-meta">
441 ${category ? escapeHtml(category) : ''} 441 ${category ? escapeHtml(category) : ''}
442 ${vendor ? ' | ' + escapeHtml(vendor) : ''} 442 ${vendor ? ' | ' + escapeHtml(vendor) : ''}
@@ -458,16 +458,17 @@ function formatDebugNumber(value, digits = 4) { @@ -458,16 +458,17 @@ function formatDebugNumber(value, digits = 4) {
458 } 458 }
459 459
460 function renderMetricList(items) { 460 function renderMetricList(items) {
461 - const rows = items 461 + const lines = items
462 .filter((item) => item && item.value !== undefined && item.value !== null && item.value !== '') 462 .filter((item) => item && item.value !== undefined && item.value !== null && item.value !== '')
463 - .map((item) => `  
464 - <div class="debug-metric">  
465 - <div class="debug-metric-label">${escapeHtml(item.label)}</div>  
466 - <div class="debug-metric-value">${escapeHtml(String(item.value))}</div> 463 + .map(
  464 + (item) => `
  465 + <div class="debug-metric-line">
  466 + <span class="debug-metric-k">${escapeHtml(item.label)}</span><span class="debug-metric-sep">:</span><span class="debug-metric-v">${escapeHtml(String(item.value))}</span>
467 </div> 467 </div>
468 - `) 468 + `
  469 + )
469 .join(''); 470 .join('');
470 - return rows ? `<div class="debug-metrics">${rows}</div>` : ''; 471 + return lines ? `<div class="debug-metrics">${lines}</div>` : '';
471 } 472 }
472 473
473 function renderScorePills(items) { 474 function renderScorePills(items) {
@@ -495,6 +496,21 @@ function renderJsonDetails(title, payload, open = false) { @@ -495,6 +496,21 @@ function renderJsonDetails(title, payload, open = false) {
495 `; 496 `;
496 } 497 }
497 498
  499 +/** Multilingual title/brief/vendor from per-result debug; shown under image/price/title on the left. */
  500 +function buildMultilingualFieldsHtml(debug) {
  501 + if (!debug || typeof debug !== 'object') {
  502 + return '';
  503 + }
  504 + const titlePayload = {};
  505 + if (debug.title_multilingual) titlePayload.title = debug.title_multilingual;
  506 + if (debug.brief_multilingual) titlePayload.brief = debug.brief_multilingual;
  507 + if (debug.vendor_multilingual) titlePayload.vendor = debug.vendor_multilingual;
  508 + if (Object.keys(titlePayload).length === 0) {
  509 + return '';
  510 + }
  511 + return `<div class="product-main-multilingual">${renderJsonDetails('Multilingual Fields', titlePayload, true)}</div>`;
  512 +}
  513 +
498 function buildProductDebugHtml({ debug, result, spuId, tenantId }) { 514 function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
499 const resultJson = customStringify(result); 515 const resultJson = customStringify(result);
500 const rawUrl = `${API_BASE_URL}/search/es-doc/${encodeURIComponent(spuId)}?tenant_id=${encodeURIComponent(tenantId)}`; 516 const rawUrl = `${API_BASE_URL}/search/es-doc/${encodeURIComponent(spuId)}?tenant_id=${encodeURIComponent(tenantId)}`;
@@ -527,7 +543,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) { @@ -527,7 +543,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
527 { label: 'rank', value: esStage.rank ?? debug.initial_rank ?? 'N/A' }, 543 { label: 'rank', value: esStage.rank ?? debug.initial_rank ?? 'N/A' },
528 { label: 'es_score', value: formatDebugNumber(esStage.score ?? debug.es_score) }, 544 { label: 'es_score', value: formatDebugNumber(esStage.score ?? debug.es_score) },
529 { label: 'es_norm', value: formatDebugNumber(esStage.normalized_score ?? debug.es_score_normalized) }, 545 { label: 'es_norm', value: formatDebugNumber(esStage.normalized_score ?? debug.es_score_normalized) },
530 - ], renderJsonDetails('Matched Queries', esStage.matched_queries ?? debug.matched_queries, false))} 546 + ], renderJsonDetails('Matched Queries', esStage.matched_queries ?? debug.matched_queries, true))}
531 ${buildStageCard('Coarse Rank', 'Text + vector fusion', [ 547 ${buildStageCard('Coarse Rank', 'Text + vector fusion', [
532 { label: 'rank', value: coarseStage.rank ?? 'N/A' }, 548 { label: 'rank', value: coarseStage.rank ?? 'N/A' },
533 { label: 'rank_change', value: coarseStage.rank_change ?? 'N/A' }, 549 { label: 'rank_change', value: coarseStage.rank_change ?? 'N/A' },
@@ -542,7 +558,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) { @@ -542,7 +558,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
542 { label: 'image_knn', value: formatDebugNumber(coarseStage.signals?.image_knn_score ?? debug.image_knn_score) }, 558 { label: 'image_knn', value: formatDebugNumber(coarseStage.signals?.image_knn_score ?? debug.image_knn_score) },
543 { label: 'text_factor', value: formatDebugNumber(coarseStage.text_factor ?? debug.coarse_text_factor) }, 559 { label: 'text_factor', value: formatDebugNumber(coarseStage.text_factor ?? debug.coarse_text_factor) },
544 { label: 'knn_factor', value: formatDebugNumber(coarseStage.knn_factor ?? debug.coarse_knn_factor) }, 560 { label: 'knn_factor', value: formatDebugNumber(coarseStage.knn_factor ?? debug.coarse_knn_factor) },
545 - ], renderJsonDetails('Coarse Signals', coarseStage.signals, false))} 561 + ], renderJsonDetails('Coarse Signals', coarseStage.signals, true))}
546 ${buildStageCard('Fine Rank', 'Lightweight reranker output', [ 562 ${buildStageCard('Fine Rank', 'Lightweight reranker output', [
547 { label: 'rank', value: fineStage.rank ?? 'N/A' }, 563 { label: 'rank', value: fineStage.rank ?? 'N/A' },
548 { label: 'rank_change', value: fineStage.rank_change ?? 'N/A' }, 564 { label: 'rank_change', value: fineStage.rank_change ?? 'N/A' },
@@ -550,7 +566,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) { @@ -550,7 +566,7 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
550 { label: 'fine_score', value: formatDebugNumber(fineStage.fine_score ?? debug.fine_score) }, 566 { label: 'fine_score', value: formatDebugNumber(fineStage.fine_score ?? debug.fine_score) },
551 { label: 'text_score', value: formatDebugNumber(fineStage.text_score ?? debug.text_score) }, 567 { label: 'text_score', value: formatDebugNumber(fineStage.text_score ?? debug.text_score) },
552 { label: 'knn_score', value: formatDebugNumber(fineStage.knn_score ?? debug.knn_score) }, 568 { label: 'knn_score', value: formatDebugNumber(fineStage.knn_score ?? debug.knn_score) },
553 - ], `${renderJsonDetails('Fine Fusion', fineStage.fusion_summary || debug.fusion_summary || fineStage.fusion_factors, false)}${renderJsonDetails('Fine Input', fineStage.rerank_input ?? debug.rerank_input, false)}`)} 569 + ], `${renderJsonDetails('Fine Fusion', fineStage.fusion_summary || debug.fusion_summary || fineStage.fusion_factors, true)}${renderJsonDetails('Fine Input', fineStage.rerank_input ?? debug.rerank_input, true)}`)}
554 ${buildStageCard('Final Rerank', 'Heavy reranker + final fusion', [ 570 ${buildStageCard('Final Rerank', 'Heavy reranker + final fusion', [
555 { label: 'rank', value: rerankStage.rank ?? finalPageStage.rank ?? debug.final_rank ?? 'N/A' }, 571 { label: 'rank', value: rerankStage.rank ?? finalPageStage.rank ?? debug.final_rank ?? 'N/A' },
556 { label: 'rank_change', value: rerankStage.rank_change ?? finalPageStage.rank_change ?? 'N/A' }, 572 { label: 'rank_change', value: rerankStage.rank_change ?? finalPageStage.rank_change ?? 'N/A' },
@@ -568,11 +584,6 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) { @@ -568,11 +584,6 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
568 </div> 584 </div>
569 `; 585 `;
570 586
571 - const titlePayload = {};  
572 - if (debug.title_multilingual) titlePayload.title = debug.title_multilingual;  
573 - if (debug.brief_multilingual) titlePayload.brief = debug.brief_multilingual;  
574 - if (debug.vendor_multilingual) titlePayload.vendor = debug.vendor_multilingual;  
575 -  
576 return ` 587 return `
577 <div class="product-debug"> 588 <div class="product-debug">
578 <div class="product-debug-title">Ranking Funnel</div> 589 <div class="product-debug-title">Ranking Funnel</div>
@@ -580,7 +591,6 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) { @@ -580,7 +591,6 @@ function buildProductDebugHtml({ debug, result, spuId, tenantId }) {
580 ${stageScores} 591 ${stageScores}
581 ${stageGrid} 592 ${stageGrid}
582 ${renderJsonDetails('Selected SKU', debug.style_intent_sku, true)} 593 ${renderJsonDetails('Selected SKU', debug.style_intent_sku, true)}
583 - ${renderJsonDetails('Multilingual Fields', titlePayload, false)}  
584 <div class="product-debug-actions"> 594 <div class="product-debug-actions">
585 <button type="button" class="product-debug-inline-result-btn" 595 <button type="button" class="product-debug-inline-result-btn"
586 data-action="toggle-result-inline-doc" 596 data-action="toggle-result-inline-doc"