Buckets:
| import{s as je,o as Ue}from"../chunks/scheduler.37c15a92.js";import{S as xe,i as $e,g as y,s as o,r as J,A as we,h as g,f as a,c as m,j as ge,u as T,x as w,k as le,y as _e,a as r,v as k,t as f,b as Je,d as h,w as j,m as Ze,n as ve,p as Te}from"../chunks/index.2bf4358c.js";import{T as Ce}from"../chunks/Tip.363c041f.js";import{C as G}from"../chunks/CodeBlock.4e987730.js";import{C as ke}from"../chunks/CourseFloatingBanner.6add7356.js";import{F as We}from"../chunks/FrameworkSwitchCourse.8d4d4ab6.js";import{H as Ve,E as Ne}from"../chunks/getInferenceSnippets.ebf8be91.js";function ze(M){let t,i;return t=new ke({props:{chapter:4,classNames:"absolute z-10 right-0 top-0",notebooks:[{label:"English",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/en/chapter4/section2_tf.ipynb"},{label:"Français",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/fr/chapter4/section2_tf.ipynb"},{label:"English",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter4/section2_tf.ipynb"},{label:"Français",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/fr/chapter4/section2_tf.ipynb"}]}}),{c(){J(t.$$.fragment)},l(l){T(t.$$.fragment,l)},m(l,d){k(t,l,d),i=!0},i(l){i||(h(t.$$.fragment,l),i=!0)},o(l){f(t.$$.fragment,l),i=!1},d(l){j(t,l)}}}function Ee(M){let t,i;return t=new ke({props:{chapter:4,classNames:"absolute z-10 right-0 top-0",notebooks:[{label:"English",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/en/chapter4/section2_pt.ipynb"},{label:"Français",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/fr/chapter4/section2_pt.ipynb"},{label:"English",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter4/section2_pt.ipynb"},{label:"Français",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/fr/chapter4/section2_pt.ipynb"}]}}),{c(){J(t.$$.fragment)},l(l){T(t.$$.fragment,l)},m(l,d){k(t,l,d),i=!0},i(l){i||(h(t.$$.fragment,l),i=!0)},o(l){f(t.$$.fragment,l),i=!1},d(l){j(t,l)}}}function Fe(M){let t,i,l,d='Cependant, nous recommandons d’utiliser les classes <a href="https://huggingface.co/transformers/model_doc/auto.html?highlight=auto#auto-classes" rel="nofollow"><code>TFAuto*</code></a> à la place, car elles sont par conception indépendantes de l’architecture. Alors que l’exemple de code précédent limite les utilisateurs aux <em>checkpoints</em> chargeables dans l’architecture CamemBERT, l’utilisation des classes <code>TFAuto*</code> facilite le changement de <em>checkpoint</em> :',u,p,b;return t=new G({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMENhbWVtYmVydFRva2VuaXplciUyQyUyMFRGQ2FtZW1iZXJ0Rm9yTWFza2VkTE0lMEElMEF0b2tlbml6ZXIlMjAlM0QlMjBDYW1lbWJlcnRUb2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkKCUyMmNhbWVtYmVydC1iYXNlJTIyKSUwQW1vZGVsJTIwJTNEJTIwVEZDYW1lbWJlcnRGb3JNYXNrZWRMTS5mcm9tX3ByZXRyYWluZWQoJTIyY2FtZW1iZXJ0LWJhc2UlMjIp",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> CamembertTokenizer, TFCamembertForMaskedLM | |
| tokenizer = CamembertTokenizer.from_pretrained(<span class="hljs-string">"camembert-base"</span>) | |
| model = TFCamembertForMaskedLM.from_pretrained(<span class="hljs-string">"camembert-base"</span>)`,wrap:!1}}),p=new G({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMEF1dG9Ub2tlbml6ZXIlMkMlMjBURkF1dG9Nb2RlbEZvck1hc2tlZExNJTBBJTBBdG9rZW5pemVyJTIwJTNEJTIwQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQoJTIyY2FtZW1iZXJ0LWJhc2UlMjIpJTBBbW9kZWwlMjAlM0QlMjBURkF1dG9Nb2RlbEZvck1hc2tlZExNLmZyb21fcHJldHJhaW5lZCglMjJjYW1lbWJlcnQtYmFzZSUyMik=",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoTokenizer, TFAutoModelForMaskedLM | |
| tokenizer = AutoTokenizer.from_pretrained(<span class="hljs-string">"camembert-base"</span>) | |
| model = TFAutoModelForMaskedLM.from_pretrained(<span class="hljs-string">"camembert-base"</span>)`,wrap:!1}}),{c(){J(t.$$.fragment),i=o(),l=y("p"),l.innerHTML=d,u=o(),J(p.$$.fragment)},l(s){T(t.$$.fragment,s),i=m(s),l=g(s,"P",{"data-svelte-h":!0}),w(l)!=="svelte-83gnjn"&&(l.innerHTML=d),u=m(s),T(p.$$.fragment,s)},m(s,c){k(t,s,c),r(s,i,c),r(s,l,c),r(s,u,c),k(p,s,c),b=!0},i(s){b||(h(t.$$.fragment,s),h(p.$$.fragment,s),b=!0)},o(s){f(t.$$.fragment,s),f(p.$$.fragment,s),b=!1},d(s){s&&(a(i),a(l),a(u)),j(t,s),j(p,s)}}}function Qe(M){let t,i,l,d='Cependant, nous recommandons d’utiliser les classes <a href="https://huggingface.co/transformers/model_doc/auto.html?highlight=auto#auto-classes" rel="nofollow"><code>Auto*</code></a> à la place, car elles sont par conception indépendantes de l’architecture. Alors que l’exemple de code précédent limite les utilisateurs aux <em>checkpoints</em> chargeables dans l’architecture CamemBERT, l’utilisation des classes <code>Auto*</code> facilite le changement de <em>checkpoint</em> :',u,p,b;return t=new G({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMENhbWVtYmVydFRva2VuaXplciUyQyUyMENhbWVtYmVydEZvck1hc2tlZExNJTBBJTBBdG9rZW5pemVyJTIwJTNEJTIwQ2FtZW1iZXJ0VG9rZW5pemVyLmZyb21fcHJldHJhaW5lZCglMjJjYW1lbWJlcnQtYmFzZSUyMiklMEFtb2RlbCUyMCUzRCUyMENhbWVtYmVydEZvck1hc2tlZExNLmZyb21fcHJldHJhaW5lZCglMjJjYW1lbWJlcnQtYmFzZSUyMik=",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> CamembertTokenizer, CamembertForMaskedLM | |
| tokenizer = CamembertTokenizer.from_pretrained(<span class="hljs-string">"camembert-base"</span>) | |
| model = CamembertForMaskedLM.from_pretrained(<span class="hljs-string">"camembert-base"</span>)`,wrap:!1}}),p=new G({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMEF1dG9Ub2tlbml6ZXIlMkMlMjBBdXRvTW9kZWxGb3JNYXNrZWRMTSUwQSUwQXRva2VuaXplciUyMCUzRCUyMEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkKCUyMmNhbWVtYmVydC1iYXNlJTIyKSUwQW1vZGVsJTIwJTNEJTIwQXV0b01vZGVsRm9yTWFza2VkTE0uZnJvbV9wcmV0cmFpbmVkKCUyMmNhbWVtYmVydC1iYXNlJTIyKQ==",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoTokenizer, AutoModelForMaskedLM | |
| tokenizer = AutoTokenizer.from_pretrained(<span class="hljs-string">"camembert-base"</span>) | |
| model = AutoModelForMaskedLM.from_pretrained(<span class="hljs-string">"camembert-base"</span>)`,wrap:!1}}),{c(){J(t.$$.fragment),i=o(),l=y("p"),l.innerHTML=d,u=o(),J(p.$$.fragment)},l(s){T(t.$$.fragment,s),i=m(s),l=g(s,"P",{"data-svelte-h":!0}),w(l)!=="svelte-8qvpr"&&(l.innerHTML=d),u=m(s),T(p.$$.fragment,s)},m(s,c){k(t,s,c),r(s,i,c),r(s,l,c),r(s,u,c),k(p,s,c),b=!0},i(s){b||(h(t.$$.fragment,s),h(p.$$.fragment,s),b=!0)},o(s){f(t.$$.fragment,s),f(p.$$.fragment,s),b=!1},d(s){s&&(a(i),a(l),a(u)),j(t,s),j(p,s)}}}function Be(M){let t;return{c(){t=Ze("Lorsque vous utilisez un modèle pré-entraîné, assurez-vous de vérifier comment il a été entraîné, sur quels jeux de données, ses limites et ses biais. Toutes ces informations doivent être indiquées dans sa carte.")},l(i){t=ve(i,"Lorsque vous utilisez un modèle pré-entraîné, assurez-vous de vérifier comment il a été entraîné, sur quels jeux de données, ses limites et ses biais. Toutes ces informations doivent être indiquées dans sa carte.")},m(i,l){r(i,t,l)},d(i){i&&a(t)}}}function Ie(M){let t,i,l,d,u,p,b,s,c,U,Y,C,re="Le <em>Hub</em> rend simple la sélection d’un modèle et permet alors que celui-ci puisse être utilisé dans toute bibliothèque en aval en seulement quelques lignes de code. Voyons comment utiliser concrètement l’un de ces modèles et comment contribuer au développement de la communauté.",X,W,ie="Supposons que nous recherchions un modèle basé sur le français, capable de remplir des masques.",L,_,ce='<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/camembert.gif" alt="Selecting the Camembert model." width="80%"/>',R,V,oe="Nous choisissons le <em>checkpoint</em> <code>camembert-base</code> pour essayer. L’identifiant <code>camembert-base</code> est tout ce dont nous avons besoin pour commencer à utiliser le modèle ! Comme vous l’avez vu dans les chapitres précédents, nous pouvons l’instancier en utilisant la fonction <code>pipeline()</code> :",S,N,H,z,D,E,me="Comme vous pouvez le constater, le chargement d’un modèle dans un pipeline est extrêmement simple. La seule chose à laquelle vous devez faire attention est que le <em>checkpoint</em> choisi soit adapté à la tâche pour laquelle il va être utilisé. Par exemple, ici nous chargeons le <em>checkpoint</em> <code>camembert-base</code> dans le pipeline <code>fill-mask</code>, ce qui est tout à fait correct. Mais si nous chargerions ce <em>checkpoint</em> dans le pipeline <code>text-classification</code>, les résultats n’auraient aucun sens car la tête de <code>camembert-base</code> n’est pas adaptée à cette tâche ! Nous recommandons d’utiliser le sélecteur de tâche dans l’interface du <em>Hub</em> afin de sélectionner les <em>checkpoints</em> appropriés :",P,Z,pe='<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/tasks.png" alt="The task selector on the web interface." width="80%"/>',K,F,ue="Vous pouvez également instancier le <em>checkpoint</em> en utilisant directement l’architecture du modèle :",O,x,$,q,v,ee,Q,se,A,te;u=new We({props:{fw:M[0]}}),b=new Ve({props:{title:"Utilisation de modèles pré-entraînés",local:"utilisation-de-modèles-pré-entraînés",headingTag:"h1"}});const be=[Ee,ze],B=[];function de(e,n){return e[0]==="pt"?0:1}c=de(M),U=B[c]=be[c](M),N=new G({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMHBpcGVsaW5lJTBBJTBBY2FtZW1iZXJ0X2ZpbGxfbWFzayUyMCUzRCUyMHBpcGVsaW5lKCUyMmZpbGwtbWFzayUyMiUyQyUyMG1vZGVsJTNEJTIyY2FtZW1iZXJ0LWJhc2UlMjIpJTBBcmVzdWx0cyUyMCUzRCUyMGNhbWVtYmVydF9maWxsX21hc2soJTIyTGUlMjBjYW1lbWJlcnQlMjBlc3QlMjAlM0NtYXNrJTNFJTIwJTNBKSUyMik=",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline | |
| camembert_fill_mask = pipeline(<span class="hljs-string">"fill-mask"</span>, model=<span class="hljs-string">"camembert-base"</span>) | |
| results = camembert_fill_mask(<span class="hljs-string">"Le camembert est <mask> :)"</span>)`,wrap:!1}}),z=new G({props:{code:"JTVCJTBBJTIwJTIwJTdCJ3NlcXVlbmNlJyUzQSUyMCdMZSUyMGNhbWVtYmVydCUyMGVzdCUyMGQlQzMlQTlsaWNpZXV4JTIwJTNBKSclMkMlMjAnc2NvcmUnJTNBJTIwMC40OTA5MTAwNTMyNTMxNzM4MyUyQyUyMCd0b2tlbiclM0ElMjA3MjAwJTJDJTIwJ3Rva2VuX3N0ciclM0ElMjAnZCVDMyVBOWxpY2lldXgnJTdEJTJDJTIwJTBBJTIwJTIwJTdCJ3NlcXVlbmNlJyUzQSUyMCdMZSUyMGNhbWVtYmVydCUyMGVzdCUyMGV4Y2VsbGVudCUyMCUzQSknJTJDJTIwJ3Njb3JlJyUzQSUyMDAuMTA1NTY5NzQyNjE5OTkxMyUyQyUyMCd0b2tlbiclM0ElMjAyMTgzJTJDJTIwJ3Rva2VuX3N0ciclM0ElMjAnZXhjZWxsZW50JyU3RCUyQyUyMCUwQSUyMCUyMCU3QidzZXF1ZW5jZSclM0ElMjAnTGUlMjBjYW1lbWJlcnQlMjBlc3QlMjBzdWNjdWxlbnQlMjAlM0EpJyUyQyUyMCdzY29yZSclM0ElMjAwLjAzNDUzMzEzMTg2NzY0NzE3JTJDJTIwJ3Rva2VuJyUzQSUyMDI2MjAyJTJDJTIwJ3Rva2VuX3N0ciclM0ElMjAnc3VjY3VsZW50JyU3RCUyQyUyMCUwQSUyMCUyMCU3QidzZXF1ZW5jZSclM0ElMjAnTGUlMjBjYW1lbWJlcnQlMjBlc3QlMjBtZWlsbGV1ciUyMCUzQSknJTJDJTIwJ3Njb3JlJyUzQSUyMDAuMDMzMDMxNDExNDY4OTgyNyUyQyUyMCd0b2tlbiclM0ElMjA1MjglMkMlMjAndG9rZW5fc3RyJyUzQSUyMCdtZWlsbGV1ciclN0QlMkMlMjAlMEElMjAlMjAlN0Inc2VxdWVuY2UnJTNBJTIwJ0xlJTIwY2FtZW1iZXJ0JTIwZXN0JTIwcGFyZmFpdCUyMCUzQSknJTJDJTIwJ3Njb3JlJyUzQSUyMDAuMDMwMDc2NTAxODkxMDE2OTYlMkMlMjAndG9rZW4nJTNBJTIwMTY1NCUyQyUyMCd0b2tlbl9zdHInJTNBJTIwJ3BhcmZhaXQnJTdEJTBBJTVE",highlighted:`[ | |
| {<span class="hljs-string">'sequence'</span>: <span class="hljs-string">'Le camembert est délicieux :)'</span>, <span class="hljs-string">'score'</span>: <span class="hljs-number">0.49091005325317383</span>, <span class="hljs-string">'token'</span>: <span class="hljs-number">7200</span>, <span class="hljs-string">'token_str'</span>: <span class="hljs-string">'délicieux'</span>}, | |
| {<span class="hljs-string">'sequence'</span>: <span class="hljs-string">'Le camembert est excellent :)'</span>, <span class="hljs-string">'score'</span>: <span class="hljs-number">0.1055697426199913</span>, <span class="hljs-string">'token'</span>: <span class="hljs-number">2183</span>, <span class="hljs-string">'token_str'</span>: <span class="hljs-string">'excellent'</span>}, | |
| {<span class="hljs-string">'sequence'</span>: <span class="hljs-string">'Le camembert est succulent :)'</span>, <span class="hljs-string">'score'</span>: <span class="hljs-number">0.03453313186764717</span>, <span class="hljs-string">'token'</span>: <span class="hljs-number">26202</span>, <span class="hljs-string">'token_str'</span>: <span class="hljs-string">'succulent'</span>}, | |
| {<span class="hljs-string">'sequence'</span>: <span class="hljs-string">'Le camembert est meilleur :)'</span>, <span class="hljs-string">'score'</span>: <span class="hljs-number">0.0330314114689827</span>, <span class="hljs-string">'token'</span>: <span class="hljs-number">528</span>, <span class="hljs-string">'token_str'</span>: <span class="hljs-string">'meilleur'</span>}, | |
| {<span class="hljs-string">'sequence'</span>: <span class="hljs-string">'Le camembert est parfait :)'</span>, <span class="hljs-string">'score'</span>: <span class="hljs-number">0.03007650189101696</span>, <span class="hljs-string">'token'</span>: <span class="hljs-number">1654</span>, <span class="hljs-string">'token_str'</span>: <span class="hljs-string">'parfait'</span>} | |
| ]`,wrap:!1}});const fe=[Qe,Fe],I=[];function he(e,n){return e[0]==="pt"?0:1}return x=he(M),$=I[x]=fe[x](M),v=new Ce({props:{$$slots:{default:[Be]},$$scope:{ctx:M}}}),Q=new Ne({props:{source:"https://github.com/huggingface/course/blob/main/chapters/fr/chapter4/2.mdx"}}),{c(){t=y("meta"),i=o(),l=y("p"),d=o(),J(u.$$.fragment),p=o(),J(b.$$.fragment),s=o(),U.c(),Y=o(),C=y("p"),C.innerHTML=re,X=o(),W=y("p"),W.textContent=ie,L=o(),_=y("div"),_.innerHTML=ce,R=o(),V=y("p"),V.innerHTML=oe,S=o(),J(N.$$.fragment),H=o(),J(z.$$.fragment),D=o(),E=y("p"),E.innerHTML=me,P=o(),Z=y("div"),Z.innerHTML=pe,K=o(),F=y("p"),F.innerHTML=ue,O=o(),$.c(),q=o(),J(v.$$.fragment),ee=o(),J(Q.$$.fragment),se=o(),A=y("p"),this.h()},l(e){const n=we("svelte-u9bgzb",document.head);t=g(n,"META",{name:!0,content:!0}),n.forEach(a),i=m(e),l=g(e,"P",{}),ge(l).forEach(a),d=m(e),T(u.$$.fragment,e),p=m(e),T(b.$$.fragment,e),s=m(e),U.l(e),Y=m(e),C=g(e,"P",{"data-svelte-h":!0}),w(C)!=="svelte-14ptojn"&&(C.innerHTML=re),X=m(e),W=g(e,"P",{"data-svelte-h":!0}),w(W)!=="svelte-1263zlh"&&(W.textContent=ie),L=m(e),_=g(e,"DIV",{class:!0,"data-svelte-h":!0}),w(_)!=="svelte-4k6hvy"&&(_.innerHTML=ce),R=m(e),V=g(e,"P",{"data-svelte-h":!0}),w(V)!=="svelte-1h6aycb"&&(V.innerHTML=oe),S=m(e),T(N.$$.fragment,e),H=m(e),T(z.$$.fragment,e),D=m(e),E=g(e,"P",{"data-svelte-h":!0}),w(E)!=="svelte-1o379vp"&&(E.innerHTML=me),P=m(e),Z=g(e,"DIV",{class:!0,"data-svelte-h":!0}),w(Z)!=="svelte-1cl7xbt"&&(Z.innerHTML=pe),K=m(e),F=g(e,"P",{"data-svelte-h":!0}),w(F)!=="svelte-1x0kbto"&&(F.innerHTML=ue),O=m(e),$.l(e),q=m(e),T(v.$$.fragment,e),ee=m(e),T(Q.$$.fragment,e),se=m(e),A=g(e,"P",{}),ge(A).forEach(a),this.h()},h(){le(t,"name","hf:doc:metadata"),le(t,"content",Ye),le(_,"class","flex justify-center"),le(Z,"class","flex justify-center")},m(e,n){_e(document.head,t),r(e,i,n),r(e,l,n),r(e,d,n),k(u,e,n),r(e,p,n),k(b,e,n),r(e,s,n),B[c].m(e,n),r(e,Y,n),r(e,C,n),r(e,X,n),r(e,W,n),r(e,L,n),r(e,_,n),r(e,R,n),r(e,V,n),r(e,S,n),k(N,e,n),r(e,H,n),k(z,e,n),r(e,D,n),r(e,E,n),r(e,P,n),r(e,Z,n),r(e,K,n),r(e,F,n),r(e,O,n),I[x].m(e,n),r(e,q,n),k(v,e,n),r(e,ee,n),k(Q,e,n),r(e,se,n),r(e,A,n),te=!0},p(e,[n]){const Me={};n&1&&(Me.fw=e[0]),u.$set(Me);let ne=c;c=de(e),c!==ne&&(Te(),f(B[ne],1,1,()=>{B[ne]=null}),Je(),U=B[c],U||(U=B[c]=be[c](e),U.c()),h(U,1),U.m(Y.parentNode,Y));let ae=x;x=he(e),x!==ae&&(Te(),f(I[ae],1,1,()=>{I[ae]=null}),Je(),$=I[x],$||($=I[x]=fe[x](e),$.c()),h($,1),$.m(q.parentNode,q));const ye={};n&2&&(ye.$$scope={dirty:n,ctx:e}),v.$set(ye)},i(e){te||(h(u.$$.fragment,e),h(b.$$.fragment,e),h(U),h(N.$$.fragment,e),h(z.$$.fragment,e),h($),h(v.$$.fragment,e),h(Q.$$.fragment,e),te=!0)},o(e){f(u.$$.fragment,e),f(b.$$.fragment,e),f(U),f(N.$$.fragment,e),f(z.$$.fragment,e),f($),f(v.$$.fragment,e),f(Q.$$.fragment,e),te=!1},d(e){e&&(a(i),a(l),a(d),a(p),a(s),a(Y),a(C),a(X),a(W),a(L),a(_),a(R),a(V),a(S),a(H),a(D),a(E),a(P),a(Z),a(K),a(F),a(O),a(q),a(ee),a(se),a(A)),a(t),j(u,e),j(b,e),B[c].d(e),j(N,e),j(z,e),I[x].d(e),j(v,e),j(Q,e)}}}const Ye='{"title":"Utilisation de modèles pré-entraînés","local":"utilisation-de-modèles-pré-entraînés","sections":[],"depth":1}';function qe(M,t,i){let l="pt";return Ue(()=>{const d=new URLSearchParams(window.location.search);i(0,l=d.get("fw")||"pt")}),[l]}class De extends xe{constructor(t){super(),$e(this,t,qe,Ie,je,{})}}export{De as component}; | |
Xet Storage Details
- Size:
- 17.3 kB
- Xet hash:
- 6dca14c4f8f218adb4a6ac2dce5e3a691b176d60297a1ef31ed12557a3b7f251
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.