Buckets:
| import{s as he,o as ue,n as ge}from"../chunks/scheduler.78382b47.js";import{S as Me,i as ye,e as p,s,c as y,h as _e,a as d,d as a,b as l,f as Y,g as _,j as U,k as K,l as g,m as n,n as j,t as w,o as T,p as b}from"../chunks/index.6dd35eb6.js";import{C as je,H as se,E as we}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.db10b59f.js";import{D as fe}from"../chunks/Docstring.892c143d.js";import{C as Te}from"../chunks/CodeBlock.e9241c92.js";import{E as be}from"../chunks/ExampleCodeBlock.b991652a.js";function Ce(V){let r,v="Example:",h,c,m;return c=new Te({props:{code:"ZnJvbSUyMGRpZmZ1c2VycyUyMGltcG9ydCUyMFN0YWJsZURpZmZ1c2lvblBpcGVsaW5lJTBBZnJvbSUyMHBlZnQlMjBpbXBvcnQlMjBMb0hhTW9kZWwlMkMlMjBMb0hhQ29uZmlnJTBBJTBBY29uZmlnX3RlJTIwJTNEJTIwTG9IYUNvbmZpZyglMEElMjAlMjAlMjAlMjByJTNEOCUyQyUwQSUyMCUyMCUyMCUyMGxvcmFfYWxwaGElM0QzMiUyQyUwQSUyMCUyMCUyMCUyMHRhcmdldF9tb2R1bGVzJTNEJTVCJTIya19wcm9qJTIyJTJDJTIwJTIycV9wcm9qJTIyJTJDJTIwJTIydl9wcm9qJTIyJTJDJTIwJTIyb3V0X3Byb2olMjIlMkMlMjAlMjJmYzElMjIlMkMlMjAlMjJmYzIlMjIlNUQlMkMlMEElMjAlMjAlMjAlMjByYW5rX2Ryb3BvdXQlM0QwLjAlMkMlMEElMjAlMjAlMjAlMjBtb2R1bGVfZHJvcG91dCUzRDAuMCUyQyUwQSUyMCUyMCUyMCUyMGluaXRfd2VpZ2h0cyUzRFRydWUlMkMlMEEpJTBBY29uZmlnX3VuZXQlMjAlM0QlMjBMb0hhQ29uZmlnKCUwQSUyMCUyMCUyMCUyMHIlM0Q4JTJDJTBBJTIwJTIwJTIwJTIwbG9yYV9hbHBoYSUzRDMyJTJDJTBBJTIwJTIwJTIwJTIwdGFyZ2V0X21vZHVsZXMlM0QlNUIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJwcm9qX2luJTIyJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIycHJval9vdXQlMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJ0b19rJTIyJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIydG9fcSUyMiUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMnRvX3YlMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJ0b19vdXQuMCUyMiUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMmZmLm5ldC4wLnByb2olMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJmZi5uZXQuMiUyMiUyQyUwQSUyMCUyMCUyMCUyMCU1RCUyQyUwQSUyMCUyMCUyMCUyMHJhbmtfZHJvcG91dCUzRDAuMCUyQyUwQSUyMCUyMCUyMCUyMG1vZHVsZV9kcm9wb3V0JTNEMC4wJTJDJTBBJTIwJTIwJTIwJTIwaW5pdF93ZWlnaHRzJTNEVHJ1ZSUyQyUwQSUyMCUyMCUyMCUyMHVzZV9lZmZlY3RpdmVfY29udjJkJTNEVHJ1ZSUyQyUwQSklMEElMEFtb2RlbCUyMCUzRCUyMFN0YWJsZURpZmZ1c2lvblBpcGVsaW5lLmZyb21fcHJldHJhaW5lZCglMjJydW53YXltbCUyRnN0YWJsZS1kaWZmdXNpb24tdjEtNSUyMiklMEFtb2RlbC50ZXh0X2VuY29kZXIlMjAlM0QlMjBMb0hhTW9kZWwobW9kZWwudGV4dF9lbmNvZGVyJTJDJTIwY29uZmlnX3RlJTJDJTIwJTIyZGVmYXVsdCUyMiklMEFtb2RlbC51bmV0JTIwJTNEJTIwTG9IYU1vZGVsKG1vZGVsLnVuZXQlMkMlMjBjb25maWdfdW5ldCUyQyUyMCUyMmRlZmF1bHQlMjIp",highlighted:`<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> diffusers <span class="hljs-keyword">import</span> StableDiffusionPipeline | |
| <span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> peft <span class="hljs-keyword">import</span> LoHaModel, LoHaConfig | |
| <span class="hljs-meta">>>> </span>config_te = LoHaConfig( | |
| <span class="hljs-meta">... </span> r=<span class="hljs-number">8</span>, | |
| <span class="hljs-meta">... </span> lora_alpha=<span class="hljs-number">32</span>, | |
| <span class="hljs-meta">... </span> target_modules=[<span class="hljs-string">"k_proj"</span>, <span class="hljs-string">"q_proj"</span>, <span class="hljs-string">"v_proj"</span>, <span class="hljs-string">"out_proj"</span>, <span class="hljs-string">"fc1"</span>, <span class="hljs-string">"fc2"</span>], | |
| <span class="hljs-meta">... </span> rank_dropout=<span class="hljs-number">0.0</span>, | |
| <span class="hljs-meta">... </span> module_dropout=<span class="hljs-number">0.0</span>, | |
| <span class="hljs-meta">... </span> init_weights=<span class="hljs-literal">True</span>, | |
| <span class="hljs-meta">... </span>) | |
| <span class="hljs-meta">>>> </span>config_unet = LoHaConfig( | |
| <span class="hljs-meta">... </span> r=<span class="hljs-number">8</span>, | |
| <span class="hljs-meta">... </span> lora_alpha=<span class="hljs-number">32</span>, | |
| <span class="hljs-meta">... </span> target_modules=[ | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"proj_in"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"proj_out"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"to_k"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"to_q"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"to_v"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"to_out.0"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"ff.net.0.proj"</span>, | |
| <span class="hljs-meta">... </span> <span class="hljs-string">"ff.net.2"</span>, | |
| <span class="hljs-meta">... </span> ], | |
| <span class="hljs-meta">... </span> rank_dropout=<span class="hljs-number">0.0</span>, | |
| <span class="hljs-meta">... </span> module_dropout=<span class="hljs-number">0.0</span>, | |
| <span class="hljs-meta">... </span> init_weights=<span class="hljs-literal">True</span>, | |
| <span class="hljs-meta">... </span> use_effective_conv2d=<span class="hljs-literal">True</span>, | |
| <span class="hljs-meta">... </span>) | |
| <span class="hljs-meta">>>> </span>model = StableDiffusionPipeline.from_pretrained(<span class="hljs-string">"runwayml/stable-diffusion-v1-5"</span>) | |
| <span class="hljs-meta">>>> </span>model.text_encoder = LoHaModel(model.text_encoder, config_te, <span class="hljs-string">"default"</span>) | |
| <span class="hljs-meta">>>> </span>model.unet = LoHaModel(model.unet, config_unet, <span class="hljs-string">"default"</span>)`,wrap:!1}}),{c(){r=p("p"),r.textContent=v,h=s(),y(c.$$.fragment)},l(o){r=d(o,"P",{"data-svelte-h":!0}),U(r)!=="svelte-11lpom8"&&(r.textContent=v),h=l(o),_(c.$$.fragment,o)},m(o,f){n(o,r,f),n(o,h,f),j(c,o,f),m=!0},p:ge,i(o){m||(w(c.$$.fragment,o),m=!0)},o(o){T(c.$$.fragment,o),m=!1},d(o){o&&(a(r),a(h)),b(c,o)}}}function Ue(V){let r,v,h,c,m,o,f,N,J,le='Low-Rank Hadamard Product (<a href="https://huggingface.co/papers/2108.06098" rel="nofollow">LoHa</a>), is similar to LoRA except it approximates the large weight matrix with more low-rank matrices and combines them with the Hadamard product. This method is even more parameter-efficient than LoRA and achieves comparable performance.',F,L,re="The abstract from the paper is:",S,H,ie="<em>In this work, we propose a communication-efficient parameterization, FedPara, for federated learning (FL) to overcome the burdens on frequent model uploads and downloads. Our method re-parameterizes weight parameters of layers using low-rank weights followed by the Hadamard product. Compared to the conventional low-rank parameterization, our FedPara method is not restricted to low-rank constraints, and thereby it has a far larger capacity. This property enables to achieve comparable performance while requiring 3 to 10 times lower communication costs than the model with the original layers, which is not achievable by the traditional low-rank methods. The efficiency of our method can be further improved by combining with other efficient FL optimizers. In addition, we extend our method to a personalized FL application, pFedPara, which separates parameters into global and local ones. We show that pFedPara outperforms competing personalized FL methods with more than three times fewer parameters</em>.",W,$,P,M,x,ee,q,pe='This is the configuration class to store the configuration of a <a href="/docs/peft/pr_3206/en/package_reference/loha#peft.LoHaModel">LoHaModel</a>.',G,I,D,i,k,te,E,de=`Creates Low-Rank Hadamard Product model from a pretrained model. The method is partially described in | |
| <a href="https://huggingface.co/papers/2108.06098" rel="nofollow">https://huggingface.co/papers/2108.06098</a> Current implementation heavily borrows from | |
| <a href="https://github.com/KohakuBlueleaf/LyCORIS/blob/eb460098187f752a5d66406d3affade6f0a07ece/lycoris/modules/loha.py" rel="nofollow">https://github.com/KohakuBlueleaf/LyCORIS/blob/eb460098187f752a5d66406d3affade6f0a07ece/lycoris/modules/loha.py</a>`,ae,C,ne,Q,ce="<strong>Attributes</strong>:",oe,B,me='<li><strong>model</strong> (<code>~torch.nn.Module</code>) — The model to be adapted.</li> <li><strong>peft_config</strong> (<a href="/docs/peft/pr_3206/en/package_reference/loha#peft.LoHaConfig">LoHaConfig</a>): The configuration of the LoHa model.</li>',O,A,X,R,z;return m=new je({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),f=new se({props:{title:"LoHa",local:"loha",headingTag:"h1"}}),$=new se({props:{title:"LoHaConfig",local:"peft.LoHaConfig",headingTag:"h2"}}),x=new fe({props:{name:"class peft.LoHaConfig",anchor:"peft.LoHaConfig",parameters:[{name:"task_type",val:": Optional[Union[str, TaskType]] = None"},{name:"peft_type",val:": Optional[Union[str, PeftType]] = None"},{name:"auto_mapping",val:": Optional[dict] = None"},{name:"peft_version",val:": Optional[str] = None"},{name:"base_model_name_or_path",val:": Optional[str] = None"},{name:"revision",val:": Optional[str] = None"},{name:"inference_mode",val:": bool = False"},{name:"rank_pattern",val:": Optional[dict] = <factory>"},{name:"alpha_pattern",val:": Optional[dict] = <factory>"},{name:"r",val:": int = 8"},{name:"alpha",val:": int = 8"},{name:"rank_dropout",val:": float = 0.0"},{name:"module_dropout",val:": float = 0.0"},{name:"use_effective_conv2d",val:": bool = False"},{name:"target_modules",val:": Optional[Union[list[str], str]] = None"},{name:"exclude_modules",val:": Optional[Union[list[str], str]] = None"},{name:"init_weights",val:": bool = True"},{name:"layers_to_transform",val:": Optional[Union[list[int], int]] = None"},{name:"layers_pattern",val:": Optional[Union[list[str], str]] = None"},{name:"modules_to_save",val:": Optional[list[str]] = None"}],parametersDescription:[{anchor:"peft.LoHaConfig.r",description:`<strong>r</strong> (<code>int</code>) — | |
| LoHa rank.`,name:"r"},{anchor:"peft.LoHaConfig.alpha",description:`<strong>alpha</strong> (<code>int</code>) — | |
| The alpha parameter for LoHa scaling.`,name:"alpha"},{anchor:"peft.LoHaConfig.rank_dropout",description:`<strong>rank_dropout</strong> (<code>float</code>) — | |
| The dropout probability for rank dimension during training.`,name:"rank_dropout"},{anchor:"peft.LoHaConfig.module_dropout",description:`<strong>module_dropout</strong> (<code>float</code>) — | |
| The dropout probability for disabling LoHa modules during training.`,name:"module_dropout"},{anchor:"peft.LoHaConfig.use_effective_conv2d",description:`<strong>use_effective_conv2d</strong> (<code>bool</code>) — | |
| Use parameter effective decomposition for Conv2d (and Conv1d) with ksize > 1 (“Proposition 3” from FedPara | |
| paper).`,name:"use_effective_conv2d"},{anchor:"peft.LoHaConfig.target_modules",description:`<strong>target_modules</strong> (<code>Optional[Union[List[str], str]]</code>) — | |
| The names of the modules to apply the adapter to. If this is specified, only the modules with the specified | |
| names will be replaced. When passing a string, a regex match will be performed. When passing a list of | |
| strings, either an exact match will be performed or it is checked if the name of the module ends with any | |
| of the passed strings. If this is specified as ‘all-linear’, then all linear/Conv1D modules are chosen, | |
| excluding the output layer. If this is not specified, modules will be chosen according to the model | |
| architecture. If the architecture is not known, an error will be raised — in this case, you should specify | |
| the target modules manually.`,name:"target_modules"},{anchor:"peft.LoHaConfig.exclude_modules",description:`<strong>exclude_modules</strong> (<code>Optional[Union[List[str], str]]</code>) — | |
| The names of the modules to not apply the adapter. When passing a string, a regex match will be performed. | |
| When passing a list of strings, either an exact match will be performed or it is checked if the name of the | |
| module ends with any of the passed strings.`,name:"exclude_modules"},{anchor:"peft.LoHaConfig.init_weights",description:`<strong>init_weights</strong> (<code>bool</code>) — | |
| Whether to perform initialization of adapter weights. This defaults to <code>True</code>, passing <code>False</code> is | |
| discouraged.`,name:"init_weights"},{anchor:"peft.LoHaConfig.layers_to_transform",description:`<strong>layers_to_transform</strong> (<code>Union[List[int], int]</code>) — | |
| The layer indices to transform. If a list of ints is passed, it will apply the adapter to the layer indices | |
| that are specified in this list. If a single integer is passed, it will apply the transformations on the | |
| layer at this index.`,name:"layers_to_transform"},{anchor:"peft.LoHaConfig.layers_pattern",description:`<strong>layers_pattern</strong> (<code>Optional[Union[List[str], str]]</code>) — | |
| The layer pattern name, used only if <code>layers_to_transform</code> is different from <code>None</code>. This should target the | |
| <code>nn.ModuleList</code> of the model, which is often called <code>'layers'</code> or <code>'h'</code>.`,name:"layers_pattern"},{anchor:"peft.LoHaConfig.rank_pattern",description:`<strong>rank_pattern</strong> (<code>dict</code>) — | |
| The mapping from layer names or regexp expression to ranks which are different from the default rank | |
| specified by <code>r</code>. For example, <code>{'^model.decoder.layers.0.encoder_attn.k_proj': 16}</code>.`,name:"rank_pattern"},{anchor:"peft.LoHaConfig.alpha_pattern",description:`<strong>alpha_pattern</strong> (<code>dict</code>) — | |
| The mapping from layer names or regexp expression to alphas which are different from the default alpha | |
| specified by <code>alpha</code>. For example, <code>{'^model.decoder.layers.0.encoder_attn.k_proj': 16}</code>.`,name:"alpha_pattern"},{anchor:"peft.LoHaConfig.modules_to_save",description:`<strong>modules_to_save</strong> (<code>Optional[List[str]]</code>) — | |
| List of modules apart from adapter layers to be set as trainable and saved in the final checkpoint.`,name:"modules_to_save"}],source:"https://github.com/huggingface/peft/blob/vr_3206/src/peft/tuners/loha/config.py#L24"}}),I=new se({props:{title:"LoHaModel",local:"peft.LoHaModel",headingTag:"h2"}}),k=new fe({props:{name:"class peft.LoHaModel",anchor:"peft.LoHaModel",parameters:[{name:"model",val:""},{name:"peft_config",val:": Union[PeftConfig, dict[str, PeftConfig]]"},{name:"adapter_name",val:": str"},{name:"low_cpu_mem_usage",val:": bool = False"},{name:"state_dict",val:": Optional[dict[str, torch.Tensor]] = None"}],parametersDescription:[{anchor:"peft.LoHaModel.model",description:"<strong>model</strong> (<code>torch.nn.Module</code>) — The model to which the adapter tuner layers will be attached.",name:"model"},{anchor:"peft.LoHaModel.config",description:'<strong>config</strong> (<a href="/docs/peft/pr_3206/en/package_reference/loha#peft.LoHaConfig">LoHaConfig</a>) — The configuration of the LoHa model.',name:"config"},{anchor:"peft.LoHaModel.adapter_name",description:"<strong>adapter_name</strong> (<code>str</code>) — The name of the adapter, defaults to <code>"default"</code>.",name:"adapter_name"},{anchor:"peft.LoHaModel.low_cpu_mem_usage",description:`<strong>low_cpu_mem_usage</strong> (<code>bool</code>, <code>optional</code>, defaults to <code>False</code>) — | |
| Create empty adapter weights on meta device. Useful to speed up the loading process.`,name:"low_cpu_mem_usage"}],source:"https://github.com/huggingface/peft/blob/vr_3206/src/peft/tuners/loha/model.py#L27",returnDescription:`<script context="module">export const metadata = 'undefined';<\/script> | |
| <p>The LoHa model.</p> | |
| `,returnType:`<script context="module">export const metadata = 'undefined';<\/script> | |
| <p><code>torch.nn.Module</code></p> | |
| `}}),C=new be({props:{anchor:"peft.LoHaModel.example",$$slots:{default:[Ce]},$$scope:{ctx:V}}}),A=new we({props:{source:"https://github.com/huggingface/peft/blob/main/docs/source/package_reference/loha.md"}}),{c(){r=p("meta"),v=s(),h=p("p"),c=s(),y(m.$$.fragment),o=s(),y(f.$$.fragment),N=s(),J=p("p"),J.innerHTML=le,F=s(),L=p("p"),L.textContent=re,S=s(),H=p("p"),H.innerHTML=ie,W=s(),y($.$$.fragment),P=s(),M=p("div"),y(x.$$.fragment),ee=s(),q=p("p"),q.innerHTML=pe,G=s(),y(I.$$.fragment),D=s(),i=p("div"),y(k.$$.fragment),te=s(),E=p("p"),E.innerHTML=de,ae=s(),y(C.$$.fragment),ne=s(),Q=p("p"),Q.innerHTML=ce,oe=s(),B=p("ul"),B.innerHTML=me,O=s(),y(A.$$.fragment),X=s(),R=p("p"),this.h()},l(e){const t=_e("svelte-u9bgzb",document.head);r=d(t,"META",{name:!0,content:!0}),t.forEach(a),v=l(e),h=d(e,"P",{}),Y(h).forEach(a),c=l(e),_(m.$$.fragment,e),o=l(e),_(f.$$.fragment,e),N=l(e),J=d(e,"P",{"data-svelte-h":!0}),U(J)!=="svelte-5yesx4"&&(J.innerHTML=le),F=l(e),L=d(e,"P",{"data-svelte-h":!0}),U(L)!=="svelte-1cwsb16"&&(L.textContent=re),S=l(e),H=d(e,"P",{"data-svelte-h":!0}),U(H)!=="svelte-8fm56j"&&(H.innerHTML=ie),W=l(e),_($.$$.fragment,e),P=l(e),M=d(e,"DIV",{class:!0});var Z=Y(M);_(x.$$.fragment,Z),ee=l(Z),q=d(Z,"P",{"data-svelte-h":!0}),U(q)!=="svelte-14g529u"&&(q.innerHTML=pe),Z.forEach(a),G=l(e),_(I.$$.fragment,e),D=l(e),i=d(e,"DIV",{class:!0});var u=Y(i);_(k.$$.fragment,u),te=l(u),E=d(u,"P",{"data-svelte-h":!0}),U(E)!=="svelte-1rluyyf"&&(E.innerHTML=de),ae=l(u),_(C.$$.fragment,u),ne=l(u),Q=d(u,"P",{"data-svelte-h":!0}),U(Q)!=="svelte-1xx6nm4"&&(Q.innerHTML=ce),oe=l(u),B=d(u,"UL",{"data-svelte-h":!0}),U(B)!=="svelte-hlemr5"&&(B.innerHTML=me),u.forEach(a),O=l(e),_(A.$$.fragment,e),X=l(e),R=d(e,"P",{}),Y(R).forEach(a),this.h()},h(){K(r,"name","hf:doc:metadata"),K(r,"content",ve),K(M,"class","docstring border-l-2 border-t-2 pl-4 pt-3.5 border-gray-100 rounded-tl-xl mb-6 mt-8"),K(i,"class","docstring border-l-2 border-t-2 pl-4 pt-3.5 border-gray-100 rounded-tl-xl mb-6 mt-8")},m(e,t){g(document.head,r),n(e,v,t),n(e,h,t),n(e,c,t),j(m,e,t),n(e,o,t),j(f,e,t),n(e,N,t),n(e,J,t),n(e,F,t),n(e,L,t),n(e,S,t),n(e,H,t),n(e,W,t),j($,e,t),n(e,P,t),n(e,M,t),j(x,M,null),g(M,ee),g(M,q),n(e,G,t),j(I,e,t),n(e,D,t),n(e,i,t),j(k,i,null),g(i,te),g(i,E),g(i,ae),j(C,i,null),g(i,ne),g(i,Q),g(i,oe),g(i,B),n(e,O,t),j(A,e,t),n(e,X,t),n(e,R,t),z=!0},p(e,[t]){const Z={};t&2&&(Z.$$scope={dirty:t,ctx:e}),C.$set(Z)},i(e){z||(w(m.$$.fragment,e),w(f.$$.fragment,e),w($.$$.fragment,e),w(x.$$.fragment,e),w(I.$$.fragment,e),w(k.$$.fragment,e),w(C.$$.fragment,e),w(A.$$.fragment,e),z=!0)},o(e){T(m.$$.fragment,e),T(f.$$.fragment,e),T($.$$.fragment,e),T(x.$$.fragment,e),T(I.$$.fragment,e),T(k.$$.fragment,e),T(C.$$.fragment,e),T(A.$$.fragment,e),z=!1},d(e){e&&(a(v),a(h),a(c),a(o),a(N),a(J),a(F),a(L),a(S),a(H),a(W),a(P),a(M),a(G),a(D),a(i),a(O),a(X),a(R)),a(r),b(m,e),b(f,e),b($,e),b(x),b(I,e),b(k),b(C),b(A,e)}}}const ve='{"title":"LoHa","local":"loha","sections":[{"title":"LoHaConfig","local":"peft.LoHaConfig","sections":[],"depth":2},{"title":"LoHaModel","local":"peft.LoHaModel","sections":[],"depth":2}],"depth":1}';function Je(V){return ue(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class Ae extends Me{constructor(r){super(),ye(this,r,Je,Ue,he,{})}}export{Ae as component}; | |
Xet Storage Details
- Size:
- 19.2 kB
- Xet hash:
- ed4ac54b5b63b3cf622fb97c62c04b34f5de6e277963502886b178ed8a0e0e4a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.