diff --git a/experiments/ethereum-repo-clusters/.gitignore b/experiments/ethereum-repo-clusters/.gitignore
index 58ae5f3c..552a22b5 100644
--- a/experiments/ethereum-repo-clusters/.gitignore
+++ b/experiments/ethereum-repo-clusters/.gitignore
@@ -35,4 +35,4 @@ ENV/
# Project specific
data/
-output/
\ No newline at end of file
+output*/
\ No newline at end of file
diff --git a/experiments/ethereum-repo-clusters/CategorySummary.ipynb b/experiments/ethereum-repo-clusters/CategorySummary.ipynb
index 9ca79d6b..8ccc2076 100644
--- a/experiments/ethereum-repo-clusters/CategorySummary.ipynb
+++ b/experiments/ethereum-repo-clusters/CategorySummary.ipynb
@@ -14,7 +14,7 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "add99052-fecf-4130-9cc5-b7413c643864",
+ "id": "7ebc1141",
"metadata": {},
"outputs": [
{
@@ -39,16 +39,14 @@
"
\n",
" | \n",
" repo_artifact_id | \n",
- " project_id | \n",
- " project_name | \n",
- " display_name | \n",
" repo_artifact_namespace | \n",
" repo_artifact_name | \n",
" created_at | \n",
" updated_at | \n",
" star_count | \n",
" fork_count | \n",
- " ... | \n",
+ " is_fork | \n",
+ " num_packages_in_deps_dev | \n",
" is_actively_maintained | \n",
" final_recommendation | \n",
" processing_timestamp | \n",
@@ -65,16 +63,14 @@
"
\n",
" | 0 | \n",
" jXXy/fnXRva/c1jf/Weav9O3pWDHf/lVArjj0/oteUM= | \n",
- " KLkMfahLmIEtzAbihkJ4U9p0e/3zWn0iN6xBrwN++lU= | \n",
- " ethereum-attestation-service | \n",
- " Ethereum Attestation Service | \n",
" ethereum-attestation-service | \n",
" eas-docs-site | \n",
" 2022-11-09 19:39:56.000 UTC | \n",
" 2025-06-02 15:51:08.000 UTC | \n",
" 17 | \n",
" 39 | \n",
- " ... | \n",
+ " False | \n",
+ " 0 | \n",
" True | \n",
" Developer Experience Tools | \n",
" 2025-06-06T00:55:35.737447 | \n",
@@ -89,16 +85,14 @@
"
\n",
" | 1 | \n",
" Ymt6ZmVh75JL7ml3IM9hU32qFd+GB84kXijLttRFS+w= | \n",
- " 4JnmAZ2ikJpcjoRMX+2ZLxAQ10don2FQd6yPyDaBZ20= | \n",
- " erigontech | \n",
- " erigontech | \n",
" erigontech | \n",
" gmp-wasm | \n",
" 2020-12-16 08:27:02.000 UTC | \n",
" 2025-03-24 16:40:59.000 UTC | \n",
" 17 | \n",
" 4 | \n",
- " ... | \n",
+ " False | \n",
+ " 0 | \n",
" True | \n",
" Cryptography & Primitives | \n",
" 2025-06-06T00:55:27.645719 | \n",
@@ -113,16 +107,14 @@
"
\n",
" | 2 | \n",
" sTL/I78T3P6uyVN+En480uSHiTXT7UdHPmKQlvWxCkc= | \n",
- " 4JnmAZ2ikJpcjoRMX+2ZLxAQ10don2FQd6yPyDaBZ20= | \n",
- " erigontech | \n",
- " erigontech | \n",
" erigontech | \n",
" diagnostics | \n",
" 2023-02-22 11:05:42.000 UTC | \n",
" 2025-04-25 07:42:52.000 UTC | \n",
" 17 | \n",
" 21 | \n",
- " ... | \n",
+ " False | \n",
+ " 1 | \n",
" True | \n",
" Infrastructure & Node Operations | \n",
" 2025-06-06T00:55:20.010674 | \n",
@@ -137,16 +129,14 @@
"
\n",
" | 3 | \n",
" 9C23r6x0hqtbR/lB/1nYpc5KVgCtm4ga+lOJa4gd2cY= | \n",
- " Fs/BFdYMfeuzzzWPOX3dtOA6Z4AOJsB2eO2JIoZEzUo= | \n",
- " ensdomains | \n",
- " ENS | \n",
" ensdomains | \n",
" court | \n",
" 2018-05-02 19:41:02.000 UTC | \n",
" 2025-05-20 03:41:25.000 UTC | \n",
" 17 | \n",
" 7 | \n",
- " ... | \n",
+ " False | \n",
+ " 0 | \n",
" True | \n",
" Application-Specific & Niche Tools | \n",
" 2025-06-06T00:55:11.604116 | \n",
@@ -161,16 +151,14 @@
"
\n",
" | 4 | \n",
" j9aT6b4e9dCsCbJ42JXen90EHik4VhyLFvX2RjeiJGM= | \n",
- " Fs/BFdYMfeuzzzWPOX3dtOA6Z4AOJsB2eO2JIoZEzUo= | \n",
- " ensdomains | \n",
- " ENS | \n",
" ensdomains | \n",
" op-resolver | \n",
" 2022-11-03 11:14:36.000 UTC | \n",
" 2025-05-20 03:21:33.000 UTC | \n",
" 17 | \n",
" 6 | \n",
- " ... | \n",
+ " False | \n",
+ " 0 | \n",
" True | \n",
" Interoperability & Cross-chain | \n",
" 2025-06-06T00:55:03.917944 | \n",
@@ -203,22 +191,18 @@
" ... | \n",
" ... | \n",
" ... | \n",
- " ... | \n",
- " ... | \n",
"
\n",
" \n",
" | 5234 | \n",
" AcuAtRmOCfY1rQN0rAx8iP5pdbgveBahZYSWK2leQq4= | \n",
- " AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= | \n",
- " fuellabs | \n",
- " Fuel Network | \n",
" fuellabs | \n",
" fuels-rs | \n",
" 2021-10-31 22:33:54.000 UTC | \n",
" 2025-06-03 17:34:29.000 UTC | \n",
" 43747 | \n",
" 1355 | \n",
- " ... | \n",
+ " False | \n",
+ " 13 | \n",
" True | \n",
" Development Frameworks | \n",
" 2025-06-05T14:24:14.479181 | \n",
@@ -233,16 +217,14 @@
"
\n",
" | 5235 | \n",
" JfvNeHojsqThZKXGfbrSSW4JIf2db88eIku67txzj9w= | \n",
- " vD6QgU2nKpWiutcCnblDJkVHtDkLDH6oyITV+xpe3+g= | \n",
- " go-ethereum | \n",
- " geth | \n",
" ethereum | \n",
" go-ethereum | \n",
" 2013-12-26 13:05:46.000 UTC | \n",
" 2025-06-03 16:54:54.000 UTC | \n",
" 49065 | \n",
" 20888 | \n",
- " ... | \n",
+ " False | \n",
+ " 2 | \n",
" True | \n",
" Infrastructure & Node Operations | \n",
" 2025-06-05T14:24:08.096520 | \n",
@@ -257,16 +239,14 @@
"
\n",
" | 5236 | \n",
" imBvQgAogfFYL0+hque3sUxe+dN53nsDQFoz1q1jgDA= | \n",
- " AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= | \n",
- " fuellabs | \n",
- " Fuel Network | \n",
" fuellabs | \n",
" fuel-core | \n",
" 2020-08-27 21:12:14.000 UTC | \n",
" 2025-06-03 17:34:30.000 UTC | \n",
" 57637 | \n",
" 2852 | \n",
- " ... | \n",
+ " False | \n",
+ " 45 | \n",
" True | \n",
" Infrastructure & Node Operations | \n",
" 2025-06-05T14:24:01.176979 | \n",
@@ -281,16 +261,14 @@
"
\n",
" | 5237 | \n",
" XK2KsRrMXU8N9WUAXb0V+X2pZWgx9H2UCtaJ6IONUC4= | \n",
- " AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= | \n",
- " fuellabs | \n",
- " Fuel Network | \n",
" fuellabs | \n",
" sway | \n",
" 2021-01-19 20:54:33.000 UTC | \n",
" 2025-06-03 17:34:31.000 UTC | \n",
" 62255 | \n",
" 5405 | \n",
- " ... | \n",
+ " False | \n",
+ " 29 | \n",
" True | \n",
" Language & Compilation Tools | \n",
" 2025-06-05T14:23:54.181337 | \n",
@@ -305,16 +283,14 @@
"
\n",
" | 5238 | \n",
" ACDSfw399At2CyBKEzgNCwOZ3zvC990eWZjGw+Z8isA= | \n",
- " cJt1yXO/geeLxyt++Pe5iU+kUyklaoGot3rHqrDNk1o= | \n",
- " base-org | \n",
- " Base | \n",
" base-org | \n",
" node | \n",
" 2023-02-01 13:55:02.000 UTC | \n",
" 2025-02-10 01:22:12.000 UTC | \n",
" 68568 | \n",
" 2635 | \n",
- " ... | \n",
+ " False | \n",
+ " 0 | \n",
" True | \n",
" Infrastructure & Node Operations | \n",
" 2025-06-05T14:23:47.813647 | \n",
@@ -328,7 +304,7 @@
"
\n",
" \n",
"\n",
- "5239 rows × 22 columns
\n",
+ "5239 rows × 19 columns
\n",
""
],
"text/plain": [
@@ -345,32 +321,6 @@
"5237 XK2KsRrMXU8N9WUAXb0V+X2pZWgx9H2UCtaJ6IONUC4= \n",
"5238 ACDSfw399At2CyBKEzgNCwOZ3zvC990eWZjGw+Z8isA= \n",
"\n",
- " project_id \\\n",
- "0 KLkMfahLmIEtzAbihkJ4U9p0e/3zWn0iN6xBrwN++lU= \n",
- "1 4JnmAZ2ikJpcjoRMX+2ZLxAQ10don2FQd6yPyDaBZ20= \n",
- "2 4JnmAZ2ikJpcjoRMX+2ZLxAQ10don2FQd6yPyDaBZ20= \n",
- "3 Fs/BFdYMfeuzzzWPOX3dtOA6Z4AOJsB2eO2JIoZEzUo= \n",
- "4 Fs/BFdYMfeuzzzWPOX3dtOA6Z4AOJsB2eO2JIoZEzUo= \n",
- "... ... \n",
- "5234 AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= \n",
- "5235 vD6QgU2nKpWiutcCnblDJkVHtDkLDH6oyITV+xpe3+g= \n",
- "5236 AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= \n",
- "5237 AmxsQKHnsygqA+a7WJawinHjVclh84R+edks3EL9jiM= \n",
- "5238 cJt1yXO/geeLxyt++Pe5iU+kUyklaoGot3rHqrDNk1o= \n",
- "\n",
- " project_name display_name \\\n",
- "0 ethereum-attestation-service Ethereum Attestation Service \n",
- "1 erigontech erigontech \n",
- "2 erigontech erigontech \n",
- "3 ensdomains ENS \n",
- "4 ensdomains ENS \n",
- "... ... ... \n",
- "5234 fuellabs Fuel Network \n",
- "5235 go-ethereum geth \n",
- "5236 fuellabs Fuel Network \n",
- "5237 fuellabs Fuel Network \n",
- "5238 base-org Base \n",
- "\n",
" repo_artifact_namespace repo_artifact_name \\\n",
"0 ethereum-attestation-service eas-docs-site \n",
"1 erigontech gmp-wasm \n",
@@ -397,18 +347,18 @@
"5237 2021-01-19 20:54:33.000 UTC 2025-06-03 17:34:31.000 UTC 62255 \n",
"5238 2023-02-01 13:55:02.000 UTC 2025-02-10 01:22:12.000 UTC 68568 \n",
"\n",
- " fork_count ... is_actively_maintained \\\n",
- "0 39 ... True \n",
- "1 4 ... True \n",
- "2 21 ... True \n",
- "3 7 ... True \n",
- "4 6 ... True \n",
- "... ... ... ... \n",
- "5234 1355 ... True \n",
- "5235 20888 ... True \n",
- "5236 2852 ... True \n",
- "5237 5405 ... True \n",
- "5238 2635 ... True \n",
+ " fork_count is_fork num_packages_in_deps_dev is_actively_maintained \\\n",
+ "0 39 False 0 True \n",
+ "1 4 False 0 True \n",
+ "2 21 False 1 True \n",
+ "3 7 False 0 True \n",
+ "4 6 False 0 True \n",
+ "... ... ... ... ... \n",
+ "5234 1355 False 13 True \n",
+ "5235 20888 False 2 True \n",
+ "5236 2852 False 45 True \n",
+ "5237 5405 False 29 True \n",
+ "5238 2635 False 0 True \n",
"\n",
" final_recommendation processing_timestamp \\\n",
"0 Developer Experience Tools 2025-06-06T00:55:35.737447 \n",
@@ -475,7 +425,7 @@
"5237 Language & Compilation Tools \n",
"5238 Infrastructure & Node Operations \n",
"\n",
- "[5239 rows x 22 columns]"
+ "[5239 rows x 19 columns]"
]
},
"execution_count": 2,
@@ -484,7 +434,7 @@
}
],
"source": [
- "df = pd.read_parquet('output/ethereum_repos_unified.parquet')\n",
+ "df = pd.read_parquet('output_v1/ethereum_repos_unified.parquet')\n",
"df[\"categorizations_list\"] = df[\"categorizations_json\"].apply(json.loads)\n",
"\n",
"def persona_to_category_map(cats_list):\n",
@@ -493,18 +443,386 @@
"df_persona_cols = pd.json_normalize(df_persona_map)\n",
"\n",
"df = df.join(df_persona_cols)\n",
- "df = df.drop(columns=[\"categorizations_list\", \"categorizations_json\", \"readme_md\"])\n",
- "#df.to_csv('categorizations.csv')\n",
+ "df = df.drop(columns=[\"categorizations_list\", \"categorizations_json\", \"readme_md\",\n",
+ " \"project_id\", \"project_name\", \"display_name\"])\n",
+ "df.to_parquet('results/ethereum_repo_categories_v1.parquet')\n",
"df"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "368d46ba-cedc-455d-a246-925b6c996090",
+ "execution_count": 3,
+ "id": "38245c13",
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " repo_artifact_id | \n",
+ " repo_artifact_namespace | \n",
+ " repo_artifact_name | \n",
+ " created_at | \n",
+ " updated_at | \n",
+ " language | \n",
+ " star_count | \n",
+ " fork_count | \n",
+ " is_fork | \n",
+ " num_packages_in_deps_dev | \n",
+ " is_actively_maintained | \n",
+ " final_recommendation | \n",
+ " processing_timestamp | \n",
+ " summary | \n",
+ " readme_status | \n",
+ " technical_reviewer | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " V52vAnlOFdRUfRIo8faESeAAwQDFIaOaQtBBCBw6a5Y= | \n",
+ " zypher-game | \n",
+ " uzkge | \n",
+ " 2023-12-29 01:28:42.000 UTC | \n",
+ " 2025-02-13 23:01:42.000 UTC | \n",
+ " Rust | \n",
+ " 10 | \n",
+ " 5 | \n",
+ " False | \n",
+ " 6 | \n",
+ " True | \n",
+ " Gaming & Metaverse Applications | \n",
+ " 2025-06-29T17:38:19.154152 | \n",
+ " uzkge is a universal zero-knowledge game engin... | \n",
+ " SUCCESS | \n",
+ " Gaming & Metaverse Applications | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " oEFKnNgSqEV+JQFLApgDkArvoXqpYJkPmIcoePwkKAc= | \n",
+ " zklinkprotocol | \n",
+ " zklink-docs-gitbook | \n",
+ " 2023-06-15 09:30:45.000 UTC | \n",
+ " 2025-04-01 04:49:42.000 UTC | \n",
+ " | \n",
+ " 10 | \n",
+ " 3 | \n",
+ " False | \n",
+ " 0 | \n",
+ " True | \n",
+ " Scaling & Layer‑2 Frameworks | \n",
+ " 2025-06-29T17:38:16.295766 | \n",
+ " zkLink X provides an aggregated rollup infrast... | \n",
+ " SUCCESS | \n",
+ " Scaling & Layer‑2 Frameworks | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 9ShJYJxtK0uLqvR89mweTLTrIFwDmKmovC3LpAU73Es= | \n",
+ " zkblind | \n",
+ " zkblindnextjs | \n",
+ " 2023-04-23 09:20:16.000 UTC | \n",
+ " 2024-10-20 18:05:28.000 UTC | \n",
+ " Circom | \n",
+ " 10 | \n",
+ " 2 | \n",
+ " False | \n",
+ " 0 | \n",
+ " True | \n",
+ " Identity & Credentials | \n",
+ " 2025-06-29T17:38:13.661183 | \n",
+ " zkBind authenticates a user's employment at a ... | \n",
+ " SUCCESS | \n",
+ " Identity & Credentials | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " GVAT0dh82iHu/5NvZXbKkrn/f2FBx5PBFgof38zKYIU= | \n",
+ " zerolend | \n",
+ " docs.zerolend.xyz | \n",
+ " 2023-07-16 19:46:10.000 UTC | \n",
+ " 2025-04-08 10:30:18.000 UTC | \n",
+ " | \n",
+ " 10 | \n",
+ " 6 | \n",
+ " False | \n",
+ " 0 | \n",
+ " True | \n",
+ " DeFi Protocols & Financial Primitives | \n",
+ " 2025-06-29T17:38:11.132290 | \n",
+ " ZeroLend is a multi-chain, non-custodial lendi... | \n",
+ " SUCCESS | \n",
+ " DeFi Protocols & Financial Primitives | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 983Z1VR9Jhb1ODQtDG1jr6tg8XDiTkb5eLroTzj2SBg= | \n",
+ " zeriontech | \n",
+ " wallet-core-ios | \n",
+ " 2022-04-21 11:01:08.000 UTC | \n",
+ " 2025-01-10 12:41:20.000 UTC | \n",
+ " Swift | \n",
+ " 10 | \n",
+ " 2 | \n",
+ " False | \n",
+ " 0 | \n",
+ " True | \n",
+ " Wallets & Account Abstraction | \n",
+ " 2025-06-29T17:38:08.757093 | \n",
+ " Zerion Wallet Core provides wallet functionali... | \n",
+ " SUCCESS | \n",
+ " Wallets & Account Abstraction | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 7044 | \n",
+ " AcuAtRmOCfY1rQN0rAx8iP5pdbgveBahZYSWK2leQq4= | \n",
+ " fuellabs | \n",
+ " fuels-rs | \n",
+ " 2021-10-31 22:33:54.000 UTC | \n",
+ " 2025-06-25 10:19:58.000 UTC | \n",
+ " Rust | \n",
+ " 43711 | \n",
+ " 1356 | \n",
+ " False | \n",
+ " 13 | \n",
+ " True | \n",
+ " Development Frameworks & Tooling | \n",
+ " 2025-06-29T13:02:17.913939 | \n",
+ " The fuels-rs project is a Rust SDK for the Fue... | \n",
+ " SUCCESS | \n",
+ " Development Frameworks & Tooling | \n",
+ "
\n",
+ " \n",
+ " | 7045 | \n",
+ " JfvNeHojsqThZKXGfbrSSW4JIf2db88eIku67txzj9w= | \n",
+ " ethereum | \n",
+ " go-ethereum | \n",
+ " 2013-12-26 13:05:46.000 UTC | \n",
+ " 2025-06-25 14:38:46.000 UTC | \n",
+ " Go | \n",
+ " 49198 | \n",
+ " 20940 | \n",
+ " False | \n",
+ " 2 | \n",
+ " True | \n",
+ " Execution Clients & Core Protocol | \n",
+ " 2025-06-29T13:02:16.065323 | \n",
+ " Go Ethereum (geth) is a Golang implementation ... | \n",
+ " SUCCESS | \n",
+ " Execution Clients & Core Protocol | \n",
+ "
\n",
+ " \n",
+ " | 7046 | \n",
+ " imBvQgAogfFYL0+hque3sUxe+dN53nsDQFoz1q1jgDA= | \n",
+ " fuellabs | \n",
+ " fuel-core | \n",
+ " 2020-08-27 21:12:14.000 UTC | \n",
+ " 2025-06-25 17:30:31.000 UTC | \n",
+ " Rust | \n",
+ " 57617 | \n",
+ " 2850 | \n",
+ " False | \n",
+ " 45 | \n",
+ " True | \n",
+ " Node Operations & DevOps | \n",
+ " 2025-06-29T13:02:13.945394 | \n",
+ " The Fuel client is a Rust implementation desig... | \n",
+ " SUCCESS | \n",
+ " Node Operations & DevOps | \n",
+ "
\n",
+ " \n",
+ " | 7047 | \n",
+ " XK2KsRrMXU8N9WUAXb0V+X2pZWgx9H2UCtaJ6IONUC4= | \n",
+ " fuellabs | \n",
+ " sway | \n",
+ " 2021-01-19 20:54:33.000 UTC | \n",
+ " 2025-06-25 15:39:40.000 UTC | \n",
+ " Rust | \n",
+ " 62224 | \n",
+ " 5405 | \n",
+ " False | \n",
+ " 29 | \n",
+ " True | \n",
+ " Smart‑Contract Languages & Compilers | \n",
+ " 2025-06-29T13:02:11.752858 | \n",
+ " Sway is a programming language designed for th... | \n",
+ " SUCCESS | \n",
+ " Smart‑Contract Languages & Compilers | \n",
+ "
\n",
+ " \n",
+ " | 7048 | \n",
+ " ACDSfw399At2CyBKEzgNCwOZ3zvC990eWZjGw+Z8isA= | \n",
+ " base-org | \n",
+ " node | \n",
+ " 2023-02-01 13:55:02.000 UTC | \n",
+ " 2025-02-10 01:22:12.000 UTC | \n",
+ " Shell | \n",
+ " 68568 | \n",
+ " 2635 | \n",
+ " False | \n",
+ " 0 | \n",
+ " True | \n",
+ " Node Operations & DevOps | \n",
+ " 2025-06-29T13:02:09.811785 | \n",
+ " The Base Node project provides Docker configur... | \n",
+ " SUCCESS | \n",
+ " Node Operations & DevOps | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
7049 rows × 16 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " repo_artifact_id repo_artifact_namespace \\\n",
+ "0 V52vAnlOFdRUfRIo8faESeAAwQDFIaOaQtBBCBw6a5Y= zypher-game \n",
+ "1 oEFKnNgSqEV+JQFLApgDkArvoXqpYJkPmIcoePwkKAc= zklinkprotocol \n",
+ "2 9ShJYJxtK0uLqvR89mweTLTrIFwDmKmovC3LpAU73Es= zkblind \n",
+ "3 GVAT0dh82iHu/5NvZXbKkrn/f2FBx5PBFgof38zKYIU= zerolend \n",
+ "4 983Z1VR9Jhb1ODQtDG1jr6tg8XDiTkb5eLroTzj2SBg= zeriontech \n",
+ "... ... ... \n",
+ "7044 AcuAtRmOCfY1rQN0rAx8iP5pdbgveBahZYSWK2leQq4= fuellabs \n",
+ "7045 JfvNeHojsqThZKXGfbrSSW4JIf2db88eIku67txzj9w= ethereum \n",
+ "7046 imBvQgAogfFYL0+hque3sUxe+dN53nsDQFoz1q1jgDA= fuellabs \n",
+ "7047 XK2KsRrMXU8N9WUAXb0V+X2pZWgx9H2UCtaJ6IONUC4= fuellabs \n",
+ "7048 ACDSfw399At2CyBKEzgNCwOZ3zvC990eWZjGw+Z8isA= base-org \n",
+ "\n",
+ " repo_artifact_name created_at \\\n",
+ "0 uzkge 2023-12-29 01:28:42.000 UTC \n",
+ "1 zklink-docs-gitbook 2023-06-15 09:30:45.000 UTC \n",
+ "2 zkblindnextjs 2023-04-23 09:20:16.000 UTC \n",
+ "3 docs.zerolend.xyz 2023-07-16 19:46:10.000 UTC \n",
+ "4 wallet-core-ios 2022-04-21 11:01:08.000 UTC \n",
+ "... ... ... \n",
+ "7044 fuels-rs 2021-10-31 22:33:54.000 UTC \n",
+ "7045 go-ethereum 2013-12-26 13:05:46.000 UTC \n",
+ "7046 fuel-core 2020-08-27 21:12:14.000 UTC \n",
+ "7047 sway 2021-01-19 20:54:33.000 UTC \n",
+ "7048 node 2023-02-01 13:55:02.000 UTC \n",
+ "\n",
+ " updated_at language star_count fork_count is_fork \\\n",
+ "0 2025-02-13 23:01:42.000 UTC Rust 10 5 False \n",
+ "1 2025-04-01 04:49:42.000 UTC 10 3 False \n",
+ "2 2024-10-20 18:05:28.000 UTC Circom 10 2 False \n",
+ "3 2025-04-08 10:30:18.000 UTC 10 6 False \n",
+ "4 2025-01-10 12:41:20.000 UTC Swift 10 2 False \n",
+ "... ... ... ... ... ... \n",
+ "7044 2025-06-25 10:19:58.000 UTC Rust 43711 1356 False \n",
+ "7045 2025-06-25 14:38:46.000 UTC Go 49198 20940 False \n",
+ "7046 2025-06-25 17:30:31.000 UTC Rust 57617 2850 False \n",
+ "7047 2025-06-25 15:39:40.000 UTC Rust 62224 5405 False \n",
+ "7048 2025-02-10 01:22:12.000 UTC Shell 68568 2635 False \n",
+ "\n",
+ " num_packages_in_deps_dev is_actively_maintained \\\n",
+ "0 6 True \n",
+ "1 0 True \n",
+ "2 0 True \n",
+ "3 0 True \n",
+ "4 0 True \n",
+ "... ... ... \n",
+ "7044 13 True \n",
+ "7045 2 True \n",
+ "7046 45 True \n",
+ "7047 29 True \n",
+ "7048 0 True \n",
+ "\n",
+ " final_recommendation processing_timestamp \\\n",
+ "0 Gaming & Metaverse Applications 2025-06-29T17:38:19.154152 \n",
+ "1 Scaling & Layer‑2 Frameworks 2025-06-29T17:38:16.295766 \n",
+ "2 Identity & Credentials 2025-06-29T17:38:13.661183 \n",
+ "3 DeFi Protocols & Financial Primitives 2025-06-29T17:38:11.132290 \n",
+ "4 Wallets & Account Abstraction 2025-06-29T17:38:08.757093 \n",
+ "... ... ... \n",
+ "7044 Development Frameworks & Tooling 2025-06-29T13:02:17.913939 \n",
+ "7045 Execution Clients & Core Protocol 2025-06-29T13:02:16.065323 \n",
+ "7046 Node Operations & DevOps 2025-06-29T13:02:13.945394 \n",
+ "7047 Smart‑Contract Languages & Compilers 2025-06-29T13:02:11.752858 \n",
+ "7048 Node Operations & DevOps 2025-06-29T13:02:09.811785 \n",
+ "\n",
+ " summary readme_status \\\n",
+ "0 uzkge is a universal zero-knowledge game engin... SUCCESS \n",
+ "1 zkLink X provides an aggregated rollup infrast... SUCCESS \n",
+ "2 zkBind authenticates a user's employment at a ... SUCCESS \n",
+ "3 ZeroLend is a multi-chain, non-custodial lendi... SUCCESS \n",
+ "4 Zerion Wallet Core provides wallet functionali... SUCCESS \n",
+ "... ... ... \n",
+ "7044 The fuels-rs project is a Rust SDK for the Fue... SUCCESS \n",
+ "7045 Go Ethereum (geth) is a Golang implementation ... SUCCESS \n",
+ "7046 The Fuel client is a Rust implementation desig... SUCCESS \n",
+ "7047 Sway is a programming language designed for th... SUCCESS \n",
+ "7048 The Base Node project provides Docker configur... SUCCESS \n",
+ "\n",
+ " technical_reviewer \n",
+ "0 Gaming & Metaverse Applications \n",
+ "1 Scaling & Layer‑2 Frameworks \n",
+ "2 Identity & Credentials \n",
+ "3 DeFi Protocols & Financial Primitives \n",
+ "4 Wallets & Account Abstraction \n",
+ "... ... \n",
+ "7044 Development Frameworks & Tooling \n",
+ "7045 Execution Clients & Core Protocol \n",
+ "7046 Node Operations & DevOps \n",
+ "7047 Smart‑Contract Languages & Compilers \n",
+ "7048 Node Operations & DevOps \n",
+ "\n",
+ "[7049 rows x 16 columns]"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.read_parquet('output_v2/ethereum_repos_unified.parquet')\n",
+ "df[\"categorizations_list\"] = df[\"categorizations_json\"].apply(json.loads)\n",
+ "\n",
+ "def persona_to_category_map(cats_list):\n",
+ " return { d[\"persona_name\"]: d[\"category\"] for d in cats_list }\n",
+ "df_persona_map = df[\"categorizations_list\"].apply(persona_to_category_map)\n",
+ "df_persona_cols = pd.json_normalize(df_persona_map)\n",
+ "\n",
+ "df = df.join(df_persona_cols)\n",
+ "df = df.drop(columns=[\"categorizations_list\", \"categorizations_json\", \"readme_md\"])\n",
+ "df.to_parquet('results/ethereum_repo_categories_v2.parquet')\n",
+ "df"
+ ]
}
],
"metadata": {
@@ -523,7 +841,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.7"
+ "version": "3.11.5"
}
},
"nbformat": 4,
diff --git a/experiments/ethereum-repo-clusters/README.md b/experiments/ethereum-repo-clusters/README.md
index 5f5db141..c5e87dc4 100644
--- a/experiments/ethereum-repo-clusters/README.md
+++ b/experiments/ethereum-repo-clusters/README.md
@@ -1,71 +1,65 @@
# Ethereum Repo Clusters
-A Python package for automatically clustering Ethereum development tools and libraries based on their README content using AI-driven analysis and multiple personas.
+A Python module for categorizing Ethereum repositories using AI-based analysis.
## Overview
This project implements a pipeline to:
1. Fetch repository data from the OSO (Open Source Observer) database.
2. Retrieve corresponding README files from GitHub.
-3. Generate concise project summaries using Google's Gemini AI.
-4. Employ multiple configurable AI personas to categorize each project based on its summary and metadata.
-5. Consolidate these categorizations, using a star-count weighted approach for projects with multiple repositories, to produce a final recommended category.
+3. Generate concise project summaries using Gemini AI.
+4. Employ multiple configurable AI personas to categorize each project based on its full README content, summary, and metadata.
+5. Consolidate categorizations and produce a final recommended category.
The entire process is managed via a Command Line Interface (CLI).
## Features
-- Fetches comprehensive repository data via OSO, including fork status and activity tracking.
+- Quickly fetches comprehensive repository metadata via OSO.
- Retrieves and processes README.md files from GitHub with robust error handling.
-- Utilizes Google's Gemini AI for intelligent summary generation.
-- Employs a multi-persona approach for nuanced project categorization.
+- Utilizes Gemini AI for intelligent summary generation.
- Supports an arbitrary number of configurable AI personas.
-- Calculates final project recommendations using star-count weighted consolidation.
-- Offers both modular pipeline and unified processing approaches.
- Provides detailed tracking of repository status (active/inactive, fork/non-fork).
- Handles empty or error READMEs gracefully with "UNCATEGORIZED" status.
-- Includes timestamps for all categorization operations.
- Test mode for quick runs on a subset of data.
-- Outputs data at various stages in Parquet and CSV formats (with README text removed from CSV for readability).
+- Outputs data at various stages in Parquet and CSV formats.
- Supports easy resumption of processing and addition of new repositories.
- Features comprehensive progress bars at multiple levels for better visibility into processing status.
-- **Checkpoint System**: Automatically saves progress after each step, allowing for seamless recovery from interruptions.
-- **Incremental Saving**: Saves results after processing each repository, ensuring no work is lost if the process is interrupted.
-- **Resume Capability**: Automatically detects partially processed repositories and continues from where it left off.
+- Automatically saves progress after each step, allowing for seamless recovery from interruptions and incremental processing.
## Prerequisites
- Python 3.10+
-- Access to OSO, GitHub, and Google Gemini APIs.
+- Poetry (for dependency management)
+- Access to OSO, GitHub, and Gemini APIs.
## Installation
1. **Clone the repository:**
```bash
- git clone
+ git clone https://github.com/ethereum/ethereum-repo-clusters.git
cd ethereum-repo-clusters
```
-2. **Set up a virtual environment (recommended):**
+2. **Install Poetry (if not already installed):**
```bash
- python -m venv venv
- source venv/bin/activate # On Windows use `venv\Scripts\activate`
+ curl -sSL https://install.python-poetry.org | python3 -
```
-3. **Install dependencies:**
+3. **Install dependencies and activate the virtual environment:**
```bash
- pip install -r requirements.txt
+ poetry install
+ poetry env activate
```
+ This will:
+ - Create a virtual environment automatically
+ - Install all dependencies from `pyproject.toml`
+ - Activate the virtual environment
-4. **Install the package in editable mode (optional, for development):**
- ```bash
- pip install -e .
- ```
-
-5. **Create a `.env` file** in the project root directory (`ethereum-repo-clusters/`) and add your API keys:
+4. **Create a `.env` file** in the project root directory (`ethereum-repo-clusters/`) and add your API keys:
```env
OSO_API_KEY="your_oso_api_key"
- GITHUB_TOKEN="your_github_token" # A GitHub Personal Access Token with repo access
+ GITHUB_TOKEN="your_github_personal_access_token"
GEMINI_API_KEY="your_gemini_api_key"
```
These keys are loaded via `ethereum-repo-clusters/config/settings.py`.
@@ -91,7 +85,7 @@ The project uses a combination of a JSON configuration file and Python modules f
- Edit this file to update the categorization taxonomy.
- **Prompt Templates (`ethereum-repo-clusters/config/prompts/summary_prompts.py`):**
- - Contains `SUMMARY_PROMPT` (for generating project summaries) and `TAGS_PROMPT` (for an auxiliary tag generation, currently not central to categorization).
+ - Contains `SUMMARY_PROMPT` (for generating project summaries).
- These are used by the `AIService`.
- **Core Settings (`ethereum-repo-clusters/config/settings.py`):**
@@ -100,10 +94,15 @@ The project uses a combination of a JSON configuration file and Python modules f
## Usage (CLI)
-The project is operated via the command line using `python -m ethereum-repo-clusters`.
+The project is operated via the command line. **Poetry is recommended** for managing the virtual environment and dependencies.
**General Command Structure:**
```bash
+# With Poetry (recommended)
+poetry run python -m ethereum-repo-clusters [GLOBAL_OPTIONS] COMMAND [COMMAND_OPTIONS]
+
+# Or activate Poetry shell first, then run directly
+poetry shell
python -m ethereum-repo-clusters [GLOBAL_OPTIONS] COMMAND [COMMAND_OPTIONS]
```
@@ -114,79 +113,57 @@ python -m ethereum-repo-clusters [GLOBAL_OPTIONS] COMMAND [COMMAND_OPTIONS]
- **`fetch_repos`**: Fetches repository data from OSO and READMEs from GitHub.
```bash
- python -m ethereum-repo-clusters fetch_repos
+ poetry run python -m ethereum-repo-clusters fetch_repos
```
- `--force-refresh`: Wipes existing raw repository data and re-fetches.
- `--fetch-new-only`: Only fetches repositories that don't exist in current data.
- **`generate_summaries`**: Generates AI summaries for fetched repositories.
```bash
- python -m ethereum-repo-clusters generate_summaries
+ poetry run python -m ethereum-repo-clusters generate_summaries
```
- `--force-refresh`: Wipes existing summaries and regenerates them.
- `--new-only`: Only generates summaries for repositories that don't have summaries yet.
- **`categorize`**: Categorizes projects using all defined AI personas.
```bash
- python -m ethereum-repo-clusters categorize
+ poetry run python -m ethereum-repo-clusters categorize
```
- `--force-refresh`: Wipes existing categorizations and re-runs.
- `--persona `: Processes only the specified persona. Can be combined with `--force-refresh`. Example:
```bash
- python -m ethereum-repo-clusters categorize --persona keyword_spotter --force-refresh
+ poetry run python -m ethereum-repo-clusters categorize --persona technical_reviewer --force-refresh
```
- `--new-only`: Only categorizes repositories that don't have categories yet.
- **`consolidate`**: Consolidates categorizations from all personas and generates final project recommendations.
```bash
- python -m ethereum-repo-clusters consolidate
+ poetry run python -m ethereum-repo-clusters consolidate
```
*(This step does not typically require a force-refresh as it always processes the latest categorized data.)*
+- **`run_all`**: Runs the complete pipeline from start to finish.
+ ```bash
+ poetry run python -m ethereum-repo-clusters run_all
+ ```
+ - `--force-refresh-all`: Wipes all existing data and re-runs the entire pipeline.
+ - `--use-unified`: Uses the unified processor approach (recommended).
+
**Persona Management (Informational):**
The CLI includes commands related to personas, but due to refactoring, persona definitions are now managed directly in `ethereum-repo-clusters/config/prompts/personas.py`. These CLI commands are informational:
-- `python -m ethereum-repo-clusters personas list`: Lists personas currently defined in `personas.py`.
-- `python -m ethereum-repo-clusters personas add ...`: Provides instructions on how to add a persona by editing `personas.py`.
-- `python -m ethereum-repo-clusters personas remove `: Provides instructions on how to remove a persona by editing `personas.py`.
+- `poetry run python -m ethereum-repo-clusters personas list`: Lists personas currently defined in `personas.py`.
+- `poetry run python -m ethereum-repo-clusters personas add ...`: Provides instructions on how to add a persona by editing `personas.py`.
+- `poetry run python -m ethereum-repo-clusters personas remove `: Provides instructions on how to remove a persona by editing `personas.py`.
**Example Full Run in Test Mode with Full Refresh:**
```bash
-# Legacy pipeline approach
-python -m ethereum-repo-clusters --test-mode run_all --force-refresh-all
-
-# New unified processor approach (recommended)
-python -m ethereum-repo-clusters --test-mode run_all --force-refresh-all --use-unified
+poetry run python -m ethereum-repo-clusters --test-mode run_all --force-refresh-all --use-unified
```
## Workflow
-### Legacy Pipeline (Step-by-Step)
-
-1. **Fetch Data (`fetch_repos`):**
- - Repository metadata is fetched from OSO.
- - README.md content is fetched from GitHub for these repositories.
- - Output: `output/devtooling_raw.parquet`
-
-2. **Generate Summaries (`generate_summaries`):**
- - READMEs are processed by Gemini AI to create concise summaries.
- - Output: `output/devtooling_summarized.parquet`
-
-3. **Categorize by Persona (`categorize`):**
- - Each project summary (with metadata) is evaluated by every defined AI persona.
- - Each persona assigns a category based on its specific prompt and the global category list.
- - Output: Individual Parquet files per persona in `output/categorized/` (e.g., `output/categorized/keyword_spotter.parquet`).
-
-4. **Consolidate Recommendations (`consolidate`):**
- - Categorizations from all personas are merged.
- - For each project:
- - If it's a single-repository project, the recommendation is based on a star-weighted aggregation of persona assignments for that repo.
- - If it's a multi-repository project, the recommendation is determined by a star-count weighted aggregation of all persona assignments across all its repositories. The category with the highest total star weight wins.
- - Output: `output/devtooling_full.parquet` and `output/devtooling_consolidated.csv`.
-
-### New Unified Processor (Recommended)
-
-The new unified processor combines all steps into a single efficient pipeline:
+The unified processor combines all steps into a single efficient pipeline:
1. **Process Repositories (`process_unified`):**
- Repository metadata is fetched from OSO, including fork status and activity tracking.
@@ -217,186 +194,17 @@ The unified processor offers several advantages:
All output data is stored in the directory specified by `output_dir` in `pipeline_config.json` (default is `output/`).
-### Legacy Pipeline Output
-
-- **`devtooling_raw.parquet`**: Raw data fetched from OSO, augmented with GitHub README content.
-- **`devtooling_summarized.parquet`**: Repositories with their AI-generated summaries.
-- **`categorized/.parquet`**: Dataframe for each persona, containing the original summary data plus that persona's assigned category and reason.
-- **`devtooling_full.parquet`**: The final consolidated dataset, with one row per project, including the overall recommendation, total stars, repo count, sample summary, and individual persona category modes.
-- **`devtooling_consolidated.csv`**: A CSV version of the final consolidated data for easier viewing.
-
### Unified Processor Output
-- **`ethereum_repos_unified.parquet`**: Comprehensive dataset containing all repositories with their metadata, summaries, and categorizations in a single structure.
-- **`ethereum_repos_unified.csv`**: A CSV version of the unified data for easier viewing, with README text removed and long text fields truncated for readability.
-- **`processing_checkpoint.json`**: Checkpoint file that tracks processing progress, allowing for seamless recovery from interruptions.
-
-### Unified Data Structure
-
-The unified processor creates a comprehensive data structure with the following key fields:
-
-```json
-{
- "repo_artifact_id": "...",
- "project_id": "...",
- "repo_artifact_namespace": "...",
- "repo_artifact_name": "...",
- "is_fork": true/false,
- "is_actively_maintained": true/false,
- "last_updated": "2024-12-01",
- "star_count": 100,
- "readme_status": "SUCCESS/EMPTY/ERROR",
- "summary": "...",
- "categorizations": [
- {
- "persona_name": "keyword_spotter",
- "category": "Developer Tools",
- "reason": "Contains keywords like 'CLI', 'build tool'...",
- "timestamp": "2025-01-05T09:15:00Z"
- },
- {
- "persona_name": "senior_strategist",
- "category": "Infrastructure",
- "reason": "Mature project with strong adoption...",
- "timestamp": "2025-01-05T09:15:01Z"
- },
- {
- "persona_name": "workflow_wizard",
- "category": "Developer Tools",
- "reason": "Streamlines development workflow...",
- "timestamp": "2025-01-05T09:15:02Z"
- }
- ],
- "final_recommendation": "Developer Tools",
- "processing_timestamp": "2025-01-05T09:15:02Z"
-}
-```
+- **`ethereum_repos_unified.parquet`**: Complete dataset with all repository metadata, README content, summaries, persona categorizations, and final recommendations.
+- **`ethereum_repos_unified.csv`**: CSV version of the unified dataset with README text removed for improved readability.
-This structure makes it easy to:
-- Track which repositories have been processed
-- Identify repositories with errors or empty READMEs
-- See the categorization from each persona with timestamps
-- Filter repositories by fork status or activity
-- Resume processing from where you left off
-
-## Development Notes
-- The project uses `tqdm` for progress bars during long operations, with detailed progress tracking at multiple levels:
- - Overall batch processing
- - Repository processing within each batch
- - README fetching for each repository
- - Categorization with each persona
-- `DataManager` class in `ethereum-repo-clusters/pipeline/data_manager.py` handles all data persistence (reading/writing Parquet files).
-- `AIService` in `ethereum-repo-clusters/processing/ai_service.py` abstracts interactions with the Gemini API.
-- `UnifiedProcessor` in `ethereum-repo-clusters/pipeline/unified_processor.py` provides the new streamlined processing approach.
-- The CLI in `ethereum-repo-clusters/cli/main_cli.py` supports both legacy and unified processing approaches.
-- Output files are saved to the local `output/` directory in the current repository.
-
-## New CLI Commands
-
-### Unified Processing
+### Step-by-Step Pipeline Output (Alternative)
-```bash
-# Process repositories with the unified processor
-python -m ethereum-repo-clusters process_unified [OPTIONS]
-
-# Options:
-# --force-refresh Force refresh all data, ignoring existing.
-# --include-forks Include forked repositories in processing.
-# --include-inactive Include repositories not updated in the last year.
-# --limit INTEGER Limit the number of repositories to process.
-```
-
-### Run All with Unified Processor
-
-```bash
-# Run the entire pipeline using the unified processor
-python -m ethereum-repo-clusters run_all --use-unified [OPTIONS]
+If using the step-by-step approach instead of the unified processor:
-# Additional options with --use-unified:
-# --include-forks Include forked repositories in processing.
-# --include-inactive Include repositories not updated in the last year.
-```
-
-## Adding New Repositories
-
-To add new repositories to the analysis:
-
-1. The unified processor automatically detects which repositories have already been processed.
-2. New repositories from OSO will be processed automatically on the next run.
-3. To add repositories manually, you can:
- - Update the OSO query in `fetcher.py` to include additional repositories.
- - Create a custom script that adds repositories to the unified data structure.
-
-## Error Handling
-
-The unified processor handles errors gracefully:
-
-- Empty READMEs: Marked with `readme_status="EMPTY"` and categorized as "UNCATEGORIZED".
-- Error fetching README: Marked with `readme_status="ERROR"` and categorized as "UNCATEGORIZED".
-- API errors during categorization: The specific persona's categorization is marked as "UNCATEGORIZED" with the error reason.
-
-This approach ensures that all repositories are included in the final output, even if they couldn't be fully processed.
-
-## Checkpoint System
-
-The unified processor now includes a robust checkpoint system that makes it resilient to interruptions:
-
-### How It Works
-
-1. **Incremental Saving**: Results are saved after processing each repository, not just at the end.
-2. **Checkpoint File**: A JSON file (`output/processing_checkpoint.json`) tracks:
- - Which repositories have been fully processed
- - Which repositories are partially processed and their current state
- - The last repository that was successfully processed
-
-3. **Granular Progress Tracking**: The checkpoint tracks progress at multiple levels:
- - README fetching status
- - Summary generation status
- - Which personas have completed categorization
-
-4. **Resume Logic**: When restarted after an interruption, the processor:
- - Skips repositories that have been fully processed
- - Continues from where it left off for partially processed repositories
- - Preserves all work that was completed before the interruption
-
-5. **Space Optimization**: Once a repository is fully processed, its partial results are removed from the checkpoint file to save space.
-
-### Benefits
-
-- **No Lost Work**: Even if interrupted during a long-running process, no work is lost.
-- **API Efficiency**: Avoids redundant API calls to GitHub and Gemini, saving rate limits and costs.
-- **Time Savings**: Picks up exactly where it left off, avoiding redundant processing.
-- **Resilience**: Handles network issues, API timeouts, and other temporary failures gracefully.
-
-### Example Checkpoint Structure
-
-```json
-{
- "last_processed_repo_id": "ethereum/solidity",
- "processed_repos": ["openzeppelin/openzeppelin-contracts", "ethereum/solidity"],
- "partial_results": {
- "ipfs/kubo": {
- "readme_fetched": true,
- "readme_status": "SUCCESS",
- "summary_generated": true,
- "personas_completed": ["protocol_architect", "ecosystem_analyst"],
- "categorizations": [
- {
- "persona_name": "protocol_architect",
- "category": "Infrastructure & Node Operations",
- "reason": "...",
- "timestamp": "2025-06-05T13:53:30.903574"
- },
- {
- "persona_name": "ecosystem_analyst",
- "category": "Infrastructure & Node Operations",
- "reason": "...",
- "timestamp": "2025-06-05T13:53:32.238039"
- }
- ]
- }
- }
-}
-```
-
-This checkpoint system ensures that the processing pipeline is robust and can handle interruptions gracefully, making it suitable for processing large numbers of repositories over extended periods.
+- **`devtooling_raw.parquet`**: Raw data fetched from OSO, augmented with GitHub README content.
+- **`devtooling_summarized.parquet`**: Repositories with their AI-generated summaries.
+- **`categorized/.parquet`**: Dataframe for each persona, containing the original summary data plus that persona's assigned category and reason.
+- **`devtooling_full.parquet`**: The final consolidated dataset, with one row per project, including the overall recommendation, total stars, repo count, sample summary, and individual persona category modes.
+- **`devtooling_consolidated.csv`**: CSV version of the final consolidated dataset.
\ No newline at end of file
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/config_manager.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/config_manager.py
index a9fb5bb1..17ee987d 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/config_manager.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/config_manager.py
@@ -2,7 +2,7 @@
from pathlib import Path
from typing import List, Dict, Any
from .settings import PROJECT_ROOT, GEMINI_API_KEY, OSO_API_KEY, GITHUB_TOKEN, GEMINI_MODEL, OUTPUT_DIR
-from .prompts.summary_prompts import SUMMARY_PROMPT, TAGS_PROMPT
+from .prompts.summary_prompts import SUMMARY_PROMPT
@@ -44,7 +44,6 @@ def _get_default_config(self) -> Dict[str, Any]:
"output_dir": str(OUTPUT_DIR),
"gemini_model": GEMINI_MODEL,
"summary_prompt_template": SUMMARY_PROMPT,
- "tags_prompt_template": TAGS_PROMPT,
"test_mode": False,
"test_mode_limit": 5,
"batch_size_summaries": 50,
@@ -108,6 +107,9 @@ def get_batch_size_summaries(self) -> int:
def get_batch_size_categorization(self) -> int:
return self.get("batch_size_categorization", 10)
+ def get_min_stars(self) -> int:
+ return self.get("min_stars", 0)
+
def get_categories(self) -> List[Dict[str, str]]:
"""Gets the categories directly from the categories.py module."""
from .prompts.categories import CATEGORIES
@@ -121,9 +123,6 @@ def get_category_names(self) -> List[str]:
def get_summary_prompt_template(self) -> str:
return self.get("summary_prompt_template", "")
- def get_tags_prompt_template(self) -> str:
- return self.get("tags_prompt_template", "")
-
if __name__ == "__main__":
# Example usage:
config_manager = ConfigManager()
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/__init__.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/__init__.py
index c22d1787..b3ae9942 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/__init__.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/__init__.py
@@ -1,11 +1,10 @@
from .categories import CATEGORIES, CATEGORY_NAMES
from .personas import PERSONAS
-from .summary_prompts import SUMMARY_PROMPT, TAGS_PROMPT
+from .summary_prompts import SUMMARY_PROMPT
__all__ = [
'CATEGORIES',
'CATEGORY_NAMES',
'PERSONAS',
'SUMMARY_PROMPT',
- 'TAGS_PROMPT',
]
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/categories.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/categories.py
index bd201d31..df7e9767 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/categories.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/categories.py
@@ -1,207 +1,83 @@
CATEGORIES = [
- # DeFi Application Categories
{
- "category": "Lending & Borrowing Protocols",
- "description": (
- "Lending & Borrowing Protocols include implementations and SDKs for collateralized lending markets, "
- "flash loans, interest rate models, and liquidation mechanisms. These tools handle asset management, "
- "risk scoring, and pool accounting, enabling users to lend or borrow assets in a trust-minimized way."
- )
+ "category": "Execution Clients & Core Protocol",
+ "description": "Implementations of the Ethereum execution layer (e.g., Geth, Nethermind) plus low‑level consensus or EVM research repos. Anything that validates blocks or directly extends the core protocol logic belongs here."
},
{
- "category": "Decentralized Exchanges (DEXs)",
- "description": (
- "DEXs power peer-to-peer asset swaps and liquidity provision. This includes AMM (automated market maker) "
- "frameworks, order book DEXes, routers, aggregators, and liquidity management libraries. They also often "
- "support advanced trading mechanisms like TWAPs, limit orders, and MEV protection."
- )
+ "category": "Scaling & Layer‑2 Frameworks",
+ "description": "Rollup SDKs, optimistic & zk proof systems, shared sequencers, data‑availability layers, and tooling that lets teams spin up or operate an L2 or sidechain."
},
{
- "category": "Derivatives & Synthetic Assets",
- "description": (
- "Derivatives & Synthetic Assets frameworks implement perpetual futures, options, and collateralized synthetic "
- "asset systems. These toolkits involve complex pricing oracles, risk engines, margin systems, and settlement layers."
- )
+ "category": "Interoperability & Bridges",
+ "description": "Cross‑chain bridges, messaging buses, generalized state‑proof frameworks, and liquidity routers focused on moving assets or data between networks."
},
{
- "category": "Stablecoin Infrastructure",
- "description": (
- "Stablecoin Infrastructure includes minting contracts, collateralization engines, algorithmic stabilization mechanisms, "
- "and off-chain attestation integrations. It also encompasses tools for analyzing backing ratios and peg health."
- )
+ "category": "Cryptography & Zero‑Knowledge Primitives",
+ "description": "Reusable cryptographic libraries—hash functions, elliptic‑curve math, SNARK/STARK circuits, proof systems, and related tooling not tied to a single application."
},
{
- "category": "Oracles & Price Feeds",
- "description": (
- "Oracles & Price Feeds provide real-world and cross-chain data into smart contracts. This category covers push-based oracles, "
- "pull-based on-demand queries, cryptoeconomic staking oracles, and off-chain data relayers."
- )
+ "category": "Oracle Networks & Data Feeds",
+ "description": "Push or pull‑based oracle contracts, off‑chain reporters, commit‑reveal schemes, and services that bring real‑world or cross‑chain data onchain."
},
{
- "category": "Vaults, Yield Strategies & Aggregators",
- "description": (
- "These tools optimize capital across yield-bearing protocols. They include yield routers, auto-compounding vaults, and rebalancers, "
- "as well as SDKs to model risk-return profiles and dynamically allocate capital across farms and lending markets."
- )
+ "category": "Smart‑Contract Languages & Compilers",
+ "description": "Compilers, interpreters, transpilers, language servers, and DSLs that translate high‑level code (Solidity, Vyper, Huff, etc.) into EVM bytecode."
},
{
- "category": "Asset Management & Portfolio Tooling",
- "description": (
- "Asset Management tooling includes interfaces and libraries for building rebalancing strategies, vault-based funds, on-chain ETFs, "
- "and automated index trackers. They often incorporate fee structures, role-based access, and compliance checks."
- )
+ "category": "Development Frameworks & Tooling",
+ "description": "Opinionated toolchains (Hardhat, Foundry, Brownie, DappTools) that scaffold, test, and deploy contracts, including plugin ecosystems and CLIs."
},
{
- "category": "DeFi Security & Monitoring",
- "description": (
- "Security tools for DeFi include real-time exploit detectors, anomaly detection systems, pause mechanisms, multisig enforcers, "
- "and post-mortem forensic tools. Monitoring dashboards and alerting frameworks fall here as well."
- )
+ "category": "Testing & Formal Verification",
+ "description": "Unit‑test harnesses, fuzzers, static analyzers, symbolic execution engines, and formal verification suites that surface correctness or security issues pre‑deployment."
},
{
- "category": "Governance & DAO Tooling",
- "description": (
- "Governance & DAO Tooling enables on-chain proposal management, token-weighted voting, off-chain signaling, execution queues, "
- "and guardrails for DeFi governance systems. Includes snapshot integration, timelocks, and delegate management interfaces."
- )
+ "category": "Deployment & Upgrade Management",
+ "description": "Libraries and services that automate contract deployment, versioning, proxy patterns, CREATE2 determinism, and governance‑controlled upgrades."
},
{
- "category": "Liquidity Bootstrapping & Token Distribution",
- "description": (
- "This includes tools for liquidity mining, airdrops, vesting contracts, bonding curves, and initial token offerings. "
- "They facilitate community-led distribution, price discovery, and progressive decentralization of DeFi protocols."
- )
+ "category": "Node Operations & DevOps",
+ "description": "Scripts, dashboards, container images, and orchestration tools for running or monitoring full nodes, validators, archival nodes, or RPC endpoints."
},
{
- "category": "DeFi Analytics & Dashboards",
- "description": (
- "These are SDKs, APIs, and frontends for aggregating on-chain DeFi metrics—TVL, yield, volume, and user activity. "
- "Includes data pipelines, Dune-compatible libraries, subgraphs, and event-based ETL infrastructure tailored to DeFi."
- )
+ "category": "Data Indexing & Analytics",
+ "description": "Subgraph definitions, ETL pipelines, time‑series databases, and API servers that structure onchain data for querying, dashboards, or research."
},
{
- "category": "Cross-chain DeFi Infrastructure",
- "description": (
- "These tools support multi-chain liquidity routing, cross-chain yield farming, state relays, and synthetic asset issuance. "
- "They abstract away bridging mechanics, offering seamless user and liquidity migration across ecosystems."
- )
+ "category": "Wallets & Account Abstraction",
+ "description": "Key‑management libraries, signature middlewares (EIP‑4337), wallet SDKs, browser extensions, mobile wallets, and transaction‑building helpers."
},
{
- "category": "User Interface & Integration SDKs",
- "description": (
- "SDKs and frontend libraries for integrating DeFi functionality into wallets, dApps, and aggregators. Includes trade UIs, "
- "Zap interfaces, gas estimators, and batch transaction helpers to improve DeFi UX."
- )
+ "category": "Identity & Credentials",
+ "description": "ENS, decentralized identity, verifiable‑credential frameworks, reputation scores, soul‑bound token standards, and onchain attestations."
},
{
- "category": "Simulation & Risk Modeling",
- "description": (
- "Tools that simulate user positions, economic incentives, or protocol upgrades. They model protocol resilience, agent behavior, "
- "market shocks, and contagion scenarios, often using agent-based or Monte Carlo methods for risk-aware design."
- )
+ "category": "DAO & Governance Systems",
+ "description": "Token‐weighted voting modules, off‑chain signaling, delegate dashboards, execution timelocks, proposal simulators, and treasury management tooling."
},
-
- # Developer Tool Categories
- {
- "category": "Language & Compilation Tools",
- "description": (
- "Language & Compilation Tools include compilers, interpreters, language servers, "
- "and syntax utilities for smart-contract development. They translate high-level "
- "source code into EVM bytecode, perform static analysis, and enable features like "
- "symbolic execution, forming the foundation for all higher-level tooling."
- )
- },
- {
- "category": "Core Protocol Interfaces",
- "description": (
- "Core Protocol Interfaces are libraries and SDKs that provide reusable building blocks "
- "for blockchain developers—smart contract libraries, JSON-RPC clients, transaction builders, "
- "wallet and key management, authorization, signature handling, and ABI encoding/decoding. "
- "They can power the core operations of many dApps and services."
- )
- },
- {
- "category": "Development Frameworks",
- "description": (
- "Development Frameworks are opinionated, end-to-end toolchains that scaffold, build, "
- "test, and deploy smart-contract projects. They bundle CLIs, IDE integrations, task "
- "runners, local networks, hot-reloading, and plugin ecosystems to enforce conventions "
- "and automate workflows from project setup through to frontend integration."
- )
- },
- {
- "category": "Deployment & Lifecycle Management",
- "description": (
- "Deployment & Lifecycle Management tools handle contract deployment, upgrades, and "
- "on-chain migrations. They automate predictable CREATE2 strategies, proxy pattern "
- "management, cross-network publishes, and governance hooks, while integrating safety "
- "checks and test-suite validations to maintain contract integrity."
- )
- },
- {
- "category": "Testing & Verification Tools",
- "description": (
- "Testing & Verification Tools provide frameworks for unit testing, property-based fuzzing, "
- "symbolic execution, formal verification, and coverage analysis. They integrate vulnerability "
- "scanners, static analyzers, and coverage reporters to identify edge-case failures and ensure "
- "on-chain correctness."
- )
- },
- {
- "category": "Developer Experience Tools",
- "description": (
- "Developer Experience Tools are lightweight plugins and utilities that boost productivity "
- "and enforce code consistency. This category includes editor extensions, linters, formatters, "
- "code generators, documentation generators, and small CLI helpers."
- )
- },
- {
- "category": "Infrastructure & Node Operations",
- "description": (
- "Infrastructure & Node Operations encompass tools for running, coordinating, and scaling "
- "blockchain nodes and peer-to-peer networks. They cover RPC providers, telemetry collectors, "
- "log aggregators, gossip-based messaging layers, peer discovery and connection management, "
- "and automation scripts to ensure reliable network participation."
- )
+ {
+ "category": "DeFi Protocols & Financial Primitives",
+ "description": "Lending markets, DEXes, derivatives, yield optimizers, stablecoins, liquidity bootstrapping, onchain indices, and associated SDKs."
},
{
- "category": "Data Indexing & Analytics",
- "description": (
- "Data Indexing & Analytics tools ingest, process, and visualize on-chain data. They provide "
- "GraphQL and REST APIs over processed datasets, real-time event streaming, and libraries or "
- "dashboards for analyzing blockchain metrics."
- )
- },
- {
- "category": "Interoperability & Cross-chain",
- "description": (
- "Interoperability & Cross-chain covers bridging frameworks, cross-chain messaging protocols, "
- "and Superchain interoperability tooling. These libraries enable seamless asset transfers, "
- "state proofs, and communication across multiple networks."
- )
- },
- {
- "category": "Cryptography & Primitives",
- "description": (
- "Cryptography & Primitives includes low-level cryptographic libraries and building blocks—"
- "hash functions, signature schemes, Merkle trees, zero-knowledge proof primitives, and "
- "encryption utilities—optimized for security and performance."
- )
- },
- {
- "category": "Application-Specific & Niche Tools",
- "description": (
- "Application-Specific & Niche Tools are libraries and SDKs tailored to very narrow use cases "
- "(e.g., DeFi adapters, NFT marketplaces, governance dashboards). They serve specific projects "
- "but do not have broad applicability or reusability across the ecosystem."
- )
- },
- {
- "category": "Others",
- "description": (
- "Others is a catch-all for repositories with limited usage or insufficient information—"
- "empty projects, single-file utilities, or items that cannot be reasonably categorized."
- )
+ "category": "NFTs & Digital Asset Protocols",
+ "description": "ERC‑721/1155 implementations, metadata standards, onchain creators' platforms, marketplace contracts, royalty engines, and fractionalization tooling."
+ },
+ {
+ "category": "Gaming & Metaverse Applications",
+ "description": "Onchain game engines, asset composability layers, play‑to‑earn economies, and metaverse SDKs focused primarily on interactive entertainment."
+ },
+ {
+ "category": "Social & Consumer Applications",
+ "description": "Protocols or SDKs for social graphs, content platforms, messaging, ticketing, subscriptions, and other consumer‑oriented experiences."
+ },
+ {
+ "category": "Storage & Data Availability",
+ "description": "IPFS pinning tools, Filecoin/Arweave clients, EigenDA or Celestia adapters, and libraries that persist or serve large blobs and proofs."
+ },
+ {
+ "category": "Security Monitoring & Incident Response",
+ "description": "Real‑time threat detectors, alerting networks (e.g., Forta), exploit simulators, pause/kill switches, forensic analysis, and post‑mortem tooling."
}
]
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/personas.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/personas.py
index 209515cf..359e7cce 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/personas.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/personas.py
@@ -1,110 +1,74 @@
PERSONAS = [
{
- "name": "protocol_architect",
- "title": "Protocol & Infrastructure Architect",
+ "name": "technical_reviewer",
+ "title": "Technical Reviewer",
"description": (
- "You evaluate projects based on their technical architecture, infrastructure role, "
- "and protocol design patterns. You focus on how well the project implements DeFi primitives, "
- "contributes to ecosystem stability, and maintains technical dependencies."
+ "Your goal is to spot the primary on‑chain or off‑chain function the repo enables, "
+ "independent of business hype or UI polish."
),
"prompt": (
- "As a Protocol & Infrastructure Architect, analyze the project's technical foundations, "
- "infrastructure role, and protocol design.\n\n"
- "Summary: {summary}\n"
+ "You are a Technical Reviewer. Analyze this single repository and categorize it.\n\n"
+ "Repository Summary: {summary}\n"
+ "Primary Language: {language}\n"
"Stars: {star_count} | Forks: {fork_count}\n"
"Created: {created_at} | Updated: {updated_at}\n\n"
- "Based on the technical architecture, infrastructure contribution, and protocol design, "
- "choose one of the categories below:\n"
+ "Full README Content:\n{readme_md}\n"
+ "Available categories:\n"
"{categories}\n\n"
- "Respond in JSON:\n"
+ "CRITICAL: Respond with ONLY a single JSON object in this exact format:\n"
"{{\n"
' "assigned_tag": "category name",\n'
- ' "reason": "analysis of protocol architecture, infrastructure role, technical dependencies, and ecosystem stability"\n'
- "}}"
- ),
- },
- {
- "name": "ecosystem_analyst",
- "title": "Ecosystem Growth Analyst",
- "description": (
- "You assess projects based on their potential to grow the Ethereum DeFi ecosystem, "
- "their user adoption metrics, and their contribution to composability and innovation."
- ),
- "prompt": (
- "As an Ecosystem Growth Analyst, evaluate the project's impact on DeFi ecosystem growth.\n\n"
- "Summary: {summary}\n"
- "Stars: {star_count} | Forks: {fork_count}\n"
- "Created: {created_at} | Updated: {updated_at}\n\n"
- "Select the category that best represents its ecosystem role:\n"
- "{categories}\n\n"
- "Respond in JSON:\n"
- "{{\n"
- ' "assigned_tag": "category name",\n'
- ' "reason": "analysis of ecosystem impact, adoption potential, and composability"\n'
- "}}"
- ),
- },
- {
- "name": "security_researcher",
- "title": "Security & Risk Researcher",
- "description": (
- "You focus on security practices, risk management approaches, and the project's "
- "contribution to making DeFi safer and more resilient."
- ),
- "prompt": (
- "As a Security & Risk Researcher, assess the project's security posture and risk management.\n\n"
- "Summary: {summary}\n"
- "Stars: {star_count} | Forks: {fork_count}\n"
- "Created: {created_at} | Updated: {updated_at}\n\n"
- "Choose the category that best reflects its security and risk management approach:\n"
- "{categories}\n\n"
- "Respond in JSON:\n"
- "{{\n"
- ' "assigned_tag": "category name",\n'
- ' "reason": "analysis of security practices, risk management, and safety features"\n'
- "}}"
- ),
- },
- {
- "name": "user_experience_advocate",
- "title": "User Experience Advocate",
- "description": (
- "You evaluate projects based on their user experience, accessibility, and potential "
- "to onboard new users to DeFi. You focus on usability and integration capabilities."
- ),
- "prompt": (
- "As a User Experience Advocate, assess the project's usability and accessibility.\n\n"
- "Summary: {summary}\n"
- "Stars: {star_count} | Forks: {fork_count}\n"
- "Created: {created_at} | Updated: {updated_at}\n\n"
- "Select the category that best represents its user experience focus:\n"
- "{categories}\n\n"
- "Respond in JSON:\n"
- "{{\n"
- ' "assigned_tag": "category name",\n'
- ' "reason": "analysis of user experience, accessibility, and onboarding potential"\n'
- "}}"
- ),
+ ' "reason": "brief technical justification"\n'
+ "}}\n\n"
+ "Do not include any other text, explanations, or formatting. Do not mention batch processing or multiple projects."
+ )
},
- {
- "name": "governance_specialist",
- "title": "Governance & Decentralization Specialist",
- "description": (
- "You analyze projects based on their governance mechanisms, decentralization approach, "
- "and contribution to sustainable protocol management."
- ),
- "prompt": (
- "As a Governance & Decentralization Specialist, evaluate the project's governance model.\n\n"
- "Summary: {summary}\n"
- "Stars: {star_count} | Forks: {fork_count}\n"
- "Created: {created_at} | Updated: {updated_at}\n\n"
- "Choose the category that best reflects its governance and decentralization approach:\n"
- "{categories}\n\n"
- "Respond in JSON:\n"
- "{{\n"
- ' "assigned_tag": "category name",\n'
- ' "reason": "analysis of governance mechanisms, decentralization, and sustainability"\n'
- "}}"
- ),
- }
-]
+ # {
+ # "name": "market_strategist",
+ # "title": "Market Strategist",
+ # "description": (
+ # "You focus on who the repo serves and the problem it solves. "
+ # "You weigh adoption potential, competitive landscape, and fit within the broader Ethereum ecosystem."
+ # ),
+ # "prompt": (
+ # "You are a Market Strategist. Analyze this single repository and categorize it.\n\n"
+ # "Repository Summary: {summary}\n"
+ # "Full README Content:\n{readme_md}\n"
+ # "Primary Language: {language}\n"
+ # "Stars: {star_count} | Forks: {fork_count}\n"
+ # "Created: {created_at} | Updated: {updated_at}\n\n"
+ # "Available categories:\n"
+ # "{categories}\n\n"
+ # "CRITICAL: Respond with ONLY a single JSON object in this exact format:\n"
+ # "{{\n"
+ # ' "assigned_tag": "category name",\n'
+ # ' "reason": "brief market justification"\n'
+ # "}}\n\n"
+ # "Do not include any other text, explanations, or formatting. Do not mention batch processing or multiple projects."
+ # )
+ # },
+ # {
+ # "name": "power_user",
+ # "title": "Power User",
+ # "description": (
+ # "You represent power users and developers who rely on Ethereum being awesome. "
+ # "You gauge ease of integration, documentation quality, and day‑to‑day usefulness."
+ # ),
+ # "prompt": (
+ # "You are a Power User. Analyze this single repository and categorize it.\n\n"
+ # "Repository Summary: {summary}\n"
+ # "Full README Content:\n{readme_md}\n"
+ # "Primary Language: {language}\n"
+ # "Stars: {star_count} | Forks: {fork_count}\n"
+ # "Created: {created_at} | Updated: {updated_at}\n\n"
+ # "Available categories:\n"
+ # "{categories}\n\n"
+ # "CRITICAL: Respond with ONLY a single JSON object in this exact format:\n"
+ # "{{\n"
+ # ' "assigned_tag": "category name",\n'
+ # ' "reason": "brief user experience justification"\n'
+ # "}}\n\n"
+ # "Do not include any other text, explanations, or formatting. Do not mention batch processing or multiple projects."
+ # )
+ # }
+]
\ No newline at end of file
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/summary_prompts.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/summary_prompts.py
index cdd27bfb..b8128439 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/summary_prompts.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/config/prompts/summary_prompts.py
@@ -1,32 +1,23 @@
SUMMARY_PROMPT = (
- "You are an analyst preparing short, neutral briefs on open-source projects. "
- "Read the README below and write a **concise, 2- to 3-sentence summary** that:\n"
+ "You are an analyst producing short, neutral briefs on Ethereum‑ecosystem open‑source projects. "
+ "Read the README below and write a **concise 2‑ to 3‑sentence summary** that:\n"
"• states the project’s core purpose / problem it solves\n"
- "• lists its main capabilities or components (1–3 key points only)\n"
- "• mentions the primary intended users or systems (e.g., smart-contract developers, node operators)\n"
- "• notes any strongly signalled context such as supported programming language, network, or runtime\n"
+ "• lists its principal capabilities or components (1 – 3 key points)\n"
+ "• identifies the primary intended users or systems (e.g., smart‑contract developers, node operators, rollup teams)\n"
+ "• notes clearly signalled context such as on‑chain layer (L1, L2, cross‑chain), domain focus (DeFi, NFTs, social, storage, etc.), "
+ "and prominent tech details (language, toolchain, runtime)\n"
"\n"
"**Style constraints**\n"
- "• Use plain, factual language in third person (no hype, no marketing adjectives).\n"
- "• **Do not** guess or invent details that are not explicit in the README.\n"
- "• **Do not** label the project with, or copy wording from, the taxonomy below (to avoid category leakage).\n"
- "• Limit the summary to <100 words; avoid bullet lists or line breaks.\n"
+ "• Use plain, factual third‑person language; avoid hype and marketing adjectives.\n"
+ "• **Do not** guess or invent information not explicit in the README.\n"
+ "• **Do not** label the project with, or quote wording from, the taxonomy categories (to prevent leakage).\n"
+ "• Keep the entire summary under 100 words with no bullet lists or extra line breaks.\n"
"\n"
- "Return your answer as **exactly one valid JSON object** in this form (nothing extra):\n"
+ "Return **exactly one valid JSON object** in this form (nothing else):\n"
"{{\n"
' \"summary\": \"your summary here\"\n'
"}}\n"
"\n"
"README:\n"
"{readme_md}"
-)
-
-TAGS_PROMPT = (
- "Based on this project summary, generate a list of relevant tags that "
- "describe the project's purpose and functionality.\n\n"
- "You must respond with a valid JSON object in this exact format:\n"
- "{{\n"
- ' "tags": ["tag1", "tag2", "tag3"]\n'
- "}}\n\n"
- "Summary:\n{summary}"
-)
+)
\ No newline at end of file
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/categorizer.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/categorizer.py
index 67762e9a..a465159f 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/categorizer.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/categorizer.py
@@ -96,7 +96,7 @@ def run(self, force_refresh: bool = False, target_persona_name: str = None, new_
# Prepare list of dicts, each containing summary and metadata for a project
project_data_batch = []
- required_metadata_cols = ['star_count', 'fork_count', 'created_at', 'updated_at']
+ required_metadata_cols = ['star_count', 'fork_count', 'language', 'created_at', 'updated_at']
for _, row in batch_df.iterrows():
project_data = {
'summary': row.get('summary', ''),
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/unified_processor.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/unified_processor.py
index d669fa76..586461d0 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/unified_processor.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/pipeline/unified_processor.py
@@ -58,10 +58,10 @@ def run(self,
# Fetch repositories from OSO
print("Fetching repositories from OSO...")
- repos_df = self.fetcher.fetch_repositories(limit=limit, sort_by_stars=True)
+ repos_df = self.fetcher.fetch_repositories(limit=limit, sort_by_stars=True, min_stars=self.config_manager.get_min_stars())
if repos_df.empty:
- print("No repositories found from OSO fetch.")
+ print("No repositories found from OSO fetch.")
return pd.DataFrame()
print(f"Found {len(repos_df)} repositories from OSO.")
@@ -239,9 +239,11 @@ def _process_repositories(self, repos_df: pd.DataFrame, batch_size: int) -> pd.D
# Prepare project data for categorization
project_data = {
'summary': repo_data['summary'],
+ 'readme_md': repo_data.get('readme_md', ''),
'repo_artifact_id': repo_id,
'star_count': repo_data.get('star_count', 0),
'fork_count': repo_data.get('fork_count', 0),
+ 'language': repo_data.get('language', 'Unknown'),
'created_at': repo_data.get('created_at'),
'updated_at': repo_data.get('updated_at')
}
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/ai_service.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/ai_service.py
index 074767dd..98405d32 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/ai_service.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/ai_service.py
@@ -9,17 +9,13 @@
# Define generic type for output classes
T = TypeVar(
'T',
- bound=Union['SummaryOutput', 'TagsOutput', 'ClassificationOutput', 'BatchClassificationOutput']
+ bound=Union['SummaryOutput', 'ClassificationOutput', 'BatchClassificationOutput']
)
@dataclass
class SummaryOutput:
summary: str
-@dataclass
-class TagsOutput:
- tags: List[str]
-
@dataclass
class ClassificationOutput:
assigned_tag: str
@@ -73,8 +69,6 @@ def execute_query(self, prompt: str, output_class: Type[T]) -> T:
# Fallback for errors
if output_class is SummaryOutput:
return SummaryOutput(summary="Error generating summary.")
- if output_class is TagsOutput:
- return TagsOutput(tags=[])
if output_class is ClassificationOutput:
return ClassificationOutput(assigned_tag="Error", reason="API call failed.")
if output_class is BatchClassificationOutput:
@@ -101,8 +95,6 @@ def execute_query(self, prompt: str, output_class: Type[T]) -> T:
if output_class is SummaryOutput:
return SummaryOutput(summary=data.get("summary", "Summary not found in response."))
- if output_class is TagsOutput:
- return TagsOutput(tags=data.get("tags", []))
if output_class is ClassificationOutput: # For single classification
return ClassificationOutput(
assigned_tag=data.get("assigned_tag", "Other"),
@@ -124,8 +116,6 @@ def execute_query(self, prompt: str, output_class: Type[T]) -> T:
print(f"Error processing Gemini response: {e}. Raw text: '{response.text[:300]}...'")
if output_class is SummaryOutput:
return SummaryOutput(summary="Failed to parse summary from response.")
- if output_class is TagsOutput:
- return TagsOutput(tags=[])
if output_class is ClassificationOutput:
return ClassificationOutput(assigned_tag="Other", reason="Failed to parse classification.")
if output_class is BatchClassificationOutput:
@@ -142,15 +132,6 @@ def make_summary(self, readme_md: str) -> SummaryOutput:
prompt = prompt_template.format(readme_md=readme_md)
return self.execute_query(prompt, SummaryOutput)
- def make_tags(self, summary: str) -> TagsOutput:
- """Generate tags for the project based on its summary."""
- if not summary or "empty repository" in summary.lower() or "error generating summary" in summary.lower():
- return TagsOutput(tags=[])
-
- prompt_template = self.config_manager.get_tags_prompt_template()
- prompt = prompt_template.format(summary=summary)
- return self.execute_query(prompt, TagsOutput)
-
def classify_projects_batch_for_persona(
self,
project_data_batch: List[Dict[str, Any]], # Changed from summaries: List[str]
@@ -196,6 +177,15 @@ def classify_projects_batch_for_persona(
if not isinstance(summary_text, str):
summary_text = str(summary_text)
+ # Ensure language is a string
+ language_text = project_data.get('language', "Unknown")
+ if not isinstance(language_text, str):
+ language_text = str(language_text) if language_text is not None else "Unknown"
+
+ # Get full README content
+ readme_content = project_data.get('readme_md', '')
+ if not isinstance(readme_content, str):
+ readme_content = str(readme_content) if readme_content is not None else ''
try:
# The persona_prompt_template itself contains the persona's role description.
@@ -203,6 +193,8 @@ def classify_projects_batch_for_persona(
# The {categories} placeholder in the persona prompt will be filled by this categories_list_str.
formatted_project_section = persona_prompt_template.format(
summary=summary_text,
+ readme_md=readme_content,
+ language=language_text,
star_count=formatted_star_count,
fork_count=formatted_fork_count,
created_at=formatted_created_at,
diff --git a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/fetcher.py b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/fetcher.py
index 36bf25ac..02edbf49 100644
--- a/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/fetcher.py
+++ b/experiments/ethereum-repo-clusters/ethereum-repo-clusters/processing/fetcher.py
@@ -9,7 +9,7 @@ class DataFetcher:
def __init__(self):
self.oso_client = Client(api_key=OSO_API_KEY)
- def fetch_repositories(self, limit: int = None, sort_by_stars: bool = True) -> pd.DataFrame:
+ def fetch_repositories(self, limit: int = None, sort_by_stars: bool = True, min_stars: int = 0) -> pd.DataFrame:
"""
Fetch repositories from OSO.
@@ -28,28 +28,25 @@ def fetch_repositories(self, limit: int = None, sort_by_stars: bool = True) -> p
query = f"""
SELECT DISTINCT
re.artifact_id AS repo_artifact_id,
- p.project_id,
- p.project_name,
- p.display_name,
re.artifact_namespace AS repo_artifact_namespace,
re.artifact_name AS repo_artifact_name,
re.created_at,
re.updated_at,
+ re.language,
re.star_count,
re.fork_count,
re.is_fork,
re.num_packages_in_deps_dev
FROM int_repositories_enriched AS re
- JOIN projects_v1 AS p ON re.project_id = p.project_id
- WHERE p.project_id IN (
+ JOIN artifacts_by_project_v1 AS ap ON re.artifact_id = ap.artifact_id
+ WHERE ap.project_id IN (
SELECT DISTINCT project_id FROM oso.projects_by_collection_v1
WHERE {where_keywords}
)
+ AND re.star_count > {min_stars}
"""
- # The table int_superchain_s7_devtooling_repositories should have star_count
- # If not, this sort will fail or do nothing. Assuming 'r.star_count' is valid.
if sort_by_stars:
- query += " ORDER BY re.star_count DESC, p.project_name ASC"
+ query += " ORDER BY re.star_count DESC, re.artifact_namespace ASC"
if limit is not None and isinstance(limit, int) and limit > 0:
query += f" LIMIT {limit}"
diff --git a/experiments/ethereum-repo-clusters/pipeline_config.json b/experiments/ethereum-repo-clusters/pipeline_config.json
index 65dc68d3..1de66d4f 100644
--- a/experiments/ethereum-repo-clusters/pipeline_config.json
+++ b/experiments/ethereum-repo-clusters/pipeline_config.json
@@ -1,10 +1,10 @@
{
- "output_dir": "/Users/cerv1/Dropbox/Kariba/Github/insights/experiments/devtooling_labels/output",
+ "output_dir": "./output",
"gemini_model": "gemini-2.0-flash",
"summary_prompt_template": "You are an analyst preparing short, neutral briefs on open-source projects. Read the README below and write a **concise, 2- to 3-sentence summary** that:\n\u2022 states the project\u2019s core purpose / problem it solves\n\u2022 lists its main capabilities or components (1\u20133 key points only)\n\u2022 mentions the primary intended users or systems (e.g., smart-contract developers, node operators)\n\u2022 notes any strongly signalled context such as supported programming language, network, or runtime\n\n**Style constraints**\n\u2022 Use plain, factual language in third person (no hype, no marketing adjectives).\n\u2022 **Do not** guess or invent details that are not explicit in the README.\n\u2022 **Do not** label the project with, or copy wording from, the taxonomy below (to avoid category leakage).\n\u2022 Limit the summary to <100 words; avoid bullet lists or line breaks.\n\nReturn your answer as **exactly one valid JSON object** in this form (nothing extra):\n{{\n \"summary\": \"your summary here\"\n}}\n\nREADME:\n{readme_md}",
- "tags_prompt_template": "Based on this project summary, generate a list of relevant tags that describe the project's purpose and functionality.\n\nYou must respond with a valid JSON object in this exact format:\n{{\n \"tags\": [\"tag1\", \"tag2\", \"tag3\"]\n}}\n\nSummary:\n{summary}",
"test_mode": false,
- "test_mode_limit": 30,
+ "test_mode_limit": 10,
"batch_size_summaries": 10,
- "batch_size_categorization": 10
+ "batch_size_categorization": 10,
+ "min_stars": 9
}
\ No newline at end of file
diff --git a/experiments/ethereum-repo-clusters/poetry.lock b/experiments/ethereum-repo-clusters/poetry.lock
new file mode 100644
index 00000000..045820c1
--- /dev/null
+++ b/experiments/ethereum-repo-clusters/poetry.lock
@@ -0,0 +1,1044 @@
+# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
+]
+
+[[package]]
+name = "cachetools"
+version = "5.5.2"
+description = "Extensible memoizing collections and decorators"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"},
+ {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"},
+]
+
+[[package]]
+name = "certifi"
+version = "2025.6.15"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"},
+ {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.2"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"},
+ {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"},
+ {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"},
+ {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"},
+ {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"},
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"},
+ {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"},
+ {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"},
+ {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"},
+ {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"},
+]
+
+[[package]]
+name = "click"
+version = "8.2.1"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.10"
+files = [
+ {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"},
+ {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "google-ai-generativelanguage"
+version = "0.6.15"
+description = "Google Ai Generativelanguage API client library"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "google_ai_generativelanguage-0.6.15-py3-none-any.whl", hash = "sha256:5a03ef86377aa184ffef3662ca28f19eeee158733e45d7947982eb953c6ebb6c"},
+ {file = "google_ai_generativelanguage-0.6.15.tar.gz", hash = "sha256:8f6d9dc4c12b065fe2d0289026171acea5183ebf2d0b11cefe12f3821e159ec3"},
+]
+
+[package.dependencies]
+google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]}
+google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev"
+proto-plus = [
+ {version = ">=1.22.3,<2.0.0dev", markers = "python_version < \"3.13\""},
+ {version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""},
+]
+protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev"
+
+[[package]]
+name = "google-api-core"
+version = "2.25.1"
+description = "Google API client core library"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "google_api_core-2.25.1-py3-none-any.whl", hash = "sha256:8a2a56c1fef82987a524371f99f3bd0143702fecc670c72e600c1cda6bf8dbb7"},
+ {file = "google_api_core-2.25.1.tar.gz", hash = "sha256:d2aaa0b13c78c61cb3f4282c464c046e45fbd75755683c9c525e6e8f7ed0a5e8"},
+]
+
+[package.dependencies]
+google-auth = ">=2.14.1,<3.0.0"
+googleapis-common-protos = ">=1.56.2,<2.0.0"
+grpcio = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
+grpcio-status = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
+proto-plus = [
+ {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""},
+ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""},
+]
+protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
+requests = ">=2.18.0,<3.0.0"
+
+[package.extras]
+async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.0)"]
+grpc = ["grpcio (>=1.33.2,<2.0.0)", "grpcio (>=1.49.1,<2.0.0)", "grpcio-status (>=1.33.2,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0)"]
+grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"]
+grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"]
+
+[[package]]
+name = "google-api-python-client"
+version = "2.174.0"
+description = "Google API Client Library for Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "google_api_python_client-2.174.0-py3-none-any.whl", hash = "sha256:f695205ceec97bfaa1590a14282559c4109326c473b07352233a3584cdbf4b89"},
+ {file = "google_api_python_client-2.174.0.tar.gz", hash = "sha256:9eb7616a820b38a9c12c5486f9b9055385c7feb18b20cbafc5c5a688b14f3515"},
+]
+
+[package.dependencies]
+google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0"
+google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0"
+google-auth-httplib2 = ">=0.2.0,<1.0.0"
+httplib2 = ">=0.19.0,<1.0.0"
+uritemplate = ">=3.0.1,<5"
+
+[[package]]
+name = "google-auth"
+version = "2.40.3"
+description = "Google Authentication Library"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "google_auth-2.40.3-py2.py3-none-any.whl", hash = "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca"},
+ {file = "google_auth-2.40.3.tar.gz", hash = "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77"},
+]
+
+[package.dependencies]
+cachetools = ">=2.0.0,<6.0"
+pyasn1-modules = ">=0.2.1"
+rsa = ">=3.1.4,<5"
+
+[package.extras]
+aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"]
+enterprise-cert = ["cryptography", "pyopenssl"]
+pyjwt = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyjwt (>=2.0)"]
+pyopenssl = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"]
+reauth = ["pyu2f (>=0.1.5)"]
+requests = ["requests (>=2.20.0,<3.0.0)"]
+testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "cryptography (<39.0.0)", "cryptography (>=38.0.3)", "flask", "freezegun", "grpcio", "mock", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"]
+urllib3 = ["packaging", "urllib3"]
+
+[[package]]
+name = "google-auth-httplib2"
+version = "0.2.0"
+description = "Google Authentication Library: httplib2 transport"
+optional = false
+python-versions = "*"
+files = [
+ {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"},
+ {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"},
+]
+
+[package.dependencies]
+google-auth = "*"
+httplib2 = ">=0.19.0"
+
+[[package]]
+name = "google-generativeai"
+version = "0.8.5"
+description = "Google Generative AI High level API client library and tools."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "google_generativeai-0.8.5-py3-none-any.whl", hash = "sha256:22b420817fb263f8ed520b33285f45976d5b21e904da32b80d4fd20c055123a2"},
+]
+
+[package.dependencies]
+google-ai-generativelanguage = "0.6.15"
+google-api-core = "*"
+google-api-python-client = "*"
+google-auth = ">=2.15.0"
+protobuf = "*"
+pydantic = "*"
+tqdm = "*"
+typing-extensions = "*"
+
+[package.extras]
+dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"]
+
+[[package]]
+name = "googleapis-common-protos"
+version = "1.70.0"
+description = "Common protobufs used in Google APIs"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8"},
+ {file = "googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257"},
+]
+
+[package.dependencies]
+protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
+
+[package.extras]
+grpc = ["grpcio (>=1.44.0,<2.0.0)"]
+
+[[package]]
+name = "grpcio"
+version = "1.73.1"
+description = "HTTP/2-based RPC framework"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "grpcio-1.73.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:2d70f4ddd0a823436c2624640570ed6097e40935c9194482475fe8e3d9754d55"},
+ {file = "grpcio-1.73.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:3841a8a5a66830261ab6a3c2a3dc539ed84e4ab019165f77b3eeb9f0ba621f26"},
+ {file = "grpcio-1.73.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:628c30f8e77e0258ab788750ec92059fc3d6628590fb4b7cea8c102503623ed7"},
+ {file = "grpcio-1.73.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67a0468256c9db6d5ecb1fde4bf409d016f42cef649323f0a08a72f352d1358b"},
+ {file = "grpcio-1.73.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68b84d65bbdebd5926eb5c53b0b9ec3b3f83408a30e4c20c373c5337b4219ec5"},
+ {file = "grpcio-1.73.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c54796ca22b8349cc594d18b01099e39f2b7ffb586ad83217655781a350ce4da"},
+ {file = "grpcio-1.73.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:75fc8e543962ece2f7ecd32ada2d44c0c8570ae73ec92869f9af8b944863116d"},
+ {file = "grpcio-1.73.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6a6037891cd2b1dd1406b388660522e1565ed340b1fea2955b0234bdd941a862"},
+ {file = "grpcio-1.73.1-cp310-cp310-win32.whl", hash = "sha256:cce7265b9617168c2d08ae570fcc2af4eaf72e84f8c710ca657cc546115263af"},
+ {file = "grpcio-1.73.1-cp310-cp310-win_amd64.whl", hash = "sha256:6a2b372e65fad38842050943f42ce8fee00c6f2e8ea4f7754ba7478d26a356ee"},
+ {file = "grpcio-1.73.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:ba2cea9f7ae4bc21f42015f0ec98f69ae4179848ad744b210e7685112fa507a1"},
+ {file = "grpcio-1.73.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:d74c3f4f37b79e746271aa6cdb3a1d7e4432aea38735542b23adcabaaee0c097"},
+ {file = "grpcio-1.73.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5b9b1805a7d61c9e90541cbe8dfe0a593dfc8c5c3a43fe623701b6a01b01d710"},
+ {file = "grpcio-1.73.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3215f69a0670a8cfa2ab53236d9e8026bfb7ead5d4baabe7d7dc11d30fda967"},
+ {file = "grpcio-1.73.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc5eccfd9577a5dc7d5612b2ba90cca4ad14c6d949216c68585fdec9848befb1"},
+ {file = "grpcio-1.73.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dc7d7fd520614fce2e6455ba89791458020a39716951c7c07694f9dbae28e9c0"},
+ {file = "grpcio-1.73.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:105492124828911f85127e4825d1c1234b032cb9d238567876b5515d01151379"},
+ {file = "grpcio-1.73.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:610e19b04f452ba6f402ac9aa94eb3d21fbc94553368008af634812c4a85a99e"},
+ {file = "grpcio-1.73.1-cp311-cp311-win32.whl", hash = "sha256:d60588ab6ba0ac753761ee0e5b30a29398306401bfbceffe7d68ebb21193f9d4"},
+ {file = "grpcio-1.73.1-cp311-cp311-win_amd64.whl", hash = "sha256:6957025a4608bb0a5ff42abd75bfbb2ed99eda29d5992ef31d691ab54b753643"},
+ {file = "grpcio-1.73.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:921b25618b084e75d424a9f8e6403bfeb7abef074bb6c3174701e0f2542debcf"},
+ {file = "grpcio-1.73.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:277b426a0ed341e8447fbf6c1d6b68c952adddf585ea4685aa563de0f03df887"},
+ {file = "grpcio-1.73.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:96c112333309493c10e118d92f04594f9055774757f5d101b39f8150f8c25582"},
+ {file = "grpcio-1.73.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f48e862aed925ae987eb7084409a80985de75243389dc9d9c271dd711e589918"},
+ {file = "grpcio-1.73.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83a6c2cce218e28f5040429835fa34a29319071079e3169f9543c3fbeff166d2"},
+ {file = "grpcio-1.73.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:65b0458a10b100d815a8426b1442bd17001fdb77ea13665b2f7dc9e8587fdc6b"},
+ {file = "grpcio-1.73.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0a9f3ea8dce9eae9d7cb36827200133a72b37a63896e0e61a9d5ec7d61a59ab1"},
+ {file = "grpcio-1.73.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:de18769aea47f18e782bf6819a37c1c528914bfd5683b8782b9da356506190c8"},
+ {file = "grpcio-1.73.1-cp312-cp312-win32.whl", hash = "sha256:24e06a5319e33041e322d32c62b1e728f18ab8c9dbc91729a3d9f9e3ed336642"},
+ {file = "grpcio-1.73.1-cp312-cp312-win_amd64.whl", hash = "sha256:303c8135d8ab176f8038c14cc10d698ae1db9c480f2b2823f7a987aa2a4c5646"},
+ {file = "grpcio-1.73.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:b310824ab5092cf74750ebd8a8a8981c1810cb2b363210e70d06ef37ad80d4f9"},
+ {file = "grpcio-1.73.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:8f5a6df3fba31a3485096ac85b2e34b9666ffb0590df0cd044f58694e6a1f6b5"},
+ {file = "grpcio-1.73.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:052e28fe9c41357da42250a91926a3e2f74c046575c070b69659467ca5aa976b"},
+ {file = "grpcio-1.73.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c0bf15f629b1497436596b1cbddddfa3234273490229ca29561209778ebe182"},
+ {file = "grpcio-1.73.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ab860d5bfa788c5a021fba264802e2593688cd965d1374d31d2b1a34cacd854"},
+ {file = "grpcio-1.73.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ad1d958c31cc91ab050bd8a91355480b8e0683e21176522bacea225ce51163f2"},
+ {file = "grpcio-1.73.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f43ffb3bd415c57224c7427bfb9e6c46a0b6e998754bfa0d00f408e1873dcbb5"},
+ {file = "grpcio-1.73.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:686231cdd03a8a8055f798b2b54b19428cdf18fa1549bee92249b43607c42668"},
+ {file = "grpcio-1.73.1-cp313-cp313-win32.whl", hash = "sha256:89018866a096e2ce21e05eabed1567479713ebe57b1db7cbb0f1e3b896793ba4"},
+ {file = "grpcio-1.73.1-cp313-cp313-win_amd64.whl", hash = "sha256:4a68f8c9966b94dff693670a5cf2b54888a48a5011c5d9ce2295a1a1465ee84f"},
+ {file = "grpcio-1.73.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:b4adc97d2d7f5c660a5498bda978ebb866066ad10097265a5da0511323ae9f50"},
+ {file = "grpcio-1.73.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:c45a28a0cfb6ddcc7dc50a29de44ecac53d115c3388b2782404218db51cb2df3"},
+ {file = "grpcio-1.73.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:10af9f2ab98a39f5b6c1896c6fc2036744b5b41d12739d48bed4c3e15b6cf900"},
+ {file = "grpcio-1.73.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45cf17dcce5ebdb7b4fe9e86cb338fa99d7d1bb71defc78228e1ddf8d0de8cbb"},
+ {file = "grpcio-1.73.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c502c2e950fc7e8bf05c047e8a14522ef7babac59abbfde6dbf46b7a0d9c71e"},
+ {file = "grpcio-1.73.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6abfc0f9153dc4924536f40336f88bd4fe7bd7494f028675e2e04291b8c2c62a"},
+ {file = "grpcio-1.73.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ed451a0e39c8e51eb1612b78686839efd1a920666d1666c1adfdb4fd51680c0f"},
+ {file = "grpcio-1.73.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:07f08705a5505c9b5b0cbcbabafb96462b5a15b7236bbf6bbcc6b0b91e1cbd7e"},
+ {file = "grpcio-1.73.1-cp39-cp39-win32.whl", hash = "sha256:ad5c958cc3d98bb9d71714dc69f1c13aaf2f4b53e29d4cc3f1501ef2e4d129b2"},
+ {file = "grpcio-1.73.1-cp39-cp39-win_amd64.whl", hash = "sha256:42f0660bce31b745eb9d23f094a332d31f210dcadd0fc8e5be7e4c62a87ce86b"},
+ {file = "grpcio-1.73.1.tar.gz", hash = "sha256:7fce2cd1c0c1116cf3850564ebfc3264fba75d3c74a7414373f1238ea365ef87"},
+]
+
+[package.extras]
+protobuf = ["grpcio-tools (>=1.73.1)"]
+
+[[package]]
+name = "grpcio-status"
+version = "1.71.2"
+description = "Status proto mapping for gRPC"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "grpcio_status-1.71.2-py3-none-any.whl", hash = "sha256:803c98cb6a8b7dc6dbb785b1111aed739f241ab5e9da0bba96888aa74704cfd3"},
+ {file = "grpcio_status-1.71.2.tar.gz", hash = "sha256:c7a97e176df71cdc2c179cd1847d7fc86cca5832ad12e9798d7fed6b7a1aab50"},
+]
+
+[package.dependencies]
+googleapis-common-protos = ">=1.5.5"
+grpcio = ">=1.71.2"
+protobuf = ">=5.26.1,<6.0dev"
+
+[[package]]
+name = "httplib2"
+version = "0.22.0"
+description = "A comprehensive HTTP client library."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"},
+ {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"},
+]
+
+[package.dependencies]
+pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""}
+
+[[package]]
+name = "idna"
+version = "3.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
+]
+
+[package.extras]
+all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
+
+[[package]]
+name = "numpy"
+version = "2.3.1"
+description = "Fundamental package for array computing in Python"
+optional = false
+python-versions = ">=3.11"
+files = [
+ {file = "numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070"},
+ {file = "numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae"},
+ {file = "numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a"},
+ {file = "numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e"},
+ {file = "numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db"},
+ {file = "numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb"},
+ {file = "numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93"},
+ {file = "numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115"},
+ {file = "numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369"},
+ {file = "numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff"},
+ {file = "numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a"},
+ {file = "numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d"},
+ {file = "numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29"},
+ {file = "numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc"},
+ {file = "numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943"},
+ {file = "numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25"},
+ {file = "numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660"},
+ {file = "numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952"},
+ {file = "numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77"},
+ {file = "numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab"},
+ {file = "numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76"},
+ {file = "numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30"},
+ {file = "numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8"},
+ {file = "numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e"},
+ {file = "numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0"},
+ {file = "numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d"},
+ {file = "numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1"},
+ {file = "numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1"},
+ {file = "numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0"},
+ {file = "numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8"},
+ {file = "numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8"},
+ {file = "numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42"},
+ {file = "numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e"},
+ {file = "numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8"},
+ {file = "numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb"},
+ {file = "numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee"},
+ {file = "numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992"},
+ {file = "numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c"},
+ {file = "numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48"},
+ {file = "numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee"},
+ {file = "numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280"},
+ {file = "numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e"},
+ {file = "numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc"},
+ {file = "numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68"},
+ {file = "numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb"},
+ {file = "numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b"},
+]
+
+[[package]]
+name = "pandas"
+version = "2.3.0"
+description = "Powerful data structures for data analysis, time series, and statistics"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pandas-2.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:625466edd01d43b75b1883a64d859168e4556261a5035b32f9d743b67ef44634"},
+ {file = "pandas-2.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6872d695c896f00df46b71648eea332279ef4077a409e2fe94220208b6bb675"},
+ {file = "pandas-2.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4dd97c19bd06bc557ad787a15b6489d2614ddaab5d104a0310eb314c724b2d2"},
+ {file = "pandas-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:034abd6f3db8b9880aaee98f4f5d4dbec7c4829938463ec046517220b2f8574e"},
+ {file = "pandas-2.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23c2b2dc5213810208ca0b80b8666670eb4660bbfd9d45f58592cc4ddcfd62e1"},
+ {file = "pandas-2.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:39ff73ec07be5e90330cc6ff5705c651ace83374189dcdcb46e6ff54b4a72cd6"},
+ {file = "pandas-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:40cecc4ea5abd2921682b57532baea5588cc5f80f0231c624056b146887274d2"},
+ {file = "pandas-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8adff9f138fc614347ff33812046787f7d43b3cef7c0f0171b3340cae333f6ca"},
+ {file = "pandas-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5f08eb9a445d07720776df6e641975665c9ea12c9d8a331e0f6890f2dcd76ef"},
+ {file = "pandas-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa35c266c8cd1a67d75971a1912b185b492d257092bdd2709bbdebe574ed228d"},
+ {file = "pandas-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a0cc77b0f089d2d2ffe3007db58f170dae9b9f54e569b299db871a3ab5bf46"},
+ {file = "pandas-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c06f6f144ad0a1bf84699aeea7eff6068ca5c63ceb404798198af7eb86082e33"},
+ {file = "pandas-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed16339bc354a73e0a609df36d256672c7d296f3f767ac07257801aa064ff73c"},
+ {file = "pandas-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:fa07e138b3f6c04addfeaf56cc7fdb96c3b68a3fe5e5401251f231fce40a0d7a"},
+ {file = "pandas-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf"},
+ {file = "pandas-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027"},
+ {file = "pandas-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09"},
+ {file = "pandas-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d"},
+ {file = "pandas-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20"},
+ {file = "pandas-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b"},
+ {file = "pandas-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be"},
+ {file = "pandas-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983"},
+ {file = "pandas-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd"},
+ {file = "pandas-2.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f"},
+ {file = "pandas-2.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3"},
+ {file = "pandas-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8"},
+ {file = "pandas-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9"},
+ {file = "pandas-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390"},
+ {file = "pandas-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575"},
+ {file = "pandas-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042"},
+ {file = "pandas-2.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c"},
+ {file = "pandas-2.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67"},
+ {file = "pandas-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f"},
+ {file = "pandas-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249"},
+ {file = "pandas-2.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9efc0acbbffb5236fbdf0409c04edce96bec4bdaa649d49985427bd1ec73e085"},
+ {file = "pandas-2.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:75651c14fde635e680496148a8526b328e09fe0572d9ae9b638648c46a544ba3"},
+ {file = "pandas-2.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5be867a0541a9fb47a4be0c5790a4bccd5b77b92f0a59eeec9375fafc2aa14"},
+ {file = "pandas-2.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84141f722d45d0c2a89544dd29d35b3abfc13d2250ed7e68394eda7564bd6324"},
+ {file = "pandas-2.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f95a2aef32614ed86216d3c450ab12a4e82084e8102e355707a1d96e33d51c34"},
+ {file = "pandas-2.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e0f51973ba93a9f97185049326d75b942b9aeb472bec616a129806facb129ebb"},
+ {file = "pandas-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b198687ca9c8529662213538a9bb1e60fa0bf0f6af89292eb68fea28743fcd5a"},
+ {file = "pandas-2.3.0.tar.gz", hash = "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133"},
+]
+
+[package.dependencies]
+numpy = [
+ {version = ">=1.23.2", markers = "python_version == \"3.11\""},
+ {version = ">=1.26.0", markers = "python_version >= \"3.12\""},
+]
+python-dateutil = ">=2.8.2"
+pytz = ">=2020.1"
+tzdata = ">=2022.7"
+
+[package.extras]
+all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"]
+aws = ["s3fs (>=2022.11.0)"]
+clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"]
+compression = ["zstandard (>=0.19.0)"]
+computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"]
+consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
+excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"]
+feather = ["pyarrow (>=10.0.1)"]
+fss = ["fsspec (>=2022.11.0)"]
+gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"]
+hdf5 = ["tables (>=3.8.0)"]
+html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"]
+mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"]
+output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"]
+parquet = ["pyarrow (>=10.0.1)"]
+performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
+plot = ["matplotlib (>=3.6.3)"]
+postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
+pyarrow = ["pyarrow (>=10.0.1)"]
+spss = ["pyreadstat (>=1.2.0)"]
+sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
+test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
+xml = ["lxml (>=4.9.2)"]
+
+[[package]]
+name = "proto-plus"
+version = "1.26.1"
+description = "Beautiful, Pythonic protocol buffers"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66"},
+ {file = "proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012"},
+]
+
+[package.dependencies]
+protobuf = ">=3.19.0,<7.0.0"
+
+[package.extras]
+testing = ["google-api-core (>=1.31.5)"]
+
+[[package]]
+name = "protobuf"
+version = "5.29.5"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"},
+ {file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"},
+ {file = "protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671"},
+ {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015"},
+ {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61"},
+ {file = "protobuf-5.29.5-cp38-cp38-win32.whl", hash = "sha256:ef91363ad4faba7b25d844ef1ada59ff1604184c0bcd8b39b8a6bef15e1af238"},
+ {file = "protobuf-5.29.5-cp38-cp38-win_amd64.whl", hash = "sha256:7318608d56b6402d2ea7704ff1e1e4597bee46d760e7e4dd42a3d45e24b87f2e"},
+ {file = "protobuf-5.29.5-cp39-cp39-win32.whl", hash = "sha256:6f642dc9a61782fa72b90878af134c5afe1917c89a568cd3476d758d3c3a0736"},
+ {file = "protobuf-5.29.5-cp39-cp39-win_amd64.whl", hash = "sha256:470f3af547ef17847a28e1f47200a1cbf0ba3ff57b7de50d22776607cd2ea353"},
+ {file = "protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5"},
+ {file = "protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84"},
+]
+
+[[package]]
+name = "pyarrow"
+version = "20.0.0"
+description = "Python library for Apache Arrow"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7"},
+ {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4"},
+ {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae"},
+ {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee"},
+ {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20"},
+ {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9"},
+ {file = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75"},
+ {file = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8"},
+ {file = "pyarrow-20.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191"},
+ {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0"},
+ {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb"},
+ {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232"},
+ {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f"},
+ {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab"},
+ {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62"},
+ {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c"},
+ {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3"},
+ {file = "pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc"},
+ {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba"},
+ {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781"},
+ {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199"},
+ {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd"},
+ {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28"},
+ {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8"},
+ {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e"},
+ {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a"},
+ {file = "pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b"},
+ {file = "pyarrow-20.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:a15532e77b94c61efadde86d10957950392999503b3616b2ffcef7621a002893"},
+ {file = "pyarrow-20.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:dd43f58037443af715f34f1322c782ec463a3c8a94a85fdb2d987ceb5658e061"},
+ {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0d288143a8585806e3cc7c39566407aab646fb9ece164609dac1cfff45f6ae"},
+ {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6953f0114f8d6f3d905d98e987d0924dabce59c3cda380bdfaa25a6201563b4"},
+ {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:991f85b48a8a5e839b2128590ce07611fae48a904cae6cab1f089c5955b57eb5"},
+ {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:97c8dc984ed09cb07d618d57d8d4b67a5100a30c3818c2fb0b04599f0da2de7b"},
+ {file = "pyarrow-20.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9b71daf534f4745818f96c214dbc1e6124d7daf059167330b610fc69b6f3d3e3"},
+ {file = "pyarrow-20.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8b88758f9303fa5a83d6c90e176714b2fd3852e776fc2d7e42a22dd6c2fb368"},
+ {file = "pyarrow-20.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:30b3051b7975801c1e1d387e17c588d8ab05ced9b1e14eec57915f79869b5031"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ca151afa4f9b7bc45bcc791eb9a89e90a9eb2772767d0b1e5389609c7d03db63"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:4680f01ecd86e0dd63e39eb5cd59ef9ff24a9d166db328679e36c108dc993d4c"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f4c8534e2ff059765647aa69b75d6543f9fef59e2cd4c6d18015192565d2b70"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e1f8a47f4b4ae4c69c4d702cfbdfe4d41e18e5c7ef6f1bb1c50918c1e81c57b"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a1f60dc14658efaa927f8214734f6a01a806d7690be4b3232ba526836d216122"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:204a846dca751428991346976b914d6d2a82ae5b8316a6ed99789ebf976551e6"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f3b117b922af5e4c6b9a9115825726cac7d8b1421c37c2b5e24fbacc8930612c"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e724a3fd23ae5b9c010e7be857f4405ed5e679db5c93e66204db1a69f733936a"},
+ {file = "pyarrow-20.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:82f1ee5133bd8f49d31be1299dc07f585136679666b502540db854968576faf9"},
+ {file = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:1bcbe471ef3349be7714261dea28fe280db574f9d0f77eeccc195a2d161fd861"},
+ {file = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:a18a14baef7d7ae49247e75641fd8bcbb39f44ed49a9fc4ec2f65d5031aa3b96"},
+ {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb497649e505dc36542d0e68eca1a3c94ecbe9799cb67b578b55f2441a247fbc"},
+ {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11529a2283cb1f6271d7c23e4a8f9f8b7fd173f7360776b668e509d712a02eec"},
+ {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fc1499ed3b4b57ee4e090e1cea6eb3584793fe3d1b4297bbf53f09b434991a5"},
+ {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:db53390eaf8a4dab4dbd6d93c85c5cf002db24902dbff0ca7d988beb5c9dd15b"},
+ {file = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:851c6a8260ad387caf82d2bbf54759130534723e37083111d4ed481cb253cc0d"},
+ {file = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e22f80b97a271f0a7d9cd07394a7d348f80d3ac63ed7cc38b6d1b696ab3b2619"},
+ {file = "pyarrow-20.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:9965a050048ab02409fb7cbbefeedba04d3d67f2cc899eff505cc084345959ca"},
+ {file = "pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1"},
+]
+
+[package.extras]
+test = ["cffi", "hypothesis", "pandas", "pytest", "pytz"]
+
+[[package]]
+name = "pyasn1"
+version = "0.6.1"
+description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
+ {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
+]
+
+[[package]]
+name = "pyasn1-modules"
+version = "0.4.2"
+description = "A collection of ASN.1-based protocols modules"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"},
+ {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"},
+]
+
+[package.dependencies]
+pyasn1 = ">=0.6.1,<0.7.0"
+
+[[package]]
+name = "pydantic"
+version = "2.11.7"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b"},
+ {file = "pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.6.0"
+pydantic-core = "2.33.2"
+typing-extensions = ">=4.12.2"
+typing-inspection = ">=0.4.0"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+timezone = ["tzdata"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.33.2"
+description = "Core functionality for Pydantic validation and serialization"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"},
+ {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"},
+ {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"},
+ {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"},
+ {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"},
+ {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"},
+ {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"},
+ {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"},
+ {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"},
+ {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"},
+ {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"},
+ {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"},
+ {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "pyoso"
+version = "0.5.1"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pyoso-0.5.1-py3-none-any.whl", hash = "sha256:1947cb4d2c4c51995e09697a02b5d63abe6918e0cd3596665b682b128fc326a7"},
+ {file = "pyoso-0.5.1.tar.gz", hash = "sha256:3086898e61cf68af0f0eeabfd8a5931665e0ec3162e059caaa546f209b239411"},
+]
+
+[package.dependencies]
+pandas = ">=1.2.0"
+requests = ">=2.32.4"
+sqlglot = ">=26.16.4"
+
+[package.extras]
+semantic = ["oso-semantic"]
+
+[[package]]
+name = "pyparsing"
+version = "3.2.3"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"},
+ {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"},
+]
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
+ {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "python-dotenv"
+version = "1.1.1"
+description = "Read key-value pairs from a .env file and set them as environment variables"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"},
+ {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"},
+]
+
+[package.extras]
+cli = ["click (>=5.0)"]
+
+[[package]]
+name = "pytz"
+version = "2025.2"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"},
+ {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"},
+]
+
+[[package]]
+name = "requests"
+version = "2.32.4"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"},
+ {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset_normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "rsa"
+version = "4.9.1"
+description = "Pure-Python RSA implementation"
+optional = false
+python-versions = "<4,>=3.6"
+files = [
+ {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"},
+ {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"},
+]
+
+[package.dependencies]
+pyasn1 = ">=0.1.3"
+
+[[package]]
+name = "six"
+version = "1.17.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
+ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
+]
+
+[[package]]
+name = "sqlglot"
+version = "26.31.0"
+description = "An easily customizable SQL parser and transpiler"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sqlglot-26.31.0-py3-none-any.whl", hash = "sha256:1f0e1071b53faebdfcbfa019a831ce0c2b71e4d825f0f08306c5f20c1aef0898"},
+ {file = "sqlglot-26.31.0.tar.gz", hash = "sha256:e9b8f52d02e21636cd7e463af29db0b86707437b9d468b7b2166b67fa96cdd87"},
+]
+
+[package.extras]
+dev = ["duckdb (>=0.6)", "maturin (>=1.4,<2.0)", "mypy", "pandas", "pandas-stubs", "pdoc", "pre-commit", "pyperf", "python-dateutil", "pytz", "ruff (==0.7.2)", "types-python-dateutil", "types-pytz", "typing_extensions"]
+rs = ["sqlglotrs (==0.6.1)"]
+
+[[package]]
+name = "tqdm"
+version = "4.67.1"
+description = "Fast, Extensible Progress Meter"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"},
+ {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[package.extras]
+dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"]
+discord = ["requests"]
+notebook = ["ipywidgets (>=6)"]
+slack = ["slack-sdk"]
+telegram = ["requests"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.14.0"
+description = "Backported and Experimental Type Hints for Python 3.9+"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"},
+ {file = "typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4"},
+]
+
+[[package]]
+name = "typing-inspection"
+version = "0.4.1"
+description = "Runtime typing introspection tools"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"},
+ {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.12.0"
+
+[[package]]
+name = "tzdata"
+version = "2025.2"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
+ {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
+]
+
+[[package]]
+name = "uritemplate"
+version = "4.2.0"
+description = "Implementation of RFC 6570 URI Templates"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "uritemplate-4.2.0-py3-none-any.whl", hash = "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686"},
+ {file = "uritemplate-4.2.0.tar.gz", hash = "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.5.0"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
+ {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.11"
+content-hash = "2698c4c83407acc7ab52e9bcc798061a0c2d3dbc5e8ab28ec4d4c1ead2c6e1d2"
diff --git a/experiments/ethereum-repo-clusters/pyproject.toml b/experiments/ethereum-repo-clusters/pyproject.toml
new file mode 100644
index 00000000..c1b65ece
--- /dev/null
+++ b/experiments/ethereum-repo-clusters/pyproject.toml
@@ -0,0 +1,23 @@
+[tool.poetry]
+name = "ethereum-repo-clusters"
+version = "0.1.0"
+description = ""
+authors = ["Your Name "]
+readme = "README.md"
+package-mode = false
+
+[tool.poetry.dependencies]
+python = "^3.11"
+pandas = "^2.3.0"
+requests = "^2.32.4"
+pyoso = "^0.5.1"
+google-generativeai = "^0.8.5"
+pydantic = "^2.11.7"
+python-dotenv = "^1.1.1"
+click = "^8.2.1"
+pyarrow = "^20.0.0"
+
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/experiments/ethereum-repo-clusters/requirements.txt b/experiments/ethereum-repo-clusters/requirements.txt
deleted file mode 100644
index 7ab7b91e..00000000
--- a/experiments/ethereum-repo-clusters/requirements.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-pandas>=2.0.0
-requests>=2.31.0
-pyoso>=0.1.0
-google-generativeai>=0.3.0
-pydantic>=2.0.0
-python-dotenv>=1.0.0
-click>=8.0.0
-pyarrow>=14.0.0 # For parquet support
diff --git a/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v1.parquet b/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v1.parquet
new file mode 100644
index 00000000..4a76475b
Binary files /dev/null and b/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v1.parquet differ
diff --git a/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v2.parquet b/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v2.parquet
new file mode 100644
index 00000000..a4c246e4
Binary files /dev/null and b/experiments/ethereum-repo-clusters/results/ethereum_repo_categories_v2.parquet differ
diff --git a/experiments/ethereum-repo-clusters/setup.py b/experiments/ethereum-repo-clusters/setup.py
deleted file mode 100644
index 1b43d1c3..00000000
--- a/experiments/ethereum-repo-clusters/setup.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from setuptools import setup, find_packages
-
-setup(
- name="devtooling_labels",
- version="0.1.0",
- packages=find_packages(),
- install_requires=[
- "pandas>=2.0.0",
- "requests>=2.31.0",
- "pyoso>=0.1.0",
- "google-generativeai>=0.3.0",
- "pydantic>=2.0.0",
- "python-dotenv>=1.0.0",
- ],
- python_requires=">=3.8",
-)
\ No newline at end of file
diff --git a/tutorials/FundingMetrics.ipynb b/tutorials/FundingMetrics.ipynb
index d64c4876..83d0cf4a 100644
--- a/tutorials/FundingMetrics.ipynb
+++ b/tutorials/FundingMetrics.ipynb
@@ -81,150 +81,225 @@
" \n",
" \n",
" | 0 | \n",
- " GITCOIN_DONATIONS_funding_awarded_biannually | \n",
+ " ARBITRUMFOUNDATION_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 1 | \n",
- " GITCOIN_DONATIONS_funding_awarded_daily | \n",
+ " CLRFUND_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 2 | \n",
- " GITCOIN_DONATIONS_funding_awarded_monthly | \n",
+ " DAODROPS_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 3 | \n",
- " GITCOIN_DONATIONS_funding_awarded_over_all_time | \n",
+ " GITCOIN_DONATIONS_funding_awarded_biannually | \n",
"
\n",
" \n",
" | 4 | \n",
- " GITCOIN_DONATIONS_funding_awarded_quarterly | \n",
+ " GITCOIN_DONATIONS_funding_awarded_daily | \n",
"
\n",
" \n",
" | 5 | \n",
- " GITCOIN_DONATIONS_funding_awarded_weekly | \n",
+ " GITCOIN_DONATIONS_funding_awarded_monthly | \n",
"
\n",
" \n",
" | 6 | \n",
- " GITCOIN_DONATIONS_funding_awarded_yearly | \n",
+ " GITCOIN_DONATIONS_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 7 | \n",
- " GITCOIN_MATCHING_funding_awarded_biannually | \n",
+ " GITCOIN_DONATIONS_funding_awarded_quarterly | \n",
"
\n",
" \n",
" | 8 | \n",
- " GITCOIN_MATCHING_funding_awarded_daily | \n",
+ " GITCOIN_DONATIONS_funding_awarded_weekly | \n",
"
\n",
" \n",
" | 9 | \n",
- " GITCOIN_MATCHING_funding_awarded_monthly | \n",
+ " GITCOIN_DONATIONS_funding_awarded_yearly | \n",
"
\n",
" \n",
" | 10 | \n",
- " GITCOIN_MATCHING_funding_awarded_over_all_time | \n",
+ " GITCOIN_MATCHING_funding_awarded_biannually | \n",
"
\n",
" \n",
" | 11 | \n",
- " GITCOIN_MATCHING_funding_awarded_quarterly | \n",
+ " GITCOIN_MATCHING_funding_awarded_daily | \n",
"
\n",
" \n",
" | 12 | \n",
- " GITCOIN_MATCHING_funding_awarded_weekly | \n",
+ " GITCOIN_MATCHING_funding_awarded_monthly | \n",
"
\n",
" \n",
" | 13 | \n",
- " GITCOIN_MATCHING_funding_awarded_yearly | \n",
+ " GITCOIN_MATCHING_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 14 | \n",
- " OPEN_COLLECTIVE_funding_received_biannually | \n",
+ " GITCOIN_MATCHING_funding_awarded_quarterly | \n",
"
\n",
" \n",
" | 15 | \n",
- " OPEN_COLLECTIVE_funding_received_daily | \n",
+ " GITCOIN_MATCHING_funding_awarded_weekly | \n",
"
\n",
" \n",
" | 16 | \n",
- " OPEN_COLLECTIVE_funding_received_monthly | \n",
+ " GITCOIN_MATCHING_funding_awarded_yearly | \n",
"
\n",
" \n",
" | 17 | \n",
- " OPEN_COLLECTIVE_funding_received_over_all_time | \n",
+ " OCTANT_funding_awarded_biannually | \n",
"
\n",
" \n",
" | 18 | \n",
- " OPEN_COLLECTIVE_funding_received_quarterly | \n",
+ " OCTANT_funding_awarded_over_all_time | \n",
"
\n",
" \n",
" | 19 | \n",
- " OPEN_COLLECTIVE_funding_received_weekly | \n",
+ " OPEN_COLLECTIVE_funding_received_biannually | \n",
"
\n",
" \n",
" | 20 | \n",
- " OPEN_COLLECTIVE_funding_received_yearly | \n",
+ " OPEN_COLLECTIVE_funding_received_daily | \n",
"
\n",
" \n",
" | 21 | \n",
- " OSS_FUNDING_funding_awarded_biannually | \n",
+ " OPEN_COLLECTIVE_funding_received_monthly | \n",
"
\n",
" \n",
" | 22 | \n",
- " OSS_FUNDING_funding_awarded_daily | \n",
+ " OPEN_COLLECTIVE_funding_received_over_all_time | \n",
"
\n",
" \n",
" | 23 | \n",
- " OSS_FUNDING_funding_awarded_monthly | \n",
+ " OPEN_COLLECTIVE_funding_received_quarterly | \n",
"
\n",
" \n",
" | 24 | \n",
- " OSS_FUNDING_funding_awarded_over_all_time | \n",
+ " OPEN_COLLECTIVE_funding_received_weekly | \n",
"
\n",
" \n",
" | 25 | \n",
- " OSS_FUNDING_funding_awarded_quarterly | \n",
+ " OPEN_COLLECTIVE_funding_received_yearly | \n",
"
\n",
" \n",
" | 26 | \n",
- " OSS_FUNDING_funding_awarded_weekly | \n",
+ " OPTIMISM_GOVGRANTS_funding_awarded_biannually | \n",
"
\n",
" \n",
" | 27 | \n",
+ " OPTIMISM_GOVGRANTS_funding_awarded_over_all_time | \n",
+ "
\n",
+ " \n",
+ " | 28 | \n",
+ " OPTIMISM_GOVGRANTS_funding_awarded_quarterly | \n",
+ "
\n",
+ " \n",
+ " | 29 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_biannually | \n",
+ "
\n",
+ " \n",
+ " | 30 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_daily | \n",
+ "
\n",
+ " \n",
+ " | 31 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_monthly | \n",
+ "
\n",
+ " \n",
+ " | 32 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_over_all... | \n",
+ "
\n",
+ " \n",
+ " | 33 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_quarterly | \n",
+ "
\n",
+ " \n",
+ " | 34 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_weekly | \n",
+ "
\n",
+ " \n",
+ " | 35 | \n",
+ " OSS_FUNDING_funding_awarded_biannually | \n",
+ "
\n",
+ " \n",
+ " | 36 | \n",
+ " OSS_FUNDING_funding_awarded_daily | \n",
+ "
\n",
+ " \n",
+ " | 37 | \n",
+ " OSS_FUNDING_funding_awarded_monthly | \n",
+ "
\n",
+ " \n",
+ " | 38 | \n",
+ " OSS_FUNDING_funding_awarded_quarterly | \n",
+ "
\n",
+ " \n",
+ " | 39 | \n",
+ " OSS_FUNDING_funding_awarded_weekly | \n",
+ "
\n",
+ " \n",
+ " | 40 | \n",
" OSS_FUNDING_funding_awarded_yearly | \n",
"
\n",
+ " \n",
+ " | 41 | \n",
+ " STELLAR_funding_awarded_biannually | \n",
+ "
\n",
+ " \n",
+ " | 42 | \n",
+ " STELLAR_funding_awarded_over_all_time | \n",
+ "
\n",
" \n",
"\n",
""
],
"text/plain": [
- " metric_name\n",
- "0 GITCOIN_DONATIONS_funding_awarded_biannually\n",
- "1 GITCOIN_DONATIONS_funding_awarded_daily\n",
- "2 GITCOIN_DONATIONS_funding_awarded_monthly\n",
- "3 GITCOIN_DONATIONS_funding_awarded_over_all_time\n",
- "4 GITCOIN_DONATIONS_funding_awarded_quarterly\n",
- "5 GITCOIN_DONATIONS_funding_awarded_weekly\n",
- "6 GITCOIN_DONATIONS_funding_awarded_yearly\n",
- "7 GITCOIN_MATCHING_funding_awarded_biannually\n",
- "8 GITCOIN_MATCHING_funding_awarded_daily\n",
- "9 GITCOIN_MATCHING_funding_awarded_monthly\n",
- "10 GITCOIN_MATCHING_funding_awarded_over_all_time\n",
- "11 GITCOIN_MATCHING_funding_awarded_quarterly\n",
- "12 GITCOIN_MATCHING_funding_awarded_weekly\n",
- "13 GITCOIN_MATCHING_funding_awarded_yearly\n",
- "14 OPEN_COLLECTIVE_funding_received_biannually\n",
- "15 OPEN_COLLECTIVE_funding_received_daily\n",
- "16 OPEN_COLLECTIVE_funding_received_monthly\n",
- "17 OPEN_COLLECTIVE_funding_received_over_all_time\n",
- "18 OPEN_COLLECTIVE_funding_received_quarterly\n",
- "19 OPEN_COLLECTIVE_funding_received_weekly\n",
- "20 OPEN_COLLECTIVE_funding_received_yearly\n",
- "21 OSS_FUNDING_funding_awarded_biannually\n",
- "22 OSS_FUNDING_funding_awarded_daily\n",
- "23 OSS_FUNDING_funding_awarded_monthly\n",
- "24 OSS_FUNDING_funding_awarded_over_all_time\n",
- "25 OSS_FUNDING_funding_awarded_quarterly\n",
- "26 OSS_FUNDING_funding_awarded_weekly\n",
- "27 OSS_FUNDING_funding_awarded_yearly"
+ " metric_name\n",
+ "0 ARBITRUMFOUNDATION_funding_awarded_over_all_time\n",
+ "1 CLRFUND_funding_awarded_over_all_time\n",
+ "2 DAODROPS_funding_awarded_over_all_time\n",
+ "3 GITCOIN_DONATIONS_funding_awarded_biannually\n",
+ "4 GITCOIN_DONATIONS_funding_awarded_daily\n",
+ "5 GITCOIN_DONATIONS_funding_awarded_monthly\n",
+ "6 GITCOIN_DONATIONS_funding_awarded_over_all_time\n",
+ "7 GITCOIN_DONATIONS_funding_awarded_quarterly\n",
+ "8 GITCOIN_DONATIONS_funding_awarded_weekly\n",
+ "9 GITCOIN_DONATIONS_funding_awarded_yearly\n",
+ "10 GITCOIN_MATCHING_funding_awarded_biannually\n",
+ "11 GITCOIN_MATCHING_funding_awarded_daily\n",
+ "12 GITCOIN_MATCHING_funding_awarded_monthly\n",
+ "13 GITCOIN_MATCHING_funding_awarded_over_all_time\n",
+ "14 GITCOIN_MATCHING_funding_awarded_quarterly\n",
+ "15 GITCOIN_MATCHING_funding_awarded_weekly\n",
+ "16 GITCOIN_MATCHING_funding_awarded_yearly\n",
+ "17 OCTANT_funding_awarded_biannually\n",
+ "18 OCTANT_funding_awarded_over_all_time\n",
+ "19 OPEN_COLLECTIVE_funding_received_biannually\n",
+ "20 OPEN_COLLECTIVE_funding_received_daily\n",
+ "21 OPEN_COLLECTIVE_funding_received_monthly\n",
+ "22 OPEN_COLLECTIVE_funding_received_over_all_time\n",
+ "23 OPEN_COLLECTIVE_funding_received_quarterly\n",
+ "24 OPEN_COLLECTIVE_funding_received_weekly\n",
+ "25 OPEN_COLLECTIVE_funding_received_yearly\n",
+ "26 OPTIMISM_GOVGRANTS_funding_awarded_biannually\n",
+ "27 OPTIMISM_GOVGRANTS_funding_awarded_over_all_time\n",
+ "28 OPTIMISM_GOVGRANTS_funding_awarded_quarterly\n",
+ "29 OPTIMISM_RETROFUNDING_funding_awarded_biannually\n",
+ "30 OPTIMISM_RETROFUNDING_funding_awarded_daily\n",
+ "31 OPTIMISM_RETROFUNDING_funding_awarded_monthly\n",
+ "32 OPTIMISM_RETROFUNDING_funding_awarded_over_all...\n",
+ "33 OPTIMISM_RETROFUNDING_funding_awarded_quarterly\n",
+ "34 OPTIMISM_RETROFUNDING_funding_awarded_weekly\n",
+ "35 OSS_FUNDING_funding_awarded_biannually\n",
+ "36 OSS_FUNDING_funding_awarded_daily\n",
+ "37 OSS_FUNDING_funding_awarded_monthly\n",
+ "38 OSS_FUNDING_funding_awarded_quarterly\n",
+ "39 OSS_FUNDING_funding_awarded_weekly\n",
+ "40 OSS_FUNDING_funding_awarded_yearly\n",
+ "41 STELLAR_funding_awarded_biannually\n",
+ "42 STELLAR_funding_awarded_over_all_time"
]
},
"execution_count": 3,
@@ -287,28 +362,64 @@
" \n",
" \n",
" | 0 | \n",
- " OSS_FUNDING_funding_awarded_over_all_time | \n",
- " 364887873.600968 | \n",
+ " OPTIMISM_RETROFUNDING_funding_awarded_over_all... | \n",
+ " 138245667.349578 | \n",
"
\n",
" \n",
" | 1 | \n",
- " GITCOIN_MATCHING_funding_awarded_over_all_time | \n",
- " 13305117.158144 | \n",
+ " ARBITRUMFOUNDATION_funding_awarded_over_all_time | \n",
+ " 121538452.0 | \n",
"
\n",
" \n",
" | 2 | \n",
+ " OPTIMISM_GOVGRANTS_funding_awarded_over_all_time | \n",
+ " 101425950.39 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " STELLAR_funding_awarded_over_all_time | \n",
+ " 33517284.98 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " GITCOIN_MATCHING_funding_awarded_over_all_time | \n",
+ " 12743948.169964 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
" GITCOIN_DONATIONS_funding_awarded_over_all_time | \n",
- " 11666103.711711 | \n",
+ " 10897861.066639 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " OCTANT_funding_awarded_over_all_time | \n",
+ " 3871958.50952 | \n",
+ "
\n",
+ " \n",
+ " | 7 | \n",
+ " DAODROPS_funding_awarded_over_all_time | \n",
+ " 168634.0 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " CLRFUND_funding_awarded_over_all_time | \n",
+ " 55286.24013 | \n",
"
\n",
" \n",
"\n",
""
],
"text/plain": [
- " metric_name total_amount_in_usd\n",
- "0 OSS_FUNDING_funding_awarded_over_all_time 364887873.600968\n",
- "1 GITCOIN_MATCHING_funding_awarded_over_all_time 13305117.158144\n",
- "2 GITCOIN_DONATIONS_funding_awarded_over_all_time 11666103.711711"
+ " metric_name total_amount_in_usd\n",
+ "0 OPTIMISM_RETROFUNDING_funding_awarded_over_all... 138245667.349578\n",
+ "1 ARBITRUMFOUNDATION_funding_awarded_over_all_time 121538452.0\n",
+ "2 OPTIMISM_GOVGRANTS_funding_awarded_over_all_time 101425950.39\n",
+ "3 STELLAR_funding_awarded_over_all_time 33517284.98\n",
+ "4 GITCOIN_MATCHING_funding_awarded_over_all_time 12743948.169964\n",
+ "5 GITCOIN_DONATIONS_funding_awarded_over_all_time 10897861.066639\n",
+ "6 OCTANT_funding_awarded_over_all_time 3871958.50952\n",
+ "7 DAODROPS_funding_awarded_over_all_time 168634.0\n",
+ "8 CLRFUND_funding_awarded_over_all_time 55286.24013"
]
},
"execution_count": 4,
@@ -383,43 +494,43 @@
" \n",
" \n",
" | 2 | \n",
- " Synthetix | \n",
- " 10022628.074157 | \n",
+ " Velodrome | \n",
+ " 10836736.04374 | \n",
"
\n",
" \n",
" | 3 | \n",
- " Perpetual Protocol | \n",
- " 9287212.140718 | \n",
+ " Gains Network | \n",
+ " 7909635.9075 | \n",
"
\n",
" \n",
" | 4 | \n",
- " Gains Network | \n",
- " 7898396.135 | \n",
+ " Synthetix | \n",
+ " 7247628.074157 | \n",
"
\n",
" \n",
" | 5 | \n",
- " Velodrome | \n",
- " 7895037.76024 | \n",
+ " Camelot | \n",
+ " 5407500.0 | \n",
"
\n",
" \n",
" | 6 | \n",
- " Camelot | \n",
- " 5407500.0 | \n",
+ " Vertex Protocol | \n",
+ " 5250000.0 | \n",
"
\n",
" \n",
" | 7 | \n",
- " Stargate Finance | \n",
- " 5289458.865658 | \n",
+ " Radiant | \n",
+ " 4991077.0 | \n",
"
\n",
" \n",
" | 8 | \n",
- " Vertex Protocol | \n",
- " 5250000.0 | \n",
+ " Stargate Finance | \n",
+ " 4879172.708658 | \n",
"
\n",
" \n",
" | 9 | \n",
- " Radiant | \n",
- " 4991077.0 | \n",
+ " Perpetual Protocol | \n",
+ " 4787212.140718 | \n",
"
\n",
" \n",
"\n",
@@ -429,14 +540,14 @@
" project_display_name total_amount_in_usd\n",
"0 GMX 21000000.0\n",
"1 MUX Protocol 10876479.0\n",
- "2 Synthetix 10022628.074157\n",
- "3 Perpetual Protocol 9287212.140718\n",
- "4 Gains Network 7898396.135\n",
- "5 Velodrome 7895037.76024\n",
- "6 Camelot 5407500.0\n",
- "7 Stargate Finance 5289458.865658\n",
- "8 Vertex Protocol 5250000.0\n",
- "9 Radiant 4991077.0"
+ "2 Velodrome 10836736.04374\n",
+ "3 Gains Network 7909635.9075\n",
+ "4 Synthetix 7247628.074157\n",
+ "5 Camelot 5407500.0\n",
+ "6 Vertex Protocol 5250000.0\n",
+ "7 Radiant 4991077.0\n",
+ "8 Stargate Finance 4879172.708658\n",
+ "9 Perpetual Protocol 4787212.140718"
]
},
"execution_count": 5,
@@ -502,12 +613,12 @@
" \n",
" | 0 | \n",
" Gitcoin | \n",
- " 1099895.038376 | \n",
+ " 1040187.136146 | \n",
"
\n",
" \n",
" | 1 | \n",
" Revoke | \n",
- " 748859.365745 | \n",
+ " 748071.985745 | \n",
"
\n",
" \n",
" | 2 | \n",
@@ -536,35 +647,35 @@
"
\n",
" \n",
" | 7 | \n",
- " ethers.js | \n",
- " 190702.539836 | \n",
+ " rotki | \n",
+ " 159744.88374 | \n",
"
\n",
" \n",
" | 8 | \n",
- " rotki | \n",
- " 174990.340416 | \n",
+ " ethers.js | \n",
+ " 149548.961252 | \n",
"
\n",
" \n",
" | 9 | \n",
- " Taho | \n",
- " 170854.869607 | \n",
+ " Lighthouse by Sigma Prime | \n",
+ " 132816.547253 | \n",
"
\n",
" \n",
"\n",
""
],
"text/plain": [
- " project_display_name total_amount_in_usd\n",
- "0 Gitcoin 1099895.038376\n",
- "1 Revoke 748859.365745\n",
- "2 DefiLlama 429924.507285\n",
- "3 Hey 360529.24178\n",
- "4 JediSwap 333277.670918\n",
- "5 Dark Forest 332205.420888\n",
- "6 ZigZag Exchange 210175.931949\n",
- "7 ethers.js 190702.539836\n",
- "8 rotki 174990.340416\n",
- "9 Taho 170854.869607"
+ " project_display_name total_amount_in_usd\n",
+ "0 Gitcoin 1040187.136146\n",
+ "1 Revoke 748071.985745\n",
+ "2 DefiLlama 429924.507285\n",
+ "3 Hey 360529.24178\n",
+ "4 JediSwap 333277.670918\n",
+ "5 Dark Forest 332205.420888\n",
+ "6 ZigZag Exchange 210175.931949\n",
+ "7 rotki 159744.88374\n",
+ "8 ethers.js 149548.961252\n",
+ "9 Lighthouse by Sigma Prime 132816.547253"
]
},
"execution_count": 6,
@@ -716,6 +827,699 @@
"\"\"\")"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "105787d9-2cd7-49f5-883e-80fc7c904794",
+ "metadata": {},
+ "source": [
+ "### To/from funders (summary metrics)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "276f4c69-c824-4acc-b77f-8009e7719100",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " project_id | \n",
+ " display_name | \n",
+ " funding_source | \n",
+ " total_amount_in_usd | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " dNDkpiWWFxWM+fz0JbPapZpz/TlsoYQCJevD3ICcAHU= | \n",
+ " BOB | \n",
+ " OPTIMISM_GOVGRANTS | \n",
+ " 997500.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 8ranj8ZjbHqnVkAyhSNS9HAKO0VN/Tb34jZdBROI788= | \n",
+ " Mint Blockchain | \n",
+ " OPTIMISM_GOVGRANTS | \n",
+ " 997500.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " qnQ1PFj4fkRd6WPxzt5EHNykmTn5G/nYVvWkWjs0h0g= | \n",
+ " Revm | \n",
+ " OPTIMISM_RETROFUNDING | \n",
+ " 982507.285439 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " ZtwRwweUfJxkM3rtVoIfvvOaqHRc7CGlSCAKE8VgmN0= | \n",
+ " Aerodrome Finance | \n",
+ " OPTIMISM_RETROFUNDING | \n",
+ " 958989.311521 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " lPxNsS/BATP5VXf5oTGLri62s8Um5J+Rm9nMBX+wFV4= | \n",
+ " Lattice | \n",
+ " OPTIMISM_RETROFUNDING | \n",
+ " 958503.015 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 2256 | \n",
+ " 9FCd3zp3AhnThPkf6mxSbon88Co2iHmkcIfQAzdWbzc= | \n",
+ " Dasy | \n",
+ " GITCOIN_MATCHING | \n",
+ " 1010.41355 | \n",
+ "
\n",
+ " \n",
+ " | 2257 | \n",
+ " R1dwI8DtnoQytJHlZmQ2puJgGCi+M0Fs0/7nr58a5/o= | \n",
+ " DexKit | \n",
+ " GITCOIN_DONATIONS | \n",
+ " 1007.749109 | \n",
+ "
\n",
+ " \n",
+ " | 2258 | \n",
+ " Q8F6p4cN/9k6DpGmVYCcjZ67J1kV3bcJmPvDI5wwz2o= | \n",
+ " dippixyz | \n",
+ " GITCOIN_MATCHING | \n",
+ " 1001.623472 | \n",
+ "
\n",
+ " \n",
+ " | 2259 | \n",
+ " uQO9q9SKY+pM9SqxIQXR83uXfbOy9jh9K77n91nU6QA= | \n",
+ " RingsNetwork | \n",
+ " GITCOIN_MATCHING | \n",
+ " 1000.425276 | \n",
+ "
\n",
+ " \n",
+ " | 2260 | \n",
+ " GG7aTBIpNDjKMwi8e7O/vZfc+ai8cg9Xw5+CcnR1Ks0= | \n",
+ " Soroban Pre-Order Contract | \n",
+ " STELLAR | \n",
+ " 1000.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
2261 rows × 4 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " project_id \\\n",
+ "0 dNDkpiWWFxWM+fz0JbPapZpz/TlsoYQCJevD3ICcAHU= \n",
+ "1 8ranj8ZjbHqnVkAyhSNS9HAKO0VN/Tb34jZdBROI788= \n",
+ "2 qnQ1PFj4fkRd6WPxzt5EHNykmTn5G/nYVvWkWjs0h0g= \n",
+ "3 ZtwRwweUfJxkM3rtVoIfvvOaqHRc7CGlSCAKE8VgmN0= \n",
+ "4 lPxNsS/BATP5VXf5oTGLri62s8Um5J+Rm9nMBX+wFV4= \n",
+ "... ... \n",
+ "2256 9FCd3zp3AhnThPkf6mxSbon88Co2iHmkcIfQAzdWbzc= \n",
+ "2257 R1dwI8DtnoQytJHlZmQ2puJgGCi+M0Fs0/7nr58a5/o= \n",
+ "2258 Q8F6p4cN/9k6DpGmVYCcjZ67J1kV3bcJmPvDI5wwz2o= \n",
+ "2259 uQO9q9SKY+pM9SqxIQXR83uXfbOy9jh9K77n91nU6QA= \n",
+ "2260 GG7aTBIpNDjKMwi8e7O/vZfc+ai8cg9Xw5+CcnR1Ks0= \n",
+ "\n",
+ " display_name funding_source total_amount_in_usd \n",
+ "0 BOB OPTIMISM_GOVGRANTS 997500.0 \n",
+ "1 Mint Blockchain OPTIMISM_GOVGRANTS 997500.0 \n",
+ "2 Revm OPTIMISM_RETROFUNDING 982507.285439 \n",
+ "3 Aerodrome Finance OPTIMISM_RETROFUNDING 958989.311521 \n",
+ "4 Lattice OPTIMISM_RETROFUNDING 958503.015 \n",
+ "... ... ... ... \n",
+ "2256 Dasy GITCOIN_MATCHING 1010.41355 \n",
+ "2257 DexKit GITCOIN_DONATIONS 1007.749109 \n",
+ "2258 dippixyz GITCOIN_MATCHING 1001.623472 \n",
+ "2259 RingsNetwork GITCOIN_MATCHING 1000.425276 \n",
+ "2260 Soroban Pre-Order Contract STELLAR 1000.0 \n",
+ "\n",
+ "[2261 rows x 4 columns]"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = client.to_pandas(\"\"\"\n",
+ "SELECT\n",
+ " p.project_id,\n",
+ " p.display_name,\n",
+ " REPLACE(m.metric_name, '_funding_awarded_over_all_time', '') AS funding_source,\n",
+ " SUM(km.amount) AS total_amount_in_usd\n",
+ "FROM key_metrics_by_project_v0 AS km\n",
+ "JOIN metrics_v0 AS m ON km.metric_id = m.metric_id\n",
+ "JOIN projects_v1 AS p ON km.project_id = p.project_id\n",
+ "WHERE\n",
+ " m.metric_name LIKE '%_funding_awarded_over_all_time'\n",
+ " AND (km.amount >= 1000 AND km.amount < 1000000)\n",
+ "GROUP BY 1,2,3\n",
+ "ORDER BY 4 DESC\n",
+ "\"\"\")\n",
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "e326c245-5f20-4847-935b-9a05485f84a1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " from_funder | \n",
+ " display_name | \n",
+ " total_amount_in_usd | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 26 | \n",
+ " Optimism (Retro Funding) | \n",
+ " rotki | \n",
+ " 773567.405 | \n",
+ "
\n",
+ " \n",
+ " | 27 | \n",
+ " Optimism (Retro Funding) | \n",
+ " Giveth | \n",
+ " 763501.505973 | \n",
+ "
\n",
+ " \n",
+ " | 60 | \n",
+ " Optimism (Retro Funding) | \n",
+ " growthepie | \n",
+ " 591839.955 | \n",
+ "
\n",
+ " \n",
+ " | 107 | \n",
+ " Optimism (Retro Funding) | \n",
+ " The Metagovernance Project | \n",
+ " 445164.86 | \n",
+ "
\n",
+ " \n",
+ " | 112 | \n",
+ " Gitcoin (Matching) | \n",
+ " rotki | \n",
+ " 437212.315468 | \n",
+ "
\n",
+ " \n",
+ " | 165 | \n",
+ " Arbitrum STIP | \n",
+ " Tally | \n",
+ " 350000.0 | \n",
+ "
\n",
+ " \n",
+ " | 178 | \n",
+ " Optimism (Retro Funding) | \n",
+ " Tally | \n",
+ " 347827.48 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " Optimism (Retro Funding) | \n",
+ " Hypercerts | \n",
+ " 330436.12 | \n",
+ "
\n",
+ " \n",
+ " | 233 | \n",
+ " Optimism (Retro Funding) | \n",
+ " Praise | \n",
+ " 277324.575 | \n",
+ "
\n",
+ " \n",
+ " | 237 | \n",
+ " Optimism (Gov Grants) | \n",
+ " Tally | \n",
+ " 272000.0 | \n",
+ "
\n",
+ " \n",
+ " | 239 | \n",
+ " Optimism (Gov Grants) | \n",
+ " growthepie | \n",
+ " 271250.0 | \n",
+ "
\n",
+ " \n",
+ " | 253 | \n",
+ " Octant | \n",
+ " rotki | \n",
+ " 264978.05933 | \n",
+ "
\n",
+ " \n",
+ " | 261 | \n",
+ " Optimism (Retro Funding) | \n",
+ " BrightID | \n",
+ " 260870.61 | \n",
+ "
\n",
+ " \n",
+ " | 271 | \n",
+ " Octant | \n",
+ " Hypercerts | \n",
+ " 254595.53848 | \n",
+ "
\n",
+ " \n",
+ " | 316 | \n",
+ " Optimism (Gov Grants) | \n",
+ " The Metagovernance Project | \n",
+ " 218750.0 | \n",
+ "
\n",
+ " \n",
+ " | 347 | \n",
+ " Optimism (Gov Grants) | \n",
+ " Praise | \n",
+ " 196000.0 | \n",
+ "
\n",
+ " \n",
+ " | 416 | \n",
+ " Gitcoin (Matching) | \n",
+ " BrightID | \n",
+ " 167265.359323 | \n",
+ "
\n",
+ " \n",
+ " | 428 | \n",
+ " Octant | \n",
+ " growthepie | \n",
+ " 160926.51583 | \n",
+ "
\n",
+ " \n",
+ " | 431 | \n",
+ " Gitcoin (Donations) | \n",
+ " rotki | \n",
+ " 159744.88374 | \n",
+ "
\n",
+ " \n",
+ " | 440 | \n",
+ " Optimism (Gov Grants) | \n",
+ " rotki | \n",
+ " 155385.0 | \n",
+ "
\n",
+ " \n",
+ " | 470 | \n",
+ " Optimism (Gov Grants) | \n",
+ " Glo Dollar | \n",
+ " 150000.0 | \n",
+ "
\n",
+ " \n",
+ " | 600 | \n",
+ " Optimism (Gov Grants) | \n",
+ " Giveth | \n",
+ " 114000.0 | \n",
+ "
\n",
+ " \n",
+ " | 607 | \n",
+ " Gitcoin (Donations) | \n",
+ " BrightID | \n",
+ " 111565.008962 | \n",
+ "
\n",
+ " \n",
+ " | 661 | \n",
+ " Octant | \n",
+ " Praise | \n",
+ " 97426.29811 | \n",
+ "
\n",
+ " \n",
+ " | 676 | \n",
+ " Octant | \n",
+ " Giveth | \n",
+ " 93294.031 | \n",
+ "
\n",
+ " \n",
+ " | 681 | \n",
+ " Gitcoin (Matching) | \n",
+ " Giveth | \n",
+ " 90637.654801 | \n",
+ "
\n",
+ " \n",
+ " | 686 | \n",
+ " Optimism (Gov Grants) | \n",
+ " Hypercerts | \n",
+ " 90000.0 | \n",
+ "
\n",
+ " \n",
+ " | 750 | \n",
+ " Gitcoin (Matching) | \n",
+ " The Metagovernance Project | \n",
+ " 75029.406501 | \n",
+ "
\n",
+ " \n",
+ " | 802 | \n",
+ " Optimism (Gov Grants) | \n",
+ " MetaGame | \n",
+ " 67900.0 | \n",
+ "
\n",
+ " \n",
+ " | 866 | \n",
+ " Gitcoin (Matching) | \n",
+ " growthepie | \n",
+ " 52982.044628 | \n",
+ "
\n",
+ " \n",
+ " | 868 | \n",
+ " Gitcoin (Donations) | \n",
+ " Giveth | \n",
+ " 52791.595378 | \n",
+ "
\n",
+ " \n",
+ " | 915 | \n",
+ " Stellar Community Fund | \n",
+ " Giveth | \n",
+ " 50000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1025 | \n",
+ " Octant | \n",
+ " MetaGame | \n",
+ " 41578.274 | \n",
+ "
\n",
+ " \n",
+ " | 1045 | \n",
+ " Gitcoin (Donations) | \n",
+ " Hypercerts | \n",
+ " 39848.534911 | \n",
+ "
\n",
+ " \n",
+ " | 1127 | \n",
+ " Gitcoin (Matching) | \n",
+ " Glo Dollar | \n",
+ " 33483.098457 | \n",
+ "
\n",
+ " \n",
+ " | 1158 | \n",
+ " Gitcoin (Matching) | \n",
+ " Hypercerts | \n",
+ " 30929.104256 | \n",
+ "
\n",
+ " \n",
+ " | 1162 | \n",
+ " Gitcoin (Donations) | \n",
+ " The Metagovernance Project | \n",
+ " 30596.102733 | \n",
+ "
\n",
+ " \n",
+ " | 1240 | \n",
+ " Octant | \n",
+ " Glo Dollar | \n",
+ " 24511.97 | \n",
+ "
\n",
+ " \n",
+ " | 1320 | \n",
+ " DAO Drops | \n",
+ " Giveth | \n",
+ " 18186.0 | \n",
+ "
\n",
+ " \n",
+ " | 1439 | \n",
+ " Octant | \n",
+ " BrightID | \n",
+ " 13053.2 | \n",
+ "
\n",
+ " \n",
+ " | 1442 | \n",
+ " Stellar Community Fund | \n",
+ " Glo Dollar | \n",
+ " 13000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1499 | \n",
+ " DAO Drops | \n",
+ " MetaGame | \n",
+ " 11287.0 | \n",
+ "
\n",
+ " \n",
+ " | 1507 | \n",
+ " DAO Drops | \n",
+ " rotki | \n",
+ " 10863.0 | \n",
+ "
\n",
+ " \n",
+ " | 1511 | \n",
+ " Gitcoin (Donations) | \n",
+ " MetaGame | \n",
+ " 10676.413439 | \n",
+ "
\n",
+ " \n",
+ " | 1519 | \n",
+ " DAO Drops | \n",
+ " The Metagovernance Project | \n",
+ " 10439.0 | \n",
+ "
\n",
+ " \n",
+ " | 1660 | \n",
+ " Gitcoin (Matching) | \n",
+ " MetaGame | \n",
+ " 7134.340396 | \n",
+ "
\n",
+ " \n",
+ " | 1697 | \n",
+ " Gitcoin (Matching) | \n",
+ " Tally | \n",
+ " 6410.531839 | \n",
+ "
\n",
+ " \n",
+ " | 1703 | \n",
+ " Gitcoin (Donations) | \n",
+ " Glo Dollar | \n",
+ " 6292.656128 | \n",
+ "
\n",
+ " \n",
+ " | 1705 | \n",
+ " Octant | \n",
+ " The Metagovernance Project | \n",
+ " 6251.63472 | \n",
+ "
\n",
+ " \n",
+ " | 1733 | \n",
+ " Gitcoin (Donations) | \n",
+ " growthepie | \n",
+ " 5564.218084 | \n",
+ "
\n",
+ " \n",
+ " | 1753 | \n",
+ " DAO Drops | \n",
+ " Praise | \n",
+ " 5326.0 | \n",
+ "
\n",
+ " \n",
+ " | 1817 | \n",
+ " clr.fund | \n",
+ " BrightID | \n",
+ " 4256.110485 | \n",
+ "
\n",
+ " \n",
+ " | 1938 | \n",
+ " Gitcoin (Donations) | \n",
+ " Praise | \n",
+ " 2839.37634 | \n",
+ "
\n",
+ " \n",
+ " | 2058 | \n",
+ " Gitcoin (Matching) | \n",
+ " Praise | \n",
+ " 1902.041358 | \n",
+ "
\n",
+ " \n",
+ " | 2154 | \n",
+ " Gitcoin (Donations) | \n",
+ " Tally | \n",
+ " 1469.24948 | \n",
+ "
\n",
+ " \n",
+ " | 2163 | \n",
+ " clr.fund | \n",
+ " rotki | \n",
+ " 1416.561436 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " from_funder display_name \\\n",
+ "26 Optimism (Retro Funding) rotki \n",
+ "27 Optimism (Retro Funding) Giveth \n",
+ "60 Optimism (Retro Funding) growthepie \n",
+ "107 Optimism (Retro Funding) The Metagovernance Project \n",
+ "112 Gitcoin (Matching) rotki \n",
+ "165 Arbitrum STIP Tally \n",
+ "178 Optimism (Retro Funding) Tally \n",
+ "187 Optimism (Retro Funding) Hypercerts \n",
+ "233 Optimism (Retro Funding) Praise \n",
+ "237 Optimism (Gov Grants) Tally \n",
+ "239 Optimism (Gov Grants) growthepie \n",
+ "253 Octant rotki \n",
+ "261 Optimism (Retro Funding) BrightID \n",
+ "271 Octant Hypercerts \n",
+ "316 Optimism (Gov Grants) The Metagovernance Project \n",
+ "347 Optimism (Gov Grants) Praise \n",
+ "416 Gitcoin (Matching) BrightID \n",
+ "428 Octant growthepie \n",
+ "431 Gitcoin (Donations) rotki \n",
+ "440 Optimism (Gov Grants) rotki \n",
+ "470 Optimism (Gov Grants) Glo Dollar \n",
+ "600 Optimism (Gov Grants) Giveth \n",
+ "607 Gitcoin (Donations) BrightID \n",
+ "661 Octant Praise \n",
+ "676 Octant Giveth \n",
+ "681 Gitcoin (Matching) Giveth \n",
+ "686 Optimism (Gov Grants) Hypercerts \n",
+ "750 Gitcoin (Matching) The Metagovernance Project \n",
+ "802 Optimism (Gov Grants) MetaGame \n",
+ "866 Gitcoin (Matching) growthepie \n",
+ "868 Gitcoin (Donations) Giveth \n",
+ "915 Stellar Community Fund Giveth \n",
+ "1025 Octant MetaGame \n",
+ "1045 Gitcoin (Donations) Hypercerts \n",
+ "1127 Gitcoin (Matching) Glo Dollar \n",
+ "1158 Gitcoin (Matching) Hypercerts \n",
+ "1162 Gitcoin (Donations) The Metagovernance Project \n",
+ "1240 Octant Glo Dollar \n",
+ "1320 DAO Drops Giveth \n",
+ "1439 Octant BrightID \n",
+ "1442 Stellar Community Fund Glo Dollar \n",
+ "1499 DAO Drops MetaGame \n",
+ "1507 DAO Drops rotki \n",
+ "1511 Gitcoin (Donations) MetaGame \n",
+ "1519 DAO Drops The Metagovernance Project \n",
+ "1660 Gitcoin (Matching) MetaGame \n",
+ "1697 Gitcoin (Matching) Tally \n",
+ "1703 Gitcoin (Donations) Glo Dollar \n",
+ "1705 Octant The Metagovernance Project \n",
+ "1733 Gitcoin (Donations) growthepie \n",
+ "1753 DAO Drops Praise \n",
+ "1817 clr.fund BrightID \n",
+ "1938 Gitcoin (Donations) Praise \n",
+ "2058 Gitcoin (Matching) Praise \n",
+ "2154 Gitcoin (Donations) Tally \n",
+ "2163 clr.fund rotki \n",
+ "\n",
+ " total_amount_in_usd \n",
+ "26 773567.405 \n",
+ "27 763501.505973 \n",
+ "60 591839.955 \n",
+ "107 445164.86 \n",
+ "112 437212.315468 \n",
+ "165 350000.0 \n",
+ "178 347827.48 \n",
+ "187 330436.12 \n",
+ "233 277324.575 \n",
+ "237 272000.0 \n",
+ "239 271250.0 \n",
+ "253 264978.05933 \n",
+ "261 260870.61 \n",
+ "271 254595.53848 \n",
+ "316 218750.0 \n",
+ "347 196000.0 \n",
+ "416 167265.359323 \n",
+ "428 160926.51583 \n",
+ "431 159744.88374 \n",
+ "440 155385.0 \n",
+ "470 150000.0 \n",
+ "600 114000.0 \n",
+ "607 111565.008962 \n",
+ "661 97426.29811 \n",
+ "676 93294.031 \n",
+ "681 90637.654801 \n",
+ "686 90000.0 \n",
+ "750 75029.406501 \n",
+ "802 67900.0 \n",
+ "866 52982.044628 \n",
+ "868 52791.595378 \n",
+ "915 50000.0 \n",
+ "1025 41578.274 \n",
+ "1045 39848.534911 \n",
+ "1127 33483.098457 \n",
+ "1158 30929.104256 \n",
+ "1162 30596.102733 \n",
+ "1240 24511.97 \n",
+ "1320 18186.0 \n",
+ "1439 13053.2 \n",
+ "1442 13000.0 \n",
+ "1499 11287.0 \n",
+ "1507 10863.0 \n",
+ "1511 10676.413439 \n",
+ "1519 10439.0 \n",
+ "1660 7134.340396 \n",
+ "1697 6410.531839 \n",
+ "1703 6292.656128 \n",
+ "1705 6251.63472 \n",
+ "1733 5564.218084 \n",
+ "1753 5326.0 \n",
+ "1817 4256.110485 \n",
+ "1938 2839.37634 \n",
+ "2058 1902.041358 \n",
+ "2154 1469.24948 \n",
+ "2163 1416.561436 "
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "popular_projects = list(df.groupby('display_name')['funding_source'].nunique().sort_values(ascending=False).index[:10])\n",
+ "dff = df[df['display_name'].isin(popular_projects)].copy()\n",
+ "funder_names = {\n",
+ " 'OPTIMISM_RETROFUNDING': 'Optimism (Retro Funding)',\n",
+ " 'GITCOIN_MATCHING': 'Gitcoin (Matching)',\n",
+ " 'ARBITRUMFOUNDATION': 'Arbitrum STIP',\n",
+ " 'OPTIMISM_GOVGRANTS': 'Optimism (Gov Grants)',\n",
+ " 'OCTANT': 'Octant', \n",
+ " 'GITCOIN_DONATIONS': 'Gitcoin (Donations)', \n",
+ " 'STELLAR': 'Stellar Community Fund', \n",
+ " 'DAODROPS': 'DAO Drops', \n",
+ " 'CLRFUND': 'clr.fund'\n",
+ "}\n",
+ "dff['from_funder'] = dff['funding_source'].map(funder_names)\n",
+ "dff = dff[['from_funder', 'display_name', 'total_amount_in_usd']]\n",
+ "dff"
+ ]
+ },
{
"cell_type": "markdown",
"id": "fe5ad20c-7772-4e94-83ec-77baea215d00",
@@ -730,7 +1534,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 10,
"id": "60aa05c7-098f-4e6f-8183-a01fc5ed9652",
"metadata": {},
"outputs": [
@@ -896,7 +1700,7 @@
"9 537.338562 "
]
},
- "execution_count": 8,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -929,7 +1733,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 11,
"id": "fa50c103-7c3c-4fb2-bcb1-ff754a8b53f6",
"metadata": {},
"outputs": [
@@ -963,8 +1767,8 @@
" \n",
" | 0 | \n",
" optimism | \n",
- " 12 | \n",
- " 240450291.744 | \n",
+ " 15 | \n",
+ " 275923907.037501 | \n",
"
\n",
" \n",
" | 1 | \n",
@@ -976,7 +1780,7 @@
" 2 | \n",
" stellar | \n",
" 29 | \n",
- " 32989032.98 | \n",
+ " 33589282.98 | \n",
"
\n",
" \n",
" | 3 | \n",
@@ -1001,16 +1805,16 @@
""
],
"text/plain": [
- " from_funder_name grant_pools amount_in_usd\n",
- "0 optimism 12 240450291.744\n",
- "1 arbitrumfoundation 1 122850952.0\n",
- "2 stellar 29 32989032.98\n",
- "3 octant-golemfoundation 5 3965429.51329\n",
- "4 dao-drops-dorgtech 1 250001.0\n",
- "5 clrfund 1 83028.740386"
+ " from_funder_name grant_pools amount_in_usd\n",
+ "0 optimism 15 275923907.037501\n",
+ "1 arbitrumfoundation 1 122850952.0\n",
+ "2 stellar 29 33589282.98\n",
+ "3 octant-golemfoundation 5 3965429.51329\n",
+ "4 dao-drops-dorgtech 1 250001.0\n",
+ "5 clrfund 1 83028.740386"
]
},
- "execution_count": 9,
+ "execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
@@ -1039,7 +1843,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 12,
"id": "1bd3a7a8-8cac-420e-9e7b-5259ff0e3b2d",
"metadata": {},
"outputs": [
@@ -1073,44 +1877,44 @@
" \n",
"
\n",
" \n",
- " | 2142 | \n",
+ " 2249 | \n",
" Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= | \n",
- " 8IKXraxq1pDuQD1xaDI20cjFrel55TZ/zf6LmP69qEg= | \n",
+ " 1rc31e43WnXR31VM//z41gY2UFQfbo2b8KCwLw0rY4k= | \n",
" Gitcoin | \n",
- " efdevcon | \n",
- " 13.531599 | \n",
+ " rantomdotapp | \n",
+ " 6131.318222 | \n",
"
\n",
" \n",
- " | 2143 | \n",
+ " 2250 | \n",
" Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= | \n",
- " 79HQoZtyZftibazh6Yz63aU06XODWs7b/9h4JAqPa1s= | \n",
+ " DRZVxhlH8Qia/HQsZTqIe+hZVn/I0wjhgSpHqcNn0RE= | \n",
" Gitcoin | \n",
- " LexDAO | \n",
- " 86499.728685 | \n",
+ " eggcess-tech | \n",
+ " 115.038641 | \n",
"
\n",
" \n",
- " | 2144 | \n",
- " 5Fgf9xv3CxTV+YbSShdY9XCJs7tgW8KNwQWq9rHUEsQ= | \n",
- " 79HQoZtyZftibazh6Yz63aU06XODWs7b/9h4JAqPa1s= | \n",
- " clr.fund | \n",
- " LexDAO | \n",
- " 193.952856 | \n",
+ " 2251 | \n",
+ " ta+k40iL4Aishk458IqTS4k+jcGiSCdYzpwaDPfKqss= | \n",
+ " GFtPmpIWk2qUtklRVLF1k8VATmNH+3bHG4CA8iOfuxA= | \n",
+ " Optimism | \n",
+ " Yearn | \n",
+ " 1597827.48 | \n",
"
\n",
" \n",
- " | 2145 | \n",
- " Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= | \n",
- " yEebFy4M1iAdb9+YQmdssSx9Qf+ZXfSVguL/JyidngI= | \n",
- " Gitcoin | \n",
- " DeFiEye | \n",
- " 224058.115245 | \n",
+ " 2252 | \n",
+ " IW0dZPkUh9+SEfZy8z8Om57ZGyjR3ZmSWkeojs9qnbU= | \n",
+ " rU5cF8xxSnfmw0tq9VCl33LJXFCXqQVzqAWnWN9iWnw= | \n",
+ " Arbitrum Foundation | \n",
+ " Synapse | \n",
+ " 3500000.0 | \n",
"
\n",
" \n",
- " | 2146 | \n",
- " 5Fgf9xv3CxTV+YbSShdY9XCJs7tgW8KNwQWq9rHUEsQ= | \n",
- " JQtLQErRk0u41xS292Cg+s3cRr8LaD5lQ2kME/Syp2Q= | \n",
- " clr.fund | \n",
- " Asilo Digital | \n",
- " 703.639308 | \n",
+ " 2253 | \n",
+ " ta+k40iL4Aishk458IqTS4k+jcGiSCdYzpwaDPfKqss= | \n",
+ " rU5cF8xxSnfmw0tq9VCl33LJXFCXqQVzqAWnWN9iWnw= | \n",
+ " Optimism | \n",
+ " Synapse | \n",
+ " 849991.175282 | \n",
"
\n",
" \n",
"\n",
@@ -1118,28 +1922,28 @@
],
"text/plain": [
" from_project_id \\\n",
- "2142 Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= \n",
- "2143 Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= \n",
- "2144 5Fgf9xv3CxTV+YbSShdY9XCJs7tgW8KNwQWq9rHUEsQ= \n",
- "2145 Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= \n",
- "2146 5Fgf9xv3CxTV+YbSShdY9XCJs7tgW8KNwQWq9rHUEsQ= \n",
+ "2249 Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= \n",
+ "2250 Qgbm336fY9862LN2Czg3UX04A3p7I/79Bv2M4D61DAI= \n",
+ "2251 ta+k40iL4Aishk458IqTS4k+jcGiSCdYzpwaDPfKqss= \n",
+ "2252 IW0dZPkUh9+SEfZy8z8Om57ZGyjR3ZmSWkeojs9qnbU= \n",
+ "2253 ta+k40iL4Aishk458IqTS4k+jcGiSCdYzpwaDPfKqss= \n",
"\n",
- " to_project_id funder project \\\n",
- "2142 8IKXraxq1pDuQD1xaDI20cjFrel55TZ/zf6LmP69qEg= Gitcoin efdevcon \n",
- "2143 79HQoZtyZftibazh6Yz63aU06XODWs7b/9h4JAqPa1s= Gitcoin LexDAO \n",
- "2144 79HQoZtyZftibazh6Yz63aU06XODWs7b/9h4JAqPa1s= clr.fund LexDAO \n",
- "2145 yEebFy4M1iAdb9+YQmdssSx9Qf+ZXfSVguL/JyidngI= Gitcoin DeFiEye \n",
- "2146 JQtLQErRk0u41xS292Cg+s3cRr8LaD5lQ2kME/Syp2Q= clr.fund Asilo Digital \n",
+ " to_project_id funder \\\n",
+ "2249 1rc31e43WnXR31VM//z41gY2UFQfbo2b8KCwLw0rY4k= Gitcoin \n",
+ "2250 DRZVxhlH8Qia/HQsZTqIe+hZVn/I0wjhgSpHqcNn0RE= Gitcoin \n",
+ "2251 GFtPmpIWk2qUtklRVLF1k8VATmNH+3bHG4CA8iOfuxA= Optimism \n",
+ "2252 rU5cF8xxSnfmw0tq9VCl33LJXFCXqQVzqAWnWN9iWnw= Arbitrum Foundation \n",
+ "2253 rU5cF8xxSnfmw0tq9VCl33LJXFCXqQVzqAWnWN9iWnw= Optimism \n",
"\n",
- " amount \n",
- "2142 13.531599 \n",
- "2143 86499.728685 \n",
- "2144 193.952856 \n",
- "2145 224058.115245 \n",
- "2146 703.639308 "
+ " project amount \n",
+ "2249 rantomdotapp 6131.318222 \n",
+ "2250 eggcess-tech 115.038641 \n",
+ "2251 Yearn 1597827.48 \n",
+ "2252 Synapse 3500000.0 \n",
+ "2253 Synapse 849991.175282 "
]
},
- "execution_count": 10,
+ "execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}