| <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' |
| |
| |
| 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') |
| |
| |
| const isDark = ref(false) |
| |
| |
| const chartSection = ref(null) |
| |
| |
| const lastSelectedDataNameChart = ref('') |
| |
| |
| 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 = '3/10/2026 10:55' |
| |
| 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> |
| |
| <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"> |
| {'bg-gray-100 dark:bg-gray-700': selectedDataName==='all'} |
| |
| |
| <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"> |
| {'bg-gray-100 dark:bg-gray-700': selectedDataName==='all'} |
| |
| |
| <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> |
| |
| |
| <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> |
| |
| |
| |
| <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"> |
| |
| <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> |
| |
| |
| <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> |