Xianbao QIAN commited on
Commit
31767a7
1 Parent(s): 29c3483

Adapt the heatmap code for AI policy

Browse files
bun.lockb CHANGED
Binary files a/bun.lockb and b/bun.lockb differ
 
content/policies/data-safety/en.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ ---
2
+ title: English Policy Title
3
+ language: English
4
+ originalLink: https://example.com/policy1/en
5
+ ---
content/policies/data-safety/zh.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: 中文政策标题
3
+ language: 中文
4
+ originalLink: https://abc.com
5
+ ---
6
+
7
+ 这是中文版的政策内容。
content/policies/global-ai/en.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ ---
2
+ title: Global AI Policy
3
+ ---
4
+
5
+ Test global policy
content/policies/global-ai/zh.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ ---
2
+ title: 全球人工智能治理倡议
3
+ ---
package.json CHANGED
@@ -18,11 +18,13 @@
18
  "@radix-ui/react-tooltip": "^1.1.2",
19
  "class-variance-authority": "^0.7.0",
20
  "clsx": "^2.1.1",
 
21
  "lucide-react": "^0.427.0",
22
  "next": "14.2.5",
23
  "react": "^18",
24
  "react-activity-calendar": "^2.2.11",
25
  "react-dom": "^18",
 
26
  "tailwind-merge": "^2.4.0",
27
  "tailwindcss-animate": "^1.0.7"
28
  },
 
18
  "@radix-ui/react-tooltip": "^1.1.2",
19
  "class-variance-authority": "^0.7.0",
20
  "clsx": "^2.1.1",
21
+ "gray-matter": "^4.0.3",
22
  "lucide-react": "^0.427.0",
23
  "next": "14.2.5",
24
  "react": "^18",
25
  "react-activity-calendar": "^2.2.11",
26
  "react-dom": "^18",
27
+ "react-markdown": "^9.0.1",
28
  "tailwind-merge": "^2.4.0",
29
  "tailwindcss-animate": "^1.0.7"
30
  },
src/components/AIPoliciesTable.tsx ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import Link from 'next/link';
3
+
4
+ interface PolicyData {
5
+ title: string;
6
+ slug: string;
7
+ fileName: string;
8
+ originalLink?: string;
9
+ }
10
+
11
+ interface AIPoliciesTableProps {
12
+ policies: PolicyData[];
13
+ }
14
+
15
+ const AIPoliciesTable: React.FC<AIPoliciesTableProps> = ({ policies }) => {
16
+ const groupedPolicies: { [slug: string]: PolicyData[] } = {};
17
+
18
+ policies.forEach((policy) => {
19
+ if (!groupedPolicies[policy.slug]) {
20
+ groupedPolicies[policy.slug] = [];
21
+ }
22
+ groupedPolicies[policy.slug].push(policy);
23
+ });
24
+
25
+ return (
26
+ <div className="my-8">
27
+ <h2 className="text-2xl font-bold mb-4 dark:text-white">AI Policies</h2>
28
+ <div className="overflow-x-auto">
29
+ <table className="w-full border-collapse table-auto">
30
+ <tbody>
31
+ {Object.entries(groupedPolicies).map(([slug, policies], index) => {
32
+ const zhPolicy = policies.find((policy) => policy.fileName === 'zh.md');
33
+ const enPolicy = policies.find((policy) => policy.fileName === 'en.md');
34
+
35
+ return (
36
+ <tr key={slug} className={`${index % 2 === 0 ? 'bg-white dark:bg-gray-700' : 'bg-gray-50 dark:bg-gray-800'}`}>
37
+ <td className="py-2 px-4 dark:text-white">
38
+ <div>{zhPolicy?.title}</div>
39
+ <div className="text-sm text-gray-500 dark:text-gray-400">{enPolicy?.title}</div>
40
+ </td>
41
+ <td className="py-2 px-4">
42
+ {policies.map((policy) => (
43
+ policy.originalLink ? (
44
+ <a key={policy.fileName} href={policy.originalLink} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline dark:text-blue-400 mr-4">
45
+ {policy.fileName === 'zh.md' ? '中文' : 'English'}
46
+ </a>
47
+ ) : (
48
+ <Link key={policy.fileName} href={`/policies/${slug}/${policy.fileName}`}>
49
+ <span className="text-blue-500 hover:underline dark:text-blue-400 mr-4 cursor-pointer">
50
+ {policy.fileName === 'zh.md' ? '中文' : 'English'}
51
+ </span>
52
+ </Link>
53
+ )
54
+ ))}
55
+ </td>
56
+ </tr>
57
+ );
58
+ })}
59
+ </tbody>
60
+ </table>
61
+ </div>
62
+ </div>
63
+ );
64
+ };
65
+
66
+ export default AIPoliciesTable;
src/pages/_document.tsx CHANGED
@@ -1,13 +1,17 @@
1
- import { Html, Head, Main, NextScript } from "next/document";
2
 
3
- export default function Document() {
4
- return (
5
- <Html lang="en">
6
- <Head />
7
- <body>
8
- <Main />
9
- <NextScript />
10
- </body>
11
- </Html>
12
- );
 
 
13
  }
 
 
 
1
+ import Document, { Html, Head, Main, NextScript } from 'next/document';
2
 
3
+ class MyDocument extends Document {
4
+ render() {
5
+ return (
6
+ <Html className="dark">
7
+ <Head />
8
+ <body>
9
+ <Main />
10
+ <NextScript />
11
+ </body>
12
+ </Html>
13
+ );
14
+ }
15
  }
16
+
17
+ export default MyDocument;
src/pages/index.tsx CHANGED
@@ -1,46 +1,81 @@
1
  import React, { useState, useEffect, useMemo } from "react";
2
- import { generateCalendarData } from "../utils/calendar";
3
- import {
4
- OpenSourceHeatmapProps,
5
- ProviderInfo,
6
- ModelData,
7
- CalendarData,
8
- } from "../types/heatmap";
9
- import Heatmap from "../components/Heatmap";
10
- import { fetchAllProvidersData, fetchAllAuthorsData } from "../utils/authors";
11
- import UserSearchDialog from "../components/UserSearchDialog";
12
-
13
- const PROVIDERS: ProviderInfo[] = [
14
- { color: "#ff7000", authors: ["mistralai"] },
15
- { color: "#1877F2", authors: ["meta-llama", "facebook", ] },
16
- { color: "#10A37F", authors: ["openai"] },
17
- { color: "#cc785c", authors: ["Anthropic"] },
18
- { color: "#DB4437", authors: ["google"] },
19
- { color: "#5E35B1", authors: ["allenai"] },
20
- { color: "#0088cc", authors: ["apple"] },
21
- { color: "#FEB800", authors: ["microsoft"] },
22
- { color: "#76B900", authors: ["nvidia"] },
23
- { color: "#0088cc", authors: ["deepseek-ai"] },
24
- { color: "#0088cc", authors: ["Qwen"] },
25
- { color: "#4C6EE6", authors: ["CohereForAI"] },
26
- { color: "#4C6EE6", authors: ["ibm-granite"] },
27
- { color: "#A020F0", authors: ["stabilityai"] },
28
- ];
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  export async function getStaticProps() {
31
  try {
32
- const allAuthors = PROVIDERS.flatMap(({ authors }) => authors);
33
- const uniqueAuthors = Array.from(new Set(allAuthors));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
- const flatData: ModelData[] = await fetchAllAuthorsData(uniqueAuthors);
36
- const updatedProviders = await fetchAllProvidersData(PROVIDERS);
37
 
38
- const calendarData = generateCalendarData(flatData, updatedProviders);
 
 
 
39
 
40
  return {
41
  props: {
42
- calendarData,
43
- providers: updatedProviders,
 
44
  },
45
  revalidate: 3600, // regenerate every hour
46
  };
@@ -48,61 +83,66 @@ export async function getStaticProps() {
48
  console.error("Error fetching data:", error);
49
  return {
50
  props: {
51
- calendarData: {},
52
- providers: PROVIDERS,
 
53
  },
54
  revalidate: 60, // retry after 1 minute if there was an error
55
  };
56
  }
57
  }
58
 
59
- const ProviderHeatmap = React.memo(({ provider, calendarData }: { provider: ProviderInfo, calendarData: CalendarData }) => {
60
- const providerName = provider.fullName || provider.authors[0];
61
- return (
62
- <div key={providerName} className="flex flex-col items-center">
63
- <Heatmap
64
- data={calendarData[providerName]}
65
- color={provider.color}
66
- providerName={providerName}
67
- fullName={provider.fullName ?? providerName}
68
- avatarUrl={provider.avatarUrl ?? ''}
69
- />
70
- </div>
71
- );
72
- });
73
 
74
- const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({
75
- calendarData,
76
- providers,
 
77
  }) => {
78
- const [isLoading, setIsLoading] = useState(true);
79
 
80
- useEffect(() => {
81
- if (calendarData && Object.keys(calendarData).length > 0) {
82
- setIsLoading(false);
83
- }
84
- }, [calendarData]);
85
-
86
- const sortedProviders = useMemo(() =>
87
- providers.sort((a, b) =>
88
- calendarData[b.fullName || b.authors[0]].reduce(
89
- (sum, day) => sum + day.count,
90
- 0
91
- ) -
92
- calendarData[a.fullName || a.authors[0]].reduce(
93
- (sum, day) => sum + day.count,
94
- 0
95
- )
96
- ),
97
- [providers, calendarData]
98
- );
99
 
100
  return (
101
- <div className="w-full max-w-screen-lg mx-auto p-4 py-16">
102
  <h1 className="text-3xl lg:text-5xl mt-16 font-bold text-center mb-2">
103
  Hugging Face Heatmap 🤗
104
  </h1>
105
- <div className="text-center text-sm my-8 space-y-4">
 
 
 
106
  <p>
107
  Models, Datasets, and Spaces from the top AI labs.
108
  </p>
@@ -111,7 +151,7 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({
111
  </div>
112
  </div>
113
 
114
- <div className="h-px max-w-lg mx-auto bg-gray-200 my-16" />
115
 
116
  {isLoading ? (
117
  <p className="text-center">Loading...</p>
@@ -125,9 +165,9 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({
125
  />
126
  ))}
127
  </div>
128
- )}
129
  </div>
130
  );
131
  };
132
 
133
- export default React.memo(OpenSourceHeatmap);
 
1
  import React, { useState, useEffect, useMemo } from "react";
2
+ // import { generateCalendarData } from "../utils/calendar";
3
+ // import {
4
+ // OpenSourceHeatmapProps,
5
+ // ProviderInfo,
6
+ // ModelData,
7
+ // CalendarData,
8
+ // } from "../types/heatmap";
9
+ // import Heatmap from "../components/Heatmap";
10
+ // import { fetchAllProvidersData, fetchAllAuthorsData } from "../utils/authors";
11
+ // import UserSearchDialog from "../components/UserSearchDialog";
12
+ import AIPoliciesTable from "../components/AIPoliciesTable";
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import matter from 'gray-matter';
16
+
17
+ // const PROVIDERS: ProviderInfo[] = [
18
+ // { color: "#ff7000", authors: ["mistralai"] },
19
+ // { color: "#1877F2", authors: ["meta-llama", "facebook", ] },
20
+ // { color: "#10A37F", authors: ["openai"] },
21
+ // { color: "#cc785c", authors: ["Anthropic"] },
22
+ // { color: "#DB4437", authors: ["google"] },
23
+ // { color: "#5E35B1", authors: ["allenai"] },
24
+ // { color: "#0088cc", authors: ["apple"] },
25
+ // { color: "#FEB800", authors: ["microsoft"] },
26
+ // { color: "#76B900", authors: ["nvidia"] },
27
+ // { color: "#0088cc", authors: ["deepseek-ai"] },
28
+ // { color: "#0088cc", authors: ["Qwen"] },
29
+ // { color: "#4C6EE6", authors: ["CohereForAI"] },
30
+ // { color: "#4C6EE6", authors: ["ibm-granite"] },
31
+ // { color: "#A020F0", authors: ["stabilityai"] },
32
+ // ];
33
+
34
+ interface PolicyData {
35
+ title: string;
36
+ language: string;
37
+ originalLink: string;
38
+ slug: string;
39
+ fileName: string;
40
+ }
41
 
42
  export async function getStaticProps() {
43
  try {
44
+ // const allAuthors = PROVIDERS.flatMap(({ authors }) => authors);
45
+ // const uniqueAuthors = Array.from(new Set(allAuthors));
46
+
47
+ // const flatData: ModelData[] = await fetchAllAuthorsData(uniqueAuthors);
48
+ // const updatedProviders = await fetchAllProvidersData(PROVIDERS);
49
+
50
+ // const calendarData = generateCalendarData(flatData, updatedProviders);
51
+
52
+ // Read policy data
53
+ const policiesDir = path.join(process.cwd(), 'content', 'policies');
54
+ const policyFolders = fs.readdirSync(policiesDir);
55
+
56
+ const policyData: PolicyData[] = [];
57
+
58
+ for (const folder of policyFolders) {
59
+ const zhFilePath = path.join(policiesDir, folder, 'zh.md');
60
+ const enFilePath = path.join(policiesDir, folder, 'en.md');
61
+
62
+ if (fs.existsSync(zhFilePath) && fs.existsSync(enFilePath)) {
63
+ const zhContent = fs.readFileSync(zhFilePath, 'utf-8');
64
+ const enContent = fs.readFileSync(enFilePath, 'utf-8');
65
 
66
+ const { data: zhData } = matter(zhContent);
67
+ const { data: enData } = matter(enContent);
68
 
69
+ policyData.push({ ...zhData, slug: folder, fileName: 'zh.md' } as PolicyData);
70
+ policyData.push({ ...enData, slug: folder, fileName: 'en.md' } as PolicyData);
71
+ }
72
+ }
73
 
74
  return {
75
  props: {
76
+ // calendarData,
77
+ // providers: updatedProviders,
78
+ policyData, // Pass policy data as props
79
  },
80
  revalidate: 3600, // regenerate every hour
81
  };
 
83
  console.error("Error fetching data:", error);
84
  return {
85
  props: {
86
+ // calendarData: {},
87
+ // providers: PROVIDERS,
88
+ policyData: [], // Pass empty policy data as props
89
  },
90
  revalidate: 60, // retry after 1 minute if there was an error
91
  };
92
  }
93
  }
94
 
95
+ // const ProviderHeatmap = React.memo(({ provider, calendarData }: { provider: ProviderInfo, calendarData: CalendarData }) => {
96
+ // const providerName = provider.fullName || provider.authors[0];
97
+ // return (
98
+ // <div key={providerName} className="flex flex-col items-center">
99
+ // <Heatmap
100
+ // data={calendarData[providerName]}
101
+ // color={provider.color}
102
+ // providerName={providerName}
103
+ // fullName={provider.fullName ?? providerName}
104
+ // avatarUrl={provider.avatarUrl ?? ''}
105
+ // />
106
+ // </div>
107
+ // );
108
+ // });
109
 
110
+ const OpenSourceHeatmap: React.FC<{ policyData: PolicyData[] }> = ({
111
+ // calendarData,
112
+ // providers,
113
+ policyData,
114
  }) => {
115
+ // const [isLoading, setIsLoading] = useState(true);
116
 
117
+ // useEffect(() => {
118
+ // if (calendarData && Object.keys(calendarData).length > 0) {
119
+ // setIsLoading(false);
120
+ // }
121
+ // }, [calendarData]);
122
+
123
+ // const sortedProviders = useMemo(() =>
124
+ // providers.sort((a, b) =>
125
+ // calendarData[b.fullName || b.authors[0]].reduce(
126
+ // (sum, day) => sum + day.count,
127
+ // 0
128
+ // ) -
129
+ // calendarData[a.fullName || a.authors[0]].reduce(
130
+ // (sum, day) => sum + day.count,
131
+ // 0
132
+ // )
133
+ // ),
134
+ // [providers, calendarData]
135
+ // );
136
 
137
  return (
138
+ <div className="w-full max-w-screen-lg mx-auto p-4 py-16 dark:bg-gray-900 dark:text-white">
139
  <h1 className="text-3xl lg:text-5xl mt-16 font-bold text-center mb-2">
140
  Hugging Face Heatmap 🤗
141
  </h1>
142
+
143
+ <AIPoliciesTable policies={policyData} />
144
+
145
+ {/* <div className="text-center text-sm my-8 space-y-4">
146
  <p>
147
  Models, Datasets, and Spaces from the top AI labs.
148
  </p>
 
151
  </div>
152
  </div>
153
 
154
+ <div className="h-px max-w-lg mx-auto bg-gray-200 dark:bg-gray-700 my-16" />
155
 
156
  {isLoading ? (
157
  <p className="text-center">Loading...</p>
 
165
  />
166
  ))}
167
  </div>
168
+ )} */}
169
  </div>
170
  );
171
  };
172
 
173
+ export default React.memo(OpenSourceHeatmap);
src/pages/policies/[slug].tsx ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { GetStaticProps, GetStaticPaths } from 'next';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import matter from 'gray-matter';
6
+ import ReactMarkdown from 'react-markdown';
7
+
8
+ interface PolicyProps {
9
+ content: string;
10
+ }
11
+
12
+ const PolicyPage: React.FC<PolicyProps> = ({ content }) => {
13
+ return (
14
+ <div className="container mx-auto py-8">
15
+ <ReactMarkdown>{content}</ReactMarkdown>
16
+ </div>
17
+ );
18
+ };
19
+
20
+ export const getStaticPaths: GetStaticPaths = async () => {
21
+ return {
22
+ paths: [],
23
+ fallback: false,
24
+ };
25
+ };
26
+
27
+ export const getStaticProps: GetStaticProps<PolicyProps> = async ({ params }) => {
28
+ const { slug, fileName } = params as { slug: string; fileName: string };
29
+ const filePath = path.join(process.cwd(), 'content', 'policies', slug, fileName);
30
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
31
+ const { content } = matter(fileContent);
32
+
33
+ return {
34
+ props: {
35
+ content,
36
+ },
37
+ };
38
+ };
39
+
40
+ export default PolicyPage;
src/pages/policies/[slug]/[fileName].tsx ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { GetStaticProps, GetStaticPaths } from 'next';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import matter from 'gray-matter';
6
+ import ReactMarkdown from 'react-markdown';
7
+
8
+ interface PolicyProps {
9
+ content: string;
10
+ }
11
+
12
+ const PolicyPage: React.FC<PolicyProps> = ({ content }) => {
13
+ return (
14
+ <div className="container mx-auto py-8">
15
+ <ReactMarkdown>{content}</ReactMarkdown>
16
+ </div>
17
+ );
18
+ };
19
+
20
+ export const getStaticPaths: GetStaticPaths = async () => {
21
+ const policiesDir = path.join(process.cwd(), 'content', 'policies');
22
+ const policyFolders = fs.readdirSync(policiesDir);
23
+
24
+ const paths = policyFolders.flatMap((folder) => {
25
+ const languageFiles = fs.readdirSync(path.join(policiesDir, folder));
26
+ return languageFiles.map((file) => {
27
+ return { params: { slug: folder, fileName: file } };
28
+ });
29
+ });
30
+
31
+ return {
32
+ paths,
33
+ fallback: false,
34
+ };
35
+ };
36
+
37
+ export const getStaticProps: GetStaticProps<PolicyProps> = async ({ params }) => {
38
+ const { slug, fileName } = params as { slug: string; fileName: string };
39
+ const filePath = path.join(process.cwd(), 'content', 'policies', slug, fileName);
40
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
41
+ const { content } = matter(fileContent);
42
+
43
+ return {
44
+ props: {
45
+ content,
46
+ },
47
+ };
48
+ };
49
+
50
+ export default PolicyPage;