Files
sanbuphy 0eba9e87e9 fix(eslint): reduce warnings in GitHub Actions deployment
- Disable formatting rules (handled by Prettier)
- Relaxed strict Vue/JS rules for demo code compatibility
- Fix syntax errors in ApiPlayground and VoiceCloningDemo
- Fix duplicate else-if condition in ApiPlayground
- Fix Promise executor async pattern in AutoregressiveAudioDemo
- Add TypeScript file support to ESLint config

Warnings reduced from 295 to 251 problems.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 17:38:10 +08:00

309 lines
6.5 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="lost-in-middle-demo">
<div class="control-panel">
<div class="control-group">
<label>关键信息大概在整段话的哪个位置{{ needlePosition }}%</label>
<input
v-model.number="needlePosition"
type="range"
min="0"
max="100"
step="1"
class="slider-input"
>
</div>
</div>
<div class="visualization-area">
<!-- Context Window Bar -->
<div class="context-bar">
<div class="context-label start">
Start (System)
</div>
<div class="context-label end">
End (Query)
</div>
<!-- Attention Heatmap Background -->
<div class="attention-heatmap" />
<!-- Needle Marker -->
<div
class="needle-marker"
:style="{ left: `${needlePosition}%` }"
>
<div class="needle-icon">
📍
</div>
<div class="needle-tooltip">
关键事实
</div>
</div>
</div>
<!-- Probability Curve Chart -->
<div class="chart-container">
<svg
viewBox="0 0 100 60"
preserveAspectRatio="none"
class="chart-svg"
>
<!-- U-Curve Path -->
<path
d="M 0 5 Q 50 55 100 5"
fill="none"
stroke="var(--vp-c-divider)"
stroke-width="2"
stroke-dasharray="4"
/>
<!-- Active Dot -->
<circle
:cx="needlePosition"
:cy="60 - (retrievalProb * 0.5 + 5)"
r="3"
fill="var(--vp-c-brand)"
/>
</svg>
<div class="chart-label y-axis">
被记住的概率
</div>
<div class="chart-label x-axis">
在上下文里的位置
</div>
</div>
</div>
<div class="metrics-panel">
<div class="metric-card">
<div
class="metric-value"
:class="getScoreClass(retrievalProb)"
>
{{ retrievalProb.toFixed(1) }}%
</div>
<div class="metric-label">
检索成功率
</div>
</div>
<div class="metric-card">
<div class="metric-value">
{{ positionLabel }}
</div>
<div class="metric-label">
位置描述
</div>
</div>
</div>
<div class="info-box">
<p>
<span class="icon">🔍</span>
<strong>实验观察</strong>当关键信息藏在整段话的<strong>中间位置</strong>模型最容易漏看掉Lost in the Middle
<br>
最靠谱的做法把重要指令放在<strong>最前面的 System Prompt</strong>或者<strong>最后的用户问题里</strong>
</p>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const needlePosition = ref(50) // 0 to 100
// Parabolic curve calculation: Vertex at (50, 40), passing through (0, 95) and (100, 95)
// y = a(x-h)^2 + k
// a = 0.022
const retrievalProb = computed(() => {
const x = needlePosition.value
const prob = 0.022 * Math.pow(x - 50, 2) + 40
return Math.min(99.9, Math.max(0, prob))
})
const positionLabel = computed(() => {
const p = needlePosition.value
if (p < 20) return '偏开头'
if (p > 80) return '偏结尾'
return '中间区域(最危险)'
})
const getScoreClass = (score) => {
if (score > 85) return 'text-success'
if (score > 60) return 'text-warning'
return 'text-danger'
}
</script>
<style scoped>
.lost-in-middle-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background-color: var(--vp-c-bg-soft);
padding: 0.75rem;
margin: 0.5rem 0;
font-family: var(--vp-font-family-mono);
}
.control-panel {
margin-bottom: 1rem;
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
border: 1px solid var(--vp-c-divider);
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.control-group label {
font-weight: bold;
font-size: 0.85rem;
}
.slider-input {
width: 100%;
accent-color: var(--vp-c-brand);
}
.visualization-area {
margin-bottom: 1rem;
position: relative;
}
.context-bar {
height: 40px;
border: 2px solid var(--vp-c-divider);
border-radius: 6px;
position: relative;
margin-bottom: 0.75rem;
background: var(--vp-c-bg);
overflow: visible; /* Allow needle to stick out */
}
.attention-heatmap {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 6px;
background: linear-gradient(
90deg,
rgba(16, 185, 129, 0.2) 0%,
rgba(239, 68, 68, 0.1) 50%,
rgba(16, 185, 129, 0.2) 100%
);
opacity: 0.6;
}
.context-label {
position: absolute;
top: -18px;
font-size: 0.7rem;
color: var(--vp-c-text-2);
}
.context-label.start { left: 0; }
.context-label.end { right: 0; }
.needle-marker {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
z-index: 10;
cursor: grab;
transition: left 0.1s ease;
}
.needle-icon {
font-size: 1.25rem;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
}
.needle-tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: var(--vp-c-text-1);
color: var(--vp-c-bg);
padding: 2px 6px;
border-radius: 4px;
font-size: 0.7rem;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
}
.needle-marker:hover .needle-tooltip {
opacity: 1;
}
.chart-container {
height: 60px;
position: relative;
border-bottom: 1px solid var(--vp-c-divider);
margin-top: 0.75rem;
}
.chart-svg {
width: 100%;
height: 100%;
overflow: visible;
}
.chart-label {
position: absolute;
font-size: 0.7rem;
color: var(--vp-c-text-3);
}
.chart-label.y-axis { top: 0; left: 0; }
.chart-label.x-axis { bottom: -1rem; width: 100%; text-align: center; }
.metrics-panel {
display: flex;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.metric-card {
flex: 1;
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
text-align: center;
}
.metric-value {
font-size: 1.25rem;
font-weight: bold;
}
.metric-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-top: 0.2rem;
}
.text-success { color: var(--vp-c-success-1); }
.text-warning { color: var(--vp-c-warning-1); }
.text-danger { color: var(--vp-c-danger-1); }
.info-box {
background-color: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.info-box .icon {
margin-right: 0.5rem;
}
</style>