TeleAI-AI-Flow's picture
Upload Leaderboard.vue
54e755a verified
<script setup>
import { ref, onMounted, watch, nextTick } from 'vue'
import { useLeaderboardData } from '@/composables/useLeaderboardData.js'
import Chart from '@/components/Chart.vue'
import { computed } from 'vue'
import { parsedHeaderHtml } from '@/utils/mk2html.js'
// 使用数据管理 composable
const {
leaderboard,
csvHeaders,
loading,
error,
selectedMode,
visibleColumns,
selectableColumns,
dataGroups,
selectedDataName,
modelSeriesICAvg,
selectedDataNameChart,
autoShowSeries,
headerDisplayMap,
dataNameDisplayMap,
modelTypeGroups,
selectedModelType,
filteredLeaderboard,
displayedColumns,
fetchAndLoadCsv,
selectAll,
clearAll,
selectAllModelTypes,
clearAllModelTypes,
formatCell,
// 排序 API
sortKey,
sortDesc,
setSortKey,
init
} = useLeaderboardData()
const isSeries = computed(() => selectedMode.value === 'ModelSeries')
// theme (dark mode) support: sync with document root class and localStorage
const isDark = ref(false)
// 图表区域ref
const chartSection = ref(null)
// 记录上一次选择的图表数据集,用于区分初始加载和用户点击
const lastSelectedDataNameChart = ref('')
// header markdown 内容
const headerMarkdown = ref(`
**Information Capacity** evaluates an LLM's **efficiency** based on text compression performance relative to computational complexity, harnessing the inherent correlation between **compression** and **intelligence**.
Larger models can predict the next token more accurately, leading to higher compression gains but at increased computational costs.
Consequently, a series of models with varying sizes exhibits **consistent** information capacity, which can be used to compare model capability across model series and predict model performance within a series.
It also facilitates dynamic routing of different-sized models for efficient handling of tasks with varying difficulties, which is especially relevant to the device-edge-cloud infrastructure detailed in the **AI Flow** framework.
With the rapid evolution of edge intelligence, we believe that this hierarchical network will replace the mainstream cloud-centric computing scheme in the near future.
If you want to add your evaluation results to the leaderboard, please submit a discussion at [this huggingface space](https://huggingface.co/spaces/TeleAI-AI-Flow/InformationCapacityLeaderboard/discussions/new).
`)
const title = 'Information Capacity Leaderboard'
const lastUpdatedTime = '11/12/2025 15:30'
const headerInfo = parsedHeaderHtml(headerMarkdown.value)
// 当图表数据集变化时,滚动到图表区域底部(仅当用户点击时)
watch(selectedDataNameChart, (newVal) => {
if (lastSelectedDataNameChart.value && lastSelectedDataNameChart.value !== newVal) {
nextTick(() => {
chartSection.value?.scrollIntoView({ behavior: 'smooth', block: 'end' })
})
}
lastSelectedDataNameChart.value = newVal
})
onMounted(() => {
init()
})
onMounted(() => {
const stored = localStorage.getItem('theme')
if (stored === 'dark') {
isDark.value = true
} else if (stored === 'light') {
isDark.value = false
} else {
// follow system preference when no stored preference
isDark.value = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
}
})
watch(isDark, (val) => {
try {
if (val) document.documentElement.classList.add('dark')
else document.documentElement.classList.remove('dark')
localStorage.setItem('theme', val ? 'dark' : 'light')
} catch (e) {
// ignore if SSR or unavailable
}
})
function clearModelTypeSelection() {
selectAllModelTypes()
}
</script>
<template>
<div
class="min-h-screen bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:via-gray-800 dark:to-gray-800 py-12 px-4 sm:px-6 lg:px-8">
<div class=" mx-auto">
<header class="mb-4 flex items-start justify-between mr-4">
<div>
<h1 class="text-3xl font-extrabold text-gray-900 dark:text-gray-100">{{ title }}</h1>
<!-- <p class="mt-1 text-sm text-gray-600 dark:text-gray-300">LLM IC Leaderboard Demo</p> -->
<div v-html="headerInfo" class="py-7"></div>
</div>
<div class="flex items-center">
<!-- 固定正方形容器,内部图片保持纵横比且居中 -->
<div class="h-40 w-40 flex items-center justify-center rounded-md overflow-hidden p-2">
<img src="/logo.png" alt="Logo" class="max-h-full max-w-full object-contain" />
</div>
</div>
</header>
<div class="bg-white dark:bg-gray-900/60 shadow rounded-lg overflow-hidden">
<div
class="px-6 py-4 border-b bg-gradient-to-r from-indigo-50 via-white to-white dark:bg-gradient-to-r dark:from-gray-800 dark:via-gray-900 dark:to-gray-900">
<div class="flex items-center justify-between">
<h2 class="text-lg font-medium text-gray-800 dark:text-gray-50">Leaderboard</h2>
<div class="text-sm text-gray-500 dark:text-gray-300">Last updated on {{ lastUpdatedTime }}</div>
</div>
</div>
<!-- 筛选(模型分类,模型系列分类) -->
<div class="px-6 py-3 border-b bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800">
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Shown as</span>
<div v-if="dataGroups.length > 0" class="flex gap-2 items-center overflow-x-auto">
<!-- <label class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer" :class="{'bg-gray-100 dark:bg-gray-700': selectedDataName==='all'}">
<input type="radio" class="hidden" value="all" v-model="selectedDataName" /> 全部
</label> -->
<label @click="selectedMode = 'Model'"
class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer dark:text-slate-300"
:class="{ 'bg-gray-100 dark:bg-gray-700 dark:text-white': selectedMode === 'Model' }">
Individual Models
</label>
<label @click="selectedMode = 'ModelSeries'"
class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer dark:text-slate-300"
:class="{ 'bg-gray-100 dark:bg-gray-700 dark:text-white': selectedMode === 'ModelSeries' }">
Model Series
</label>
</div>
<div v-else class="text-sm text-gray-500 dark:text-gray-400">(数据集中未检测到 data_name 列)</div>
</div>
</div>
<!-- 数据集筛选区域(独立于列筛选) -->
<div class="px-6 py-3 border-b bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800">
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Dataset</span>
<div v-if="dataGroups.length > 0" class="flex gap-2 items-center overflow-x-auto">
<!-- <label class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer" :class="{'bg-gray-100 dark:bg-gray-700': selectedDataName==='all'}">
<input type="radio" class="hidden" value="all" v-model="selectedDataName" /> 全部
</label> -->
<label v-for="g in dataGroups" :key="g"
class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer dark:text-slate-300"
:class="{ 'bg-gray-100 dark:bg-gray-700 dark:text-white': selectedDataName === g }">
<input type="radio" class="hidden" :value="g" v-model="selectedDataName" /> <span
class="whitespace-nowrap">{{ dataNameDisplayMap[g] ?
dataNameDisplayMap[g] : g }}</span>
</label>
</div>
<div v-else class="text-sm text-gray-500 dark:text-gray-400">(数据集中未检测到 data_name 列)</div>
</div>
</div>
<!-- 模型类型筛选区域 -->
<div class="px-6 py-3 border-b bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800">
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200 whitespace-nowrap">Model Series</span>
<div class="flex items-center gap-2">
<button @click="clearModelTypeSelection"
class="whitespace-nowrap text-sm px-2 py-1 bg-white/90 dark:bg-gray-700/60 border border-gray-200 dark:border-gray-600 rounded text-gray-700 dark:text-gray-200 hover:bg-white dark:hover:bg-gray-600 transition">
全选
</button>
<button @click="clearAllModelTypes"
class="whitespace-nowrap text-sm px-2 py-1 bg-transparent border border-gray-200 dark:border-gray-700 rounded text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition">
清除
</button>
</div>
<div v-if="modelTypeGroups.length > 0" class="flex flex-wrap gap-2 items-center">
<label v-for="g in modelTypeGroups" :key="g"
class="flex items-center gap-2 text-sm bg-white dark:bg-gray-800 px-3 py-1 rounded-full border border-gray-200 dark:border-gray-700 hover:shadow-sm whitespace-nowrap">
<input type="checkbox" :value="g" v-model="selectedModelType"
class="h-4 w-4 text-indigo-600 dark:text-indigo-400 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 rounded" />
<span class="truncate text-gray-800 dark:text-gray-50">{{ g }}</span>
</label>
</div>
<div v-else class="text-sm text-gray-500 dark:text-gray-400">(未配置模型类型映射)</div>
</div>
</div>
<!-- 内联列选择区域:pills 风格,支持水平滚动,并兼容深色/浅色模式 -->
<div class="px-6 py-3 border-b bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800" v-show="!isSeries">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Visible Columns</span>
<div class="flex items-center gap-2">
<button @click.prevent="selectAll"
class="text-sm px-2 py-1 bg-white/90 dark:bg-gray-700/60 border border-gray-200 dark:border-gray-600 rounded text-gray-700 dark:text-gray-200 hover:bg-white dark:hover:bg-gray-600 transition">全选</button>
<button @click.prevent="clearAll"
class="text-sm px-2 py-1 bg-transparent border border-gray-200 dark:border-gray-700 rounded text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition">清除</button>
</div>
</div>
<div class="flex-1 overflow-x-auto">
<div class="flex gap-2 items-center px-1 py-2">
<label v-for="h in selectableColumns" :key="h"
class="flex items-center gap-2 text-sm bg-white dark:bg-gray-800 px-3 py-1 rounded-full border border-gray-200 dark:border-gray-700 hover:shadow-sm whitespace-nowrap">
<input type="checkbox" :value="h" v-model="visibleColumns"
class="h-4 w-4 text-indigo-600 dark:text-indigo-400 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 rounded" />
<span class="truncate text-gray-800 dark:text-gray-50">{{ headerDisplayMap[h] || h }}</span>
</label>
</div>
</div>
</div>
</div>
<div class="p-4 overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gradient-to-r dark:from-gray-800 dark:to-gray-900">
<tr>
<!-- 序号列 -->
<!-- <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">RANK</th> -->
<!-- ModelSeries 模式下使用计算结果列,否则使用普通列 -->
<template v-if="selectedMode === 'ModelSeries'">
<th v-if="visibleColumns.includes('rank')"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap['rank'] || 'rank' }}</span>
</div>
</th>
<th v-if="visibleColumns.includes('model_series')"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap['model_series'] || 'ModelSeries' }}</span>
</div>
</th>
<th v-if="visibleColumns.includes('constant')"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap['constant']}}</span>
</div>
</th>
<th v-if="visibleColumns.includes('ic')" @click="setSortKey('ic')"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap['ic']}} (AVG)</span>
<span v-if="sortKey === 'ic'" class="text-xs text-gray-600 dark:text-gray-300">
<span v-if="sortDesc"></span>
<span v-else></span>
</span>
</div>
</th>
<th v-if="visibleColumns.includes('model_source')" @click="setSortKey('model_source')"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap['model_source']}} </span>
<span v-if="sortKey === 'model_source'" class="text-xs text-gray-600 dark:text-gray-300">
<span v-if="sortDesc"></span>
<span v-else></span>
</span>
</div>
</th>
</template>
<template v-else>
<th v-for="h in displayedColumns" :key="h" @click="setSortKey(h)"
class="px-4 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-300 tracking-wider cursor-pointer select-none">
<div class="flex items-center gap-2">
<span class="whitespace-nowrap">{{ headerDisplayMap[h] || h }}</span>
<span v-if="sortKey === h" class="text-xs text-gray-600 dark:text-gray-300">
<span v-if="sortDesc"></span>
<span v-else></span>
</span>
</div>
</th>
</template>
</tr>
</thead>
<tbody class="bg-white dark:bg-transparent divide-y divide-gray-100 dark:divide-gray-700">
<!-- ModelSeries mode -> 显示 modelSeriesICAvg -->
<template v-if="selectedMode === 'ModelSeries'">
<tr v-for="(row, idx) in modelSeriesICAvg" :key="row.ModelSeries"
class="hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-150">
<td class="px-4 py-3 whitespace-nowrap font-medium text-gray-800 dark:text-gray-50">{{ idx + 1 }}</td>
<td v-if="visibleColumns.includes('model_series')" class="px-4 py-3 whitespace-nowrap">
<div class="text-sm text-gray-800 dark:text-gray-50">{{ row.ModelSeries }}</div>
</td>
<td v-if="visibleColumns.includes('constant')"
class="px-4 py-3 whitespace-nowrap">
<div class="text-sm text-gray-800 dark:text-gray-50">{{ row.Constant }}</div>
</td>
<td v-if="visibleColumns.includes('ic')"
class="px-4 py-3 whitespace-nowrap">
<div class="text-sm text-gray-800 dark:text-gray-50">{{ row.IC }}</div>
</td>
<td v-if="visibleColumns.includes('model_source')"
class="px-4 py-3 whitespace-nowrap">
<div class="text-sm text-gray-800 dark:text-gray-50">{{ row.ModelSource }}</div>
</td>
</tr>
</template>
<!-- 默认 Model 模式 -> 现有表格 -->
<template v-else>
<tr v-for="(model, index) in filteredLeaderboard" :key="model.rank" :class="{
// 'bg-yellow-50 dark:bg-yellow-700/25': index === 0,
// 'bg-gray-50 dark:bg-gray-800/60': index === 1,
// 'bg-indigo-50 dark:bg-indigo-700/25': index === 2
}" class="hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-150">
<td v-for="h in displayedColumns" :key="h" class="px-4 py-3 whitespace-nowrap">
<div class="text-sm text-gray-800 dark:text-gray-50">{{ formatCell(h, model) }}</div>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
<!-- 图表区域 -->
<div ref="chartSection" class="mt-8 bg-white dark:bg-gray-900/60 shadow rounded-lg overflow-hidden">
<!-- 图表头部 -->
<div
class="px-6 py-4 border-b bg-gradient-to-r from-indigo-50 via-white to-white dark:bg-gradient-to-r dark:from-gray-800 dark:via-gray-900 dark:to-gray-900">
<h2 class="text-lg font-medium text-gray-800 dark:text-gray-50">Data visualization</h2>
</div>
<!-- 图表数据集筛选区域 -->
<div class="px-6 py-3 border-b bg-gray-50 dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800">
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Dataset</span>
<div v-if="dataGroups.length > 0" class="flex gap-2 items-center overflow-x-auto">
<label v-for="g in dataGroups" :key="g"
class="px-2 py-1 rounded-full border border-gray-200 dark:border-gray-700 text-sm cursor-pointer dark:text-slate-300"
:class="{ 'bg-gray-100 dark:bg-gray-700 dark:text-white': selectedDataNameChart === g }">
<input type="radio" class="hidden" :value="g" v-model="selectedDataNameChart" /> <span
class="whitespace-nowrap">{{ dataNameDisplayMap[g]
? dataNameDisplayMap[g] : g }}</span>
</label>
</div>
<div v-else class="text-sm text-gray-500 dark:text-gray-400">(数据集中未检测到 data_name 列)</div>
</div>
</div>
<!-- 图表内容 -->
<div class="p-6">
<Chart :autoShowSeries="autoShowSeries" />
</div>
</div>
</div>
</div>
</template>
<style scoped></style>