Buckets:
| import{s as Cs,n as _s,o as Zs}from"../chunks/scheduler.36a0863c.js";import{S as qs,i as ks,g as p,s as t,r,A as gs,h as o,f as l,c as n,j as Is,u as c,x as i,k as Bs,y as As,a,v as M,d,t as m,w as u}from"../chunks/index.f891bdb2.js";import{C as y}from"../chunks/CodeBlock.3ec784ea.js";import{H as Le,E as vs}from"../chunks/EditOnGithub.a58e27a9.js";function Hs(Ke){let j,pe,te,oe,J,ie,w,De=`En esta guía, veremos cómo crear un pipeline personalizado y cómo compartirlo en el <a href="https://hf.co/models" rel="nofollow">Hub</a> o añadirlo | |
| a la biblioteca 🤗 Transformers.`,re,T,Oe=`En primer lugar, debes decidir las entradas que tu pipeline podrá recibir. Pueden ser strings, bytes, | |
| diccionarios o lo que te parezca que vaya a ser la entrada más apropiada. Intenta mantener estas entradas en un | |
| formato que sea tan Python puro como sea posible, puesto que esto facilita la compatibilidad (incluso con otros | |
| lenguajes de programación por medio de JSON). Estos serán los <code>inputs</code> (entradas) del pipeline (<code>preprocess</code>).`,ce,U,es=`Ahora debes definir los <code>outputs</code> (salidas). Al igual que con los <code>inputs</code>, entre más simple el formato, mejor. | |
| Estas serán las salidas del método <code>postprocess</code> (posprocesamiento).`,Me,f,ss=`Empieza heredando la clase base <code>Pipeline</code> con los 4 métodos que debemos implementar: <code>preprocess</code> (preprocesamiento), | |
| <code>_forward</code> (ejecución), <code>postprocess</code> (posprocesamiento) y <code>_sanitize_parameters</code> (verificar parámetros).`,de,b,me,h,ls=`La estructura de este desglose es así para garantizar una compatibilidad más o menos transparente con el uso de | |
| CPU/GPU y el pre/posprocesamiento en CPU en varios hilos.`,ue,I,as=`<code>preprocess</code> tomará las entradas definidas originalmente y las convertirá en algo que se le pueda pasar al modelo. | |
| Podría contener más información y a menudo es un objeto <code>Dict</code> (diccionario).`,ye,B,ts=`<code>_forward</code> contiene los detalles de la implementación y no debería ser invocado de forma directa. <code>forward</code> es el | |
| método preferido a utilizar pues contiene verificaciones para asegurar que todo funcione en el dispositivo correcto. | |
| Cualquier cosa que esté relacionada con un modelo real debería ir en el método <code>_forward</code>, todo lo demás va en | |
| los métodos de preprocesamiento y posprocesamiento.`,je,C,ns=`Los métodos <code>postprocess</code> reciben la salida <code>_forward</code> y la convierten en la salida final que decidimos | |
| anteriormente.`,Je,_,ps=`<code>_sanitize_parameters</code> existe para permitir a los usuarios pasar cualesquiera parámetros cuando lo deseen, ya | |
| sea al momento de inicializar el pipeline <code>pipeline(...., maybe_arg=4)</code> o al momento de invocarlo | |
| <code>pipe = pipeline(...); output = pipe(...., maybe_arg=4)</code>.`,we,Z,os=`El método <code>_sanitize_parameters</code> devuelve 3 diccionarios de kwargs que serán pasados directamente a <code>preprocess</code>, | |
| <code>_forward</code> y <code>postprocess</code>. No ingreses nada si el caller no se va a invocar con parámetros adicionales. | |
| Esto permite mantener los parámetros por defecto de la definición de la función, lo que es más “natural”.`,Te,q,is="Un ejemplo clásico sería un argumento <code>top_k</code> en el posprocesamiento de una tarea de clasificación.",Ue,k,fe,g,rs=`Para lograrlo, actualizaremos nuestro método <code>postprocess</code> con un valor por defecto de <code>5</code> y modificaremos | |
| <code>_sanitize_parameters</code> para permitir este nuevo parámetro.`,be,A,he,v,cs=`Intenta que las entradas y salidas sean muy simples e, idealmente, que puedan serializarse como JSON, pues esto | |
| hace el uso del pipeline muy sencillo sin que el usuario tenga que preocuparse por conocer nuevos tipos de objetos. | |
| También es relativamente común tener compatibilidad con muchos tipos diferentes de argumentos por facilidad de uso | |
| (por ejemplo, los archivos de audio pueden ser nombres de archivo, URLs o bytes).`,Ie,H,Be,E,Ms=`Para registrar tu <code>new-task</code> (nueva tarea) en la lista de tareas, debes añadirla al | |
| <code>PIPELINE_REGISTRY</code> (registro de pipelines):`,Ce,W,_e,V,ds="Puedes especificar un modelo por defecto si lo deseas, en cuyo caso debe venir con una versión específica (que puede ser el nombre de un branch o hash de commit, en este caso usamos <code>"abcdef"</code>), así como el tipo:",Ze,R,qe,z,ke,G,ms=`Para compartir tu pipeline personalizado en el Hub, solo tienes que guardar el código personalizado de tu sub-clase | |
| <code>Pipeline</code> en un archivo de Python. Por ejemplo, digamos que queremos usar un pipeline personalizado para la | |
| clasificación de duplas de oraciones de esta forma:`,ge,N,Ae,X,us=`La implementación es independiente del framework y funcionará con modelos de PyTorch y TensorFlow. Si guardamos | |
| esto en un archivo llamado <code>pair_classification.py</code>, podemos importarlo y registrarlo de la siguiente manera:`,ve,$,He,x,ys=`Una vez hecho esto, podemos usarlo con un modelo pre-entrenado. Por ejemplo, al modelo <code>sgugger/finetuned-bert-mrpc</code> | |
| se le hizo fine-tuning con el dataset MRPC, en el cual se clasifican duplas de oraciones como paráfrasis o no.`,Ee,Y,We,F,js="Ahora podemos compartirlo en el Hub usando el método <code>save_pretrained</code>:",Ve,Q,Re,S,Js=`Esto copiará el archivo donde definiste <code>PairClassificationPipeline</code> dentro de la carpeta <code>"test-dynamic-pipeline"</code>, | |
| y además guardará el modelo y el tokenizer del pipeline, antes de enviar todo al repositorio | |
| <code>{your_username}/test-dynamic-pipeline</code>. Después de esto, cualquier persona puede usarlo siempre que usen la opción | |
| <code>trust_remote_code=True</code> (confiar en código remoto):`,ze,P,Ge,L,Ne,K,ws=`Si quieres contribuir tu pipeline a la biblioteca 🤗 Transformers, tendrás que añadirlo a un nuevo módulo en el | |
| sub-módulo <code>pipelines</code> con el código de tu pipeline. Luego, debes añadirlo a la lista de tareas definidas en | |
| <code>pipelines/__init__.py</code>.`,Xe,D,Ts=`A continuación tienes que añadir las pruebas. Crea un nuevo archivo llamado <code>tests/test_pipelines_MY_PIPELINE.py</code> | |
| basándote en las pruebas existentes.`,$e,O,Us=`La función <code>run_pipeline_test</code> será muy genérica y se correrá sobre modelos pequeños escogidos al azar sobre todas las | |
| arquitecturas posibles definidas en <code>model_mapping</code> y <code>tf_model_mapping</code>.`,xe,ee,fs=`Esto es muy importante para probar compatibilidades a futuro, lo que significa que si alguien añade un nuevo modelo | |
| para <code>XXXForQuestionAnswering</code> entonces el pipeline intentará ejecutarse con ese modelo. Ya que los modelos son aleatorios, | |
| es imposible verificar los valores como tales, y es por eso que hay un helper <code>ANY</code> que simplemente intentará que la | |
| salida tenga el mismo tipo que la salida esperada del pipeline.`,Ye,se,bs="También <em>debes</em> implementar 2 (preferiblemente 4) pruebas:",Fe,le,hs=`<li><code>test_small_model_pt</code> : Define un (1) modelo pequeño para este pipeline (no importa si los resultados no tienen sentido) | |
| y prueba las salidas del pipeline. Los resultados deberían ser los mismos que en <code>test_small_model_tf</code>.</li> <li><code>test_small_model_tf</code> : Define un (1) modelo pequeño para este pipeline (no importa si los resultados no tienen sentido) | |
| y prueba las salidas del pipeline. Los resultados deberían ser los mismos que en <code>test_small_model_pt</code>.</li> <li><code>test_large_model_pt</code> (<code>optional</code>): Prueba el pipeline en una tarea real en la que los resultados deben tener sentido. | |
| Estas pruebas son lentas y deben marcarse como tales. El objetivo de esto es ejemplificar el pipeline y asegurarse de que | |
| no haya divergencias en versiones futuras.</li> <li><code>test_large_model_tf</code> (<code>optional</code>): Prueba el pipeline en una tarea real en la que los resultados deben tener sentido. | |
| Estas pruebas son lentas y deben marcarse como tales. El objetivo de esto es ejemplificar el pipeline y asegurarse de que | |
| no haya divergencias en versiones futuras.</li>`,Qe,ae,Se,ne,Pe;return J=new Le({props:{title:"¿Cómo puedo crear un pipeline personalizado?",local:"cómo-puedo-crear-un-pipeline-personalizado",headingTag:"h1"}}),b=new y({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMFBpcGVsaW5lJTBBJTBBJTBBY2xhc3MlMjBNeVBpcGVsaW5lKFBpcGVsaW5lKSUzQSUwQSUyMCUyMCUyMCUyMGRlZiUyMF9zYW5pdGl6ZV9wYXJhbWV0ZXJzKHNlbGYlMkMlMjAqKmt3YXJncyklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcmVwcm9jZXNzX2t3YXJncyUyMCUzRCUyMCU3QiU3RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGlmJTIwJTIybWF5YmVfYXJnJTIyJTIwaW4lMjBrd2FyZ3MlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcmVwcm9jZXNzX2t3YXJncyU1QiUyMm1heWJlX2FyZyUyMiU1RCUyMCUzRCUyMGt3YXJncyU1QiUyMm1heWJlX2FyZyUyMiU1RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMHByZXByb2Nlc3Nfa3dhcmdzJTJDJTIwJTdCJTdEJTJDJTIwJTdCJTdEJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwcHJlcHJvY2VzcyhzZWxmJTJDJTIwaW5wdXRzJTJDJTIwbWF5YmVfYXJnJTNEMiklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBtb2RlbF9pbnB1dCUyMCUzRCUyMFRlbnNvcihpbnB1dHMlNUIlMjJpbnB1dF9pZHMlMjIlNUQpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTdCJTIybW9kZWxfaW5wdXQlMjIlM0ElMjBtb2RlbF9pbnB1dCU3RCUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMF9mb3J3YXJkKHNlbGYlMkMlMjBtb2RlbF9pbnB1dHMpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwbW9kZWxfaW5wdXRzJTIwJTNEJTNEJTIwJTdCJTIybW9kZWxfaW5wdXQlMjIlM0ElMjBtb2RlbF9pbnB1dCU3RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG91dHB1dHMlMjAlM0QlMjBzZWxmLm1vZGVsKCoqbW9kZWxfaW5wdXRzKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMFF1aXolQzMlQTElMjAlN0IlMjJsb2dpdHMlMjIlM0ElMjBUZW5zb3IoLi4uKSU3RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMG91dHB1dHMlMEElMEElMjAlMjAlMjAlMjBkZWYlMjBwb3N0cHJvY2VzcyhzZWxmJTJDJTIwbW9kZWxfb3V0cHV0cyklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBiZXN0X2NsYXNzJTIwJTNEJTIwbW9kZWxfb3V0cHV0cyU1QiUyMmxvZ2l0cyUyMiU1RC5zb2Z0bWF4KC0xKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMGJlc3RfY2xhc3M=",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> Pipeline | |
| <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyPipeline</span>(<span class="hljs-title class_ inherited__">Pipeline</span>): | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_sanitize_parameters</span>(<span class="hljs-params">self, **kwargs</span>): | |
| preprocess_kwargs = {} | |
| <span class="hljs-keyword">if</span> <span class="hljs-string">"maybe_arg"</span> <span class="hljs-keyword">in</span> kwargs: | |
| preprocess_kwargs[<span class="hljs-string">"maybe_arg"</span>] = kwargs[<span class="hljs-string">"maybe_arg"</span>] | |
| <span class="hljs-keyword">return</span> preprocess_kwargs, {}, {} | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">preprocess</span>(<span class="hljs-params">self, inputs, maybe_arg=<span class="hljs-number">2</span></span>): | |
| model_input = Tensor(inputs[<span class="hljs-string">"input_ids"</span>]) | |
| <span class="hljs-keyword">return</span> {<span class="hljs-string">"model_input"</span>: model_input} | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_forward</span>(<span class="hljs-params">self, model_inputs</span>): | |
| <span class="hljs-comment"># model_inputs == {"model_input": model_input}</span> | |
| outputs = self.model(**model_inputs) | |
| <span class="hljs-comment"># Quizá {"logits": Tensor(...)}</span> | |
| <span class="hljs-keyword">return</span> outputs | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">postprocess</span>(<span class="hljs-params">self, model_outputs</span>): | |
| best_class = model_outputs[<span class="hljs-string">"logits"</span>].softmax(-<span class="hljs-number">1</span>) | |
| <span class="hljs-keyword">return</span> best_class`,wrap:!1}}),k=new y({props:{code:"cGlwZSUyMCUzRCUyMHBpcGVsaW5lKCUyMm15LW5ldy10YXNrJTIyKSUwQXBpcGUoJTIyVGhpcyUyMGlzJTIwYSUyMHRlc3QlMjIpJTBBJTBBcGlwZSglMjJUaGlzJTIwaXMlMjBhJTIwdGVzdCUyMiUyQyUyMHRvcF9rJTNEMik=",highlighted:`<span class="hljs-meta">>>> </span>pipe = pipeline(<span class="hljs-string">"my-new-task"</span>) | |
| <span class="hljs-meta">>>> </span>pipe(<span class="hljs-string">"This is a test"</span>) | |
| [{<span class="hljs-string">"label"</span>: <span class="hljs-string">"1-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.8</span>}, {<span class="hljs-string">"label"</span>: <span class="hljs-string">"2-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.1</span>}, {<span class="hljs-string">"label"</span>: <span class="hljs-string">"3-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.05</span>} | |
| {<span class="hljs-string">"label"</span>: <span class="hljs-string">"4-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.025</span>}, {<span class="hljs-string">"label"</span>: <span class="hljs-string">"5-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.025</span>}] | |
| <span class="hljs-meta">>>> </span>pipe(<span class="hljs-string">"This is a test"</span>, top_k=<span class="hljs-number">2</span>) | |
| [{<span class="hljs-string">"label"</span>: <span class="hljs-string">"1-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.8</span>}, {<span class="hljs-string">"label"</span>: <span class="hljs-string">"2-star"</span>, <span class="hljs-string">"score"</span>: <span class="hljs-number">0.1</span>}]`,wrap:!1}}),A=new y({props:{code:"ZGVmJTIwcG9zdHByb2Nlc3Moc2VsZiUyQyUyMG1vZGVsX291dHB1dHMlMkMlMjB0b3BfayUzRDUpJTNBJTBBJTIwJTIwJTIwJTIwYmVzdF9jbGFzcyUyMCUzRCUyMG1vZGVsX291dHB1dHMlNUIlMjJsb2dpdHMlMjIlNUQuc29mdG1heCgtMSklMEElMjAlMjAlMjAlMjAlMjMlMjBBJUMzJUIxYWRlJTIwbGElMjBsJUMzJUIzZ2ljYSUyMHBhcmElMjBtYW5lamFyJTIwZWwlMjB0b3BfayUwQSUyMCUyMCUyMCUyMHJldHVybiUyMGJlc3RfY2xhc3MlMEElMEElMEFkZWYlMjBfc2FuaXRpemVfcGFyYW1ldGVycyhzZWxmJTJDJTIwKiprd2FyZ3MpJTNBJTBBJTIwJTIwJTIwJTIwcHJlcHJvY2Vzc19rd2FyZ3MlMjAlM0QlMjAlN0IlN0QlMEElMjAlMjAlMjAlMjBpZiUyMCUyMm1heWJlX2FyZyUyMiUyMGluJTIwa3dhcmdzJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJlcHJvY2Vzc19rd2FyZ3MlNUIlMjJtYXliZV9hcmclMjIlNUQlMjAlM0QlMjBrd2FyZ3MlNUIlMjJtYXliZV9hcmclMjIlNUQlMEElMEElMjAlMjAlMjAlMjBwb3N0cHJvY2Vzc19rd2FyZ3MlMjAlM0QlMjAlN0IlN0QlMEElMjAlMjAlMjAlMjBpZiUyMCUyMnRvcF9rJTIyJTIwaW4lMjBrd2FyZ3MlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwb3N0cHJvY2Vzc19rd2FyZ3MlNUIlMjJ0b3BfayUyMiU1RCUyMCUzRCUyMGt3YXJncyU1QiUyMnRvcF9rJTIyJTVEJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwcHJlcHJvY2Vzc19rd2FyZ3MlMkMlMjAlN0IlN0QlMkMlMjBwb3N0cHJvY2Vzc19rd2FyZ3M=",highlighted:`<span class="hljs-keyword">def</span> <span class="hljs-title function_">postprocess</span>(<span class="hljs-params">self, model_outputs, top_k=<span class="hljs-number">5</span></span>): | |
| best_class = model_outputs[<span class="hljs-string">"logits"</span>].softmax(-<span class="hljs-number">1</span>) | |
| <span class="hljs-comment"># Añade la lógica para manejar el top_k</span> | |
| <span class="hljs-keyword">return</span> best_class | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_sanitize_parameters</span>(<span class="hljs-params">self, **kwargs</span>): | |
| preprocess_kwargs = {} | |
| <span class="hljs-keyword">if</span> <span class="hljs-string">"maybe_arg"</span> <span class="hljs-keyword">in</span> kwargs: | |
| preprocess_kwargs[<span class="hljs-string">"maybe_arg"</span>] = kwargs[<span class="hljs-string">"maybe_arg"</span>] | |
| postprocess_kwargs = {} | |
| <span class="hljs-keyword">if</span> <span class="hljs-string">"top_k"</span> <span class="hljs-keyword">in</span> kwargs: | |
| postprocess_kwargs[<span class="hljs-string">"top_k"</span>] = kwargs[<span class="hljs-string">"top_k"</span>] | |
| <span class="hljs-keyword">return</span> preprocess_kwargs, {}, postprocess_kwargs`,wrap:!1}}),H=new Le({props:{title:"Añadirlo a la lista de tareas",local:"añadirlo-a-la-lista-de-tareas",headingTag:"h2"}}),W=new y({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycy5waXBlbGluZXMlMjBpbXBvcnQlMjBQSVBFTElORV9SRUdJU1RSWSUwQSUwQVBJUEVMSU5FX1JFR0lTVFJZLnJlZ2lzdGVyX3BpcGVsaW5lKCUwQSUyMCUyMCUyMCUyMCUyMm5ldy10YXNrJTIyJTJDJTBBJTIwJTIwJTIwJTIwcGlwZWxpbmVfY2xhc3MlM0RNeVBpcGVsaW5lJTJDJTBBJTIwJTIwJTIwJTIwcHRfbW9kZWwlM0RBdXRvTW9kZWxGb3JTZXF1ZW5jZUNsYXNzaWZpY2F0aW9uJTJDJTBBKQ==",highlighted:`<span class="hljs-keyword">from</span> transformers.pipelines <span class="hljs-keyword">import</span> PIPELINE_REGISTRY | |
| PIPELINE_REGISTRY.register_pipeline( | |
| <span class="hljs-string">"new-task"</span>, | |
| pipeline_class=MyPipeline, | |
| pt_model=AutoModelForSequenceClassification, | |
| )`,wrap:!1}}),R=new y({props:{code:"UElQRUxJTkVfUkVHSVNUUlkucmVnaXN0ZXJfcGlwZWxpbmUoJTBBJTIwJTIwJTIwJTIwJTIybmV3LXRhc2slMjIlMkMlMEElMjAlMjAlMjAlMjBwaXBlbGluZV9jbGFzcyUzRE15UGlwZWxpbmUlMkMlMEElMjAlMjAlMjAlMjBwdF9tb2RlbCUzREF1dG9Nb2RlbEZvclNlcXVlbmNlQ2xhc3NpZmljYXRpb24lMkMlMEElMjAlMjAlMjAlMjBkZWZhdWx0JTNEJTdCJTIycHQlMjIlM0ElMjAoJTIydXNlciUyRmF3ZXNvbWVfbW9kZWwlMjIlMkMlMjAlMjJhYmNkZWYlMjIpJTdEJTJDJTBBJTIwJTIwJTIwJTIwdHlwZSUzRCUyMnRleHQlMjIlMkMlMjAlMjAlMjMlMjB0aXBvJTIwZGUlMjBkYXRvcyUyMHF1ZSUyMG1hbmVqYSUzQSUyMHRleHRvJTJDJTIwYXVkaW8lMkMlMjBpbWFnZW4lMkMlMjBtdWx0aS1tb2RhbGlkYWQlMEEp",highlighted:`PIPELINE_REGISTRY.register_pipeline( | |
| <span class="hljs-string">"new-task"</span>, | |
| pipeline_class=MyPipeline, | |
| pt_model=AutoModelForSequenceClassification, | |
| default={<span class="hljs-string">"pt"</span>: (<span class="hljs-string">"user/awesome_model"</span>, <span class="hljs-string">"abcdef"</span>)}, | |
| <span class="hljs-built_in">type</span>=<span class="hljs-string">"text"</span>, <span class="hljs-comment"># tipo de datos que maneja: texto, audio, imagen, multi-modalidad</span> | |
| )`,wrap:!1}}),z=new Le({props:{title:"Comparte tu pipeline en el Hub",local:"comparte-tu-pipeline-en-el-hub",headingTag:"h2"}}),N=new y({props:{code:"aW1wb3J0JTIwbnVtcHklMjBhcyUyMG5wJTBBJTBBZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMFBpcGVsaW5lJTBBJTBBJTBBZGVmJTIwc29mdG1heChvdXRwdXRzKSUzQSUwQSUyMCUyMCUyMCUyMG1heGVzJTIwJTNEJTIwbnAubWF4KG91dHB1dHMlMkMlMjBheGlzJTNELTElMkMlMjBrZWVwZGltcyUzRFRydWUpJTBBJTIwJTIwJTIwJTIwc2hpZnRlZF9leHAlMjAlM0QlMjBucC5leHAob3V0cHV0cyUyMC0lMjBtYXhlcyklMEElMjAlMjAlMjAlMjByZXR1cm4lMjBzaGlmdGVkX2V4cCUyMCUyRiUyMHNoaWZ0ZWRfZXhwLnN1bShheGlzJTNELTElMkMlMjBrZWVwZGltcyUzRFRydWUpJTBBJTBBJTBBY2xhc3MlMjBQYWlyQ2xhc3NpZmljYXRpb25QaXBlbGluZShQaXBlbGluZSklM0ElMEElMjAlMjAlMjAlMjBkZWYlMjBfc2FuaXRpemVfcGFyYW1ldGVycyhzZWxmJTJDJTIwKiprd2FyZ3MpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJlcHJvY2Vzc19rd2FyZ3MlMjAlM0QlMjAlN0IlN0QlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBpZiUyMCUyMnNlY29uZF90ZXh0JTIyJTIwaW4lMjBrd2FyZ3MlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcmVwcm9jZXNzX2t3YXJncyU1QiUyMnNlY29uZF90ZXh0JTIyJTVEJTIwJTNEJTIwa3dhcmdzJTVCJTIyc2Vjb25kX3RleHQlMjIlNUQlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBwcmVwcm9jZXNzX2t3YXJncyUyQyUyMCU3QiU3RCUyQyUyMCU3QiU3RCUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMHByZXByb2Nlc3Moc2VsZiUyQyUyMHRleHQlMkMlMjBzZWNvbmRfdGV4dCUzRE5vbmUpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwc2VsZi50b2tlbml6ZXIodGV4dCUyQyUyMHRleHRfcGFpciUzRHNlY29uZF90ZXh0JTJDJTIwcmV0dXJuX3RlbnNvcnMlM0RzZWxmLmZyYW1ld29yayklMEElMEElMjAlMjAlMjAlMjBkZWYlMjBfZm9yd2FyZChzZWxmJTJDJTIwbW9kZWxfaW5wdXRzKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMHNlbGYubW9kZWwoKiptb2RlbF9pbnB1dHMpJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwcG9zdHByb2Nlc3Moc2VsZiUyQyUyMG1vZGVsX291dHB1dHMpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbG9naXRzJTIwJTNEJTIwbW9kZWxfb3V0cHV0cy5sb2dpdHMlNUIwJTVELm51bXB5KCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcm9iYWJpbGl0aWVzJTIwJTNEJTIwc29mdG1heChsb2dpdHMpJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwYmVzdF9jbGFzcyUyMCUzRCUyMG5wLmFyZ21heChwcm9iYWJpbGl0aWVzKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGxhYmVsJTIwJTNEJTIwc2VsZi5tb2RlbC5jb25maWcuaWQybGFiZWwlNUJiZXN0X2NsYXNzJTVEJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc2NvcmUlMjAlM0QlMjBwcm9iYWJpbGl0aWVzJTVCYmVzdF9jbGFzcyU1RC5pdGVtKCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBsb2dpdHMlMjAlM0QlMjBsb2dpdHMudG9saXN0KCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAlN0IlMjJsYWJlbCUyMiUzQSUyMGxhYmVsJTJDJTIwJTIyc2NvcmUlMjIlM0ElMjBzY29yZSUyQyUyMCUyMmxvZ2l0cyUyMiUzQSUyMGxvZ2l0cyU3RA==",highlighted:`<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np | |
| <span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> Pipeline | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">softmax</span>(<span class="hljs-params">outputs</span>): | |
| maxes = np.<span class="hljs-built_in">max</span>(outputs, axis=-<span class="hljs-number">1</span>, keepdims=<span class="hljs-literal">True</span>) | |
| shifted_exp = np.exp(outputs - maxes) | |
| <span class="hljs-keyword">return</span> shifted_exp / shifted_exp.<span class="hljs-built_in">sum</span>(axis=-<span class="hljs-number">1</span>, keepdims=<span class="hljs-literal">True</span>) | |
| <span class="hljs-keyword">class</span> <span class="hljs-title class_">PairClassificationPipeline</span>(<span class="hljs-title class_ inherited__">Pipeline</span>): | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_sanitize_parameters</span>(<span class="hljs-params">self, **kwargs</span>): | |
| preprocess_kwargs = {} | |
| <span class="hljs-keyword">if</span> <span class="hljs-string">"second_text"</span> <span class="hljs-keyword">in</span> kwargs: | |
| preprocess_kwargs[<span class="hljs-string">"second_text"</span>] = kwargs[<span class="hljs-string">"second_text"</span>] | |
| <span class="hljs-keyword">return</span> preprocess_kwargs, {}, {} | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">preprocess</span>(<span class="hljs-params">self, text, second_text=<span class="hljs-literal">None</span></span>): | |
| <span class="hljs-keyword">return</span> self.tokenizer(text, text_pair=second_text, return_tensors=self.framework) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_forward</span>(<span class="hljs-params">self, model_inputs</span>): | |
| <span class="hljs-keyword">return</span> self.model(**model_inputs) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">postprocess</span>(<span class="hljs-params">self, model_outputs</span>): | |
| logits = model_outputs.logits[<span class="hljs-number">0</span>].numpy() | |
| probabilities = softmax(logits) | |
| best_class = np.argmax(probabilities) | |
| label = self.model.config.id2label[best_class] | |
| score = probabilities[best_class].item() | |
| logits = logits.tolist() | |
| <span class="hljs-keyword">return</span> {<span class="hljs-string">"label"</span>: label, <span class="hljs-string">"score"</span>: score, <span class="hljs-string">"logits"</span>: logits}`,wrap:!1}}),$=new y({props:{code:"ZnJvbSUyMHBhaXJfY2xhc3NpZmljYXRpb24lMjBpbXBvcnQlMjBQYWlyQ2xhc3NpZmljYXRpb25QaXBlbGluZSUwQWZyb20lMjB0cmFuc2Zvcm1lcnMucGlwZWxpbmVzJTIwaW1wb3J0JTIwUElQRUxJTkVfUkVHSVNUUlklMEFmcm9tJTIwdHJhbnNmb3JtZXJzJTIwaW1wb3J0JTIwQXV0b01vZGVsRm9yU2VxdWVuY2VDbGFzc2lmaWNhdGlvbiUyQyUyMFRGQXV0b01vZGVsRm9yU2VxdWVuY2VDbGFzc2lmaWNhdGlvbiUwQSUwQVBJUEVMSU5FX1JFR0lTVFJZLnJlZ2lzdGVyX3BpcGVsaW5lKCUwQSUyMCUyMCUyMCUyMCUyMnBhaXItY2xhc3NpZmljYXRpb24lMjIlMkMlMEElMjAlMjAlMjAlMjBwaXBlbGluZV9jbGFzcyUzRFBhaXJDbGFzc2lmaWNhdGlvblBpcGVsaW5lJTJDJTBBJTIwJTIwJTIwJTIwcHRfbW9kZWwlM0RBdXRvTW9kZWxGb3JTZXF1ZW5jZUNsYXNzaWZpY2F0aW9uJTJDJTBBJTIwJTIwJTIwJTIwdGZfbW9kZWwlM0RURkF1dG9Nb2RlbEZvclNlcXVlbmNlQ2xhc3NpZmljYXRpb24lMkMlMEEp",highlighted:`<span class="hljs-keyword">from</span> pair_classification <span class="hljs-keyword">import</span> PairClassificationPipeline | |
| <span class="hljs-keyword">from</span> transformers.pipelines <span class="hljs-keyword">import</span> PIPELINE_REGISTRY | |
| <span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoModelForSequenceClassification, TFAutoModelForSequenceClassification | |
| PIPELINE_REGISTRY.register_pipeline( | |
| <span class="hljs-string">"pair-classification"</span>, | |
| pipeline_class=PairClassificationPipeline, | |
| pt_model=AutoModelForSequenceClassification, | |
| tf_model=TFAutoModelForSequenceClassification, | |
| )`,wrap:!1}}),Y=new y({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMHBpcGVsaW5lJTBBJTBBY2xhc3NpZmllciUyMCUzRCUyMHBpcGVsaW5lKCUyMnBhaXItY2xhc3NpZmljYXRpb24lMjIlMkMlMjBtb2RlbCUzRCUyMnNndWdnZXIlMkZmaW5ldHVuZWQtYmVydC1tcnBjJTIyKQ==",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline | |
| classifier = pipeline(<span class="hljs-string">"pair-classification"</span>, model=<span class="hljs-string">"sgugger/finetuned-bert-mrpc"</span>)`,wrap:!1}}),Q=new y({props:{code:"Y2xhc3NpZmllci5wdXNoX3RvX2h1YiglMjJ0ZXN0LWR5bmFtaWMtcGlwZWxpbmUlMjIp",highlighted:'classifier.push_to_hub(<span class="hljs-string">"test-dynamic-pipeline"</span>)',wrap:!1}}),P=new y({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMHBpcGVsaW5lJTBBJTBBY2xhc3NpZmllciUyMCUzRCUyMHBpcGVsaW5lKG1vZGVsJTNEJTIyJTdCeW91cl91c2VybmFtZSU3RCUyRnRlc3QtZHluYW1pYy1waXBlbGluZSUyMiUyQyUyMHRydXN0X3JlbW90ZV9jb2RlJTNEVHJ1ZSk=",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline | |
| classifier = pipeline(model=<span class="hljs-string">"{your_username}/test-dynamic-pipeline"</span>, trust_remote_code=<span class="hljs-literal">True</span>)`,wrap:!1}}),L=new Le({props:{title:"Añadir el pipeline a 🤗 Transformers",local:"añadir-el-pipeline-a--transformers",headingTag:"h2"}}),ae=new vs({props:{source:"https://github.com/huggingface/transformers/blob/main/docs/source/es/add_new_pipeline.md"}}),{c(){j=p("meta"),pe=t(),te=p("p"),oe=t(),r(J.$$.fragment),ie=t(),w=p("p"),w.innerHTML=De,re=t(),T=p("p"),T.innerHTML=Oe,ce=t(),U=p("p"),U.innerHTML=es,Me=t(),f=p("p"),f.innerHTML=ss,de=t(),r(b.$$.fragment),me=t(),h=p("p"),h.textContent=ls,ue=t(),I=p("p"),I.innerHTML=as,ye=t(),B=p("p"),B.innerHTML=ts,je=t(),C=p("p"),C.innerHTML=ns,Je=t(),_=p("p"),_.innerHTML=ps,we=t(),Z=p("p"),Z.innerHTML=os,Te=t(),q=p("p"),q.innerHTML=is,Ue=t(),r(k.$$.fragment),fe=t(),g=p("p"),g.innerHTML=rs,be=t(),r(A.$$.fragment),he=t(),v=p("p"),v.textContent=cs,Ie=t(),r(H.$$.fragment),Be=t(),E=p("p"),E.innerHTML=Ms,Ce=t(),r(W.$$.fragment),_e=t(),V=p("p"),V.innerHTML=ds,Ze=t(),r(R.$$.fragment),qe=t(),r(z.$$.fragment),ke=t(),G=p("p"),G.innerHTML=ms,ge=t(),r(N.$$.fragment),Ae=t(),X=p("p"),X.innerHTML=us,ve=t(),r($.$$.fragment),He=t(),x=p("p"),x.innerHTML=ys,Ee=t(),r(Y.$$.fragment),We=t(),F=p("p"),F.innerHTML=js,Ve=t(),r(Q.$$.fragment),Re=t(),S=p("p"),S.innerHTML=Js,ze=t(),r(P.$$.fragment),Ge=t(),r(L.$$.fragment),Ne=t(),K=p("p"),K.innerHTML=ws,Xe=t(),D=p("p"),D.innerHTML=Ts,$e=t(),O=p("p"),O.innerHTML=Us,xe=t(),ee=p("p"),ee.innerHTML=fs,Ye=t(),se=p("p"),se.innerHTML=bs,Fe=t(),le=p("ul"),le.innerHTML=hs,Qe=t(),r(ae.$$.fragment),Se=t(),ne=p("p"),this.h()},l(e){const s=gs("svelte-u9bgzb",document.head);j=o(s,"META",{name:!0,content:!0}),s.forEach(l),pe=n(e),te=o(e,"P",{}),Is(te).forEach(l),oe=n(e),c(J.$$.fragment,e),ie=n(e),w=o(e,"P",{"data-svelte-h":!0}),i(w)!=="svelte-85mzvy"&&(w.innerHTML=De),re=n(e),T=o(e,"P",{"data-svelte-h":!0}),i(T)!=="svelte-9hudq2"&&(T.innerHTML=Oe),ce=n(e),U=o(e,"P",{"data-svelte-h":!0}),i(U)!=="svelte-1nte1oa"&&(U.innerHTML=es),Me=n(e),f=o(e,"P",{"data-svelte-h":!0}),i(f)!=="svelte-sxwk05"&&(f.innerHTML=ss),de=n(e),c(b.$$.fragment,e),me=n(e),h=o(e,"P",{"data-svelte-h":!0}),i(h)!=="svelte-1drpjjm"&&(h.textContent=ls),ue=n(e),I=o(e,"P",{"data-svelte-h":!0}),i(I)!=="svelte-ou03bc"&&(I.innerHTML=as),ye=n(e),B=o(e,"P",{"data-svelte-h":!0}),i(B)!=="svelte-1p7c6jy"&&(B.innerHTML=ts),je=n(e),C=o(e,"P",{"data-svelte-h":!0}),i(C)!=="svelte-3im4jr"&&(C.innerHTML=ns),Je=n(e),_=o(e,"P",{"data-svelte-h":!0}),i(_)!=="svelte-1n3nzkq"&&(_.innerHTML=ps),we=n(e),Z=o(e,"P",{"data-svelte-h":!0}),i(Z)!=="svelte-hjl9w0"&&(Z.innerHTML=os),Te=n(e),q=o(e,"P",{"data-svelte-h":!0}),i(q)!=="svelte-hbriii"&&(q.innerHTML=is),Ue=n(e),c(k.$$.fragment,e),fe=n(e),g=o(e,"P",{"data-svelte-h":!0}),i(g)!=="svelte-1q1g6rb"&&(g.innerHTML=rs),be=n(e),c(A.$$.fragment,e),he=n(e),v=o(e,"P",{"data-svelte-h":!0}),i(v)!=="svelte-1r0c6lg"&&(v.textContent=cs),Ie=n(e),c(H.$$.fragment,e),Be=n(e),E=o(e,"P",{"data-svelte-h":!0}),i(E)!=="svelte-z7p84k"&&(E.innerHTML=Ms),Ce=n(e),c(W.$$.fragment,e),_e=n(e),V=o(e,"P",{"data-svelte-h":!0}),i(V)!=="svelte-v4vfe7"&&(V.innerHTML=ds),Ze=n(e),c(R.$$.fragment,e),qe=n(e),c(z.$$.fragment,e),ke=n(e),G=o(e,"P",{"data-svelte-h":!0}),i(G)!=="svelte-1x3dswg"&&(G.innerHTML=ms),ge=n(e),c(N.$$.fragment,e),Ae=n(e),X=o(e,"P",{"data-svelte-h":!0}),i(X)!=="svelte-664ykw"&&(X.innerHTML=us),ve=n(e),c($.$$.fragment,e),He=n(e),x=o(e,"P",{"data-svelte-h":!0}),i(x)!=="svelte-1cbx8mt"&&(x.innerHTML=ys),Ee=n(e),c(Y.$$.fragment,e),We=n(e),F=o(e,"P",{"data-svelte-h":!0}),i(F)!=="svelte-1av9tan"&&(F.innerHTML=js),Ve=n(e),c(Q.$$.fragment,e),Re=n(e),S=o(e,"P",{"data-svelte-h":!0}),i(S)!=="svelte-iz3f4"&&(S.innerHTML=Js),ze=n(e),c(P.$$.fragment,e),Ge=n(e),c(L.$$.fragment,e),Ne=n(e),K=o(e,"P",{"data-svelte-h":!0}),i(K)!=="svelte-1yvleqa"&&(K.innerHTML=ws),Xe=n(e),D=o(e,"P",{"data-svelte-h":!0}),i(D)!=="svelte-1ywpgxj"&&(D.innerHTML=Ts),$e=n(e),O=o(e,"P",{"data-svelte-h":!0}),i(O)!=="svelte-10dn6d8"&&(O.innerHTML=Us),xe=n(e),ee=o(e,"P",{"data-svelte-h":!0}),i(ee)!=="svelte-1fz3esc"&&(ee.innerHTML=fs),Ye=n(e),se=o(e,"P",{"data-svelte-h":!0}),i(se)!=="svelte-1ssmkmu"&&(se.innerHTML=bs),Fe=n(e),le=o(e,"UL",{"data-svelte-h":!0}),i(le)!=="svelte-15dsdoq"&&(le.innerHTML=hs),Qe=n(e),c(ae.$$.fragment,e),Se=n(e),ne=o(e,"P",{}),Is(ne).forEach(l),this.h()},h(){Bs(j,"name","hf:doc:metadata"),Bs(j,"content",Es)},m(e,s){As(document.head,j),a(e,pe,s),a(e,te,s),a(e,oe,s),M(J,e,s),a(e,ie,s),a(e,w,s),a(e,re,s),a(e,T,s),a(e,ce,s),a(e,U,s),a(e,Me,s),a(e,f,s),a(e,de,s),M(b,e,s),a(e,me,s),a(e,h,s),a(e,ue,s),a(e,I,s),a(e,ye,s),a(e,B,s),a(e,je,s),a(e,C,s),a(e,Je,s),a(e,_,s),a(e,we,s),a(e,Z,s),a(e,Te,s),a(e,q,s),a(e,Ue,s),M(k,e,s),a(e,fe,s),a(e,g,s),a(e,be,s),M(A,e,s),a(e,he,s),a(e,v,s),a(e,Ie,s),M(H,e,s),a(e,Be,s),a(e,E,s),a(e,Ce,s),M(W,e,s),a(e,_e,s),a(e,V,s),a(e,Ze,s),M(R,e,s),a(e,qe,s),M(z,e,s),a(e,ke,s),a(e,G,s),a(e,ge,s),M(N,e,s),a(e,Ae,s),a(e,X,s),a(e,ve,s),M($,e,s),a(e,He,s),a(e,x,s),a(e,Ee,s),M(Y,e,s),a(e,We,s),a(e,F,s),a(e,Ve,s),M(Q,e,s),a(e,Re,s),a(e,S,s),a(e,ze,s),M(P,e,s),a(e,Ge,s),M(L,e,s),a(e,Ne,s),a(e,K,s),a(e,Xe,s),a(e,D,s),a(e,$e,s),a(e,O,s),a(e,xe,s),a(e,ee,s),a(e,Ye,s),a(e,se,s),a(e,Fe,s),a(e,le,s),a(e,Qe,s),M(ae,e,s),a(e,Se,s),a(e,ne,s),Pe=!0},p:_s,i(e){Pe||(d(J.$$.fragment,e),d(b.$$.fragment,e),d(k.$$.fragment,e),d(A.$$.fragment,e),d(H.$$.fragment,e),d(W.$$.fragment,e),d(R.$$.fragment,e),d(z.$$.fragment,e),d(N.$$.fragment,e),d($.$$.fragment,e),d(Y.$$.fragment,e),d(Q.$$.fragment,e),d(P.$$.fragment,e),d(L.$$.fragment,e),d(ae.$$.fragment,e),Pe=!0)},o(e){m(J.$$.fragment,e),m(b.$$.fragment,e),m(k.$$.fragment,e),m(A.$$.fragment,e),m(H.$$.fragment,e),m(W.$$.fragment,e),m(R.$$.fragment,e),m(z.$$.fragment,e),m(N.$$.fragment,e),m($.$$.fragment,e),m(Y.$$.fragment,e),m(Q.$$.fragment,e),m(P.$$.fragment,e),m(L.$$.fragment,e),m(ae.$$.fragment,e),Pe=!1},d(e){e&&(l(pe),l(te),l(oe),l(ie),l(w),l(re),l(T),l(ce),l(U),l(Me),l(f),l(de),l(me),l(h),l(ue),l(I),l(ye),l(B),l(je),l(C),l(Je),l(_),l(we),l(Z),l(Te),l(q),l(Ue),l(fe),l(g),l(be),l(he),l(v),l(Ie),l(Be),l(E),l(Ce),l(_e),l(V),l(Ze),l(qe),l(ke),l(G),l(ge),l(Ae),l(X),l(ve),l(He),l(x),l(Ee),l(We),l(F),l(Ve),l(Re),l(S),l(ze),l(Ge),l(Ne),l(K),l(Xe),l(D),l($e),l(O),l(xe),l(ee),l(Ye),l(se),l(Fe),l(le),l(Qe),l(Se),l(ne)),l(j),u(J,e),u(b,e),u(k,e),u(A,e),u(H,e),u(W,e),u(R,e),u(z,e),u(N,e),u($,e),u(Y,e),u(Q,e),u(P,e),u(L,e),u(ae,e)}}}const Es='{"title":"¿Cómo puedo crear un pipeline personalizado?","local":"cómo-puedo-crear-un-pipeline-personalizado","sections":[{"title":"Añadirlo a la lista de tareas","local":"añadirlo-a-la-lista-de-tareas","sections":[],"depth":2},{"title":"Comparte tu pipeline en el Hub","local":"comparte-tu-pipeline-en-el-hub","sections":[],"depth":2},{"title":"Añadir el pipeline a 🤗 Transformers","local":"añadir-el-pipeline-a--transformers","sections":[],"depth":2}],"depth":1}';function Ws(Ke){return Zs(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class Ns extends qs{constructor(j){super(),ks(this,j,Ws,Hs,Cs,{})}}export{Ns as component}; | |
Xet Storage Details
- Size:
- 33.2 kB
- Xet hash:
- bddf811f5392ba85440aba13a30a40cba5b8c4d5484d935e3e54c54238e30dcf
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.