File size: 6,051 Bytes
428d2d6 633e5e5 428d2d6 5e26aa6 b17ac62 428d2d6 4fe065f 428d2d6 4fe065f e4c1ec6 14b7a3b 9b1fb70 428d2d6 5e26aa6 ecba77a 633e5e5 428d2d6 ecba77a 633e5e5 5e26aa6 ecba77a 633e5e5 02bf005 428d2d6 633e5e5 b41495f 02bf005 633e5e5 b41495f ecba77a 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 5e26aa6 633e5e5 ecba77a 633e5e5 ecba77a 633e5e5 428d2d6 87761a0 9f6f162 428d2d6 b17ac62 428d2d6 b17ac62 633e5e5 428d2d6 5e26aa6 633e5e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
import React, { useState, useEffect } from 'react';
import ActivityCalendar from "react-activity-calendar";
import { Tooltip } from '@mui/material';
interface ProviderInfo {
color: string;
authors: string[];
}
const PROVIDERS_MAP: Record<string, ProviderInfo> = {
"Mistral AI": { color: "#ff7000", authors: ["mistralai"] },
"Meta": { color: "#1877F2", authors: ["facebook", "meta-llama"] },
"OpenAI": { color: "#10A37F", authors: ["openai"] },
"Anthropic": { color: "#cc785c", authors: ["Anthropic"] },
"Google": { color: "#DB4437", authors: ["google"] },
"Allen Institute for AI": { color: "#5E35B1", authors: ["allenai"] },
"Apple": { color: "#0088cc", authors: ["apple"] },
"Microsoft": { color: "#FEB800", authors: ["microsoft"] },
"NVIDIA": { color: "#76B900", authors: ["nvidia"] },
"DeepSeek": { color: "#0088cc", authors: ["deepseek-ai"] },
"Qwen": { color: "#0088cc", authors: ["Qwen"] },
"Cohere For AI": { color: "#4C6EE6", authors: ["CohereForAI"] },
"IBM": { color: "#4C6EE6", authors: ["ibm-granite"] },
"Stability AI": { color: "#A020F0", authors: ["stabilityai"] },
};
interface ModelData {
createdAt: string;
id: string;
}
interface Activity {
date: string;
count: number;
level: number;
}
export default function OpenSourceHeatmap() {
const [calendarData, setCalendarData] = useState<Record<string, Activity[]>>({});
const [isLoading, setIsLoading] = useState(true);
const generateCalendarData = (modelData: ModelData[]) => {
const data: Record<string, Activity[]> = Object.fromEntries(
Object.keys(PROVIDERS_MAP).map(provider => [provider, []])
);
const today = new Date();
const startDate = new Date(today);
startDate.setMonth(today.getMonth() - 11);
startDate.setDate(1);
// create a map to store counts for each provider and date
const countMap: Record<string, Record<string, number>> = {};
modelData.forEach(item => {
const dateString = item.createdAt.split('T')[0];
Object.entries(PROVIDERS_MAP).forEach(([provider, { authors }]) => {
if (authors.some(author => item.id.startsWith(author))) {
countMap[provider] = countMap[provider] || {};
countMap[provider][dateString] = (countMap[provider][dateString] || 0) + 1;
}
});
});
// fill in with 0s for days with no activity
for (let d = new Date(startDate); d <= today; d.setDate(d.getDate() + 1)) {
const dateString = d.toISOString().split('T')[0];
Object.entries(PROVIDERS_MAP).forEach(([provider]) => {
const count = countMap[provider]?.[dateString] || 0;
data[provider].push({ date: dateString, count, level: 0 });
});
}
// calculate average counts for each provider
const avgCounts = Object.fromEntries(
Object.entries(data).map(([provider, days]) => [
provider,
days.reduce((sum, day) => sum + day.count, 0) / days.length || 0
])
);
// assign levels based on count relative to average
Object.entries(data).forEach(([provider, days]) => {
const avgCount = avgCounts[provider];
days.forEach(day => {
day.level =
day.count === 0 ? 0 :
day.count <= avgCount * 0.5 ? 1 :
day.count <= avgCount ? 2 :
day.count <= avgCount * 1.5 ? 3 : 4;
});
});
return data;
}
const initData = async () => {
try {
const allAuthors = Object.values(PROVIDERS_MAP).flatMap(({ authors }) => authors);
const uniqueAuthors = Array.from(new Set(allAuthors));
const allModelData = await Promise.all(
uniqueAuthors.map(async (author) => {
const response = await fetch(`https://huggingface.co/api/models?author=${author}&sort=createdAt&direction=-1`);
const data = await response.json();
return data.map((item: any) => ({
createdAt: item.createdAt,
id: item.id,
}));
})
);
const flatModelData = allModelData.flat();
const calendarData = generateCalendarData(flatModelData);
setCalendarData(calendarData);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
setIsLoading(false);
}
}
useEffect(() => {
initData();
}, []);
return (
<div className="w-full max-w-screen-lg mx-auto p-4">
<h1 className="text-3xl lg:text-5xl mt-16 font-bold text-center mb-2">Hugging Face Heatmap 🤗</h1>
<p className="text-center text-sm mb-8">The top AI labs and model releases. Request more heatmaps by [opening a discussion](https://huggingface.co/spaces/cfahlgren1/model-release-heatmap/discussions/new).</p>
{isLoading ? (
<p className="text-center">Loading...</p>
) : (
<div className="space-y-8">
{Object.entries(PROVIDERS_MAP)
.sort(([keyA], [keyB]) =>
calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
calendarData[keyA].reduce((sum, day) => sum + day.count, 0)
)
.map(([providerName, { color }]) => (
<div key={providerName} className="flex flex-col items-center">
<h2 className="text-xl font-bold mb-4">{providerName}</h2>
<div className="w-full overflow-x-auto flex justify-center">
<ActivityCalendar
data={calendarData[providerName]}
theme={{
dark: ['#161b22', color],
light: ['#e0e0e0', color],
}}
hideTotalCount
renderBlock={(block, activity) => (
<Tooltip
title={`${activity.count} models created on ${activity.date}`}
arrow
>
{block}
</Tooltip>
)}
/>
</div>
</div>
))
}
</div>
)}
</div>
);
} |