Buckets:

rtrm's picture
download
raw
33.2 kB
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>&quot;abcdef&quot;</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>&quot;test-dynamic-pipeline&quot;</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">&quot;maybe_arg&quot;</span> <span class="hljs-keyword">in</span> kwargs:
preprocess_kwargs[<span class="hljs-string">&quot;maybe_arg&quot;</span>] = kwargs[<span class="hljs-string">&quot;maybe_arg&quot;</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">&quot;input_ids&quot;</span>])
<span class="hljs-keyword">return</span> {<span class="hljs-string">&quot;model_input&quot;</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 == {&quot;model_input&quot;: model_input}</span>
outputs = self.model(**model_inputs)
<span class="hljs-comment"># Quizá {&quot;logits&quot;: 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">&quot;logits&quot;</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">&gt;&gt;&gt; </span>pipe = pipeline(<span class="hljs-string">&quot;my-new-task&quot;</span>)
<span class="hljs-meta">&gt;&gt;&gt; </span>pipe(<span class="hljs-string">&quot;This is a test&quot;</span>)
[{<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;1-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.8</span>}, {<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;2-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.1</span>}, {<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;3-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.05</span>}
{<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;4-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.025</span>}, {<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;5-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.025</span>}]
<span class="hljs-meta">&gt;&gt;&gt; </span>pipe(<span class="hljs-string">&quot;This is a test&quot;</span>, top_k=<span class="hljs-number">2</span>)
[{<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;1-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</span>: <span class="hljs-number">0.8</span>}, {<span class="hljs-string">&quot;label&quot;</span>: <span class="hljs-string">&quot;2-star&quot;</span>, <span class="hljs-string">&quot;score&quot;</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">&quot;logits&quot;</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">&quot;maybe_arg&quot;</span> <span class="hljs-keyword">in</span> kwargs:
preprocess_kwargs[<span class="hljs-string">&quot;maybe_arg&quot;</span>] = kwargs[<span class="hljs-string">&quot;maybe_arg&quot;</span>]
postprocess_kwargs = {}
<span class="hljs-keyword">if</span> <span class="hljs-string">&quot;top_k&quot;</span> <span class="hljs-keyword">in</span> kwargs:
postprocess_kwargs[<span class="hljs-string">&quot;top_k&quot;</span>] = kwargs[<span class="hljs-string">&quot;top_k&quot;</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">&quot;new-task&quot;</span>,
pipeline_class=MyPipeline,
pt_model=AutoModelForSequenceClassification,
)`,wrap:!1}}),R=new y({props:{code:"UElQRUxJTkVfUkVHSVNUUlkucmVnaXN0ZXJfcGlwZWxpbmUoJTBBJTIwJTIwJTIwJTIwJTIybmV3LXRhc2slMjIlMkMlMEElMjAlMjAlMjAlMjBwaXBlbGluZV9jbGFzcyUzRE15UGlwZWxpbmUlMkMlMEElMjAlMjAlMjAlMjBwdF9tb2RlbCUzREF1dG9Nb2RlbEZvclNlcXVlbmNlQ2xhc3NpZmljYXRpb24lMkMlMEElMjAlMjAlMjAlMjBkZWZhdWx0JTNEJTdCJTIycHQlMjIlM0ElMjAoJTIydXNlciUyRmF3ZXNvbWVfbW9kZWwlMjIlMkMlMjAlMjJhYmNkZWYlMjIpJTdEJTJDJTBBJTIwJTIwJTIwJTIwdHlwZSUzRCUyMnRleHQlMjIlMkMlMjAlMjAlMjMlMjB0aXBvJTIwZGUlMjBkYXRvcyUyMHF1ZSUyMG1hbmVqYSUzQSUyMHRleHRvJTJDJTIwYXVkaW8lMkMlMjBpbWFnZW4lMkMlMjBtdWx0aS1tb2RhbGlkYWQlMEEp",highlighted:`PIPELINE_REGISTRY.register_pipeline(
<span class="hljs-string">&quot;new-task&quot;</span>,
pipeline_class=MyPipeline,
pt_model=AutoModelForSequenceClassification,
default={<span class="hljs-string">&quot;pt&quot;</span>: (<span class="hljs-string">&quot;user/awesome_model&quot;</span>, <span class="hljs-string">&quot;abcdef&quot;</span>)},
<span class="hljs-built_in">type</span>=<span class="hljs-string">&quot;text&quot;</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">&quot;second_text&quot;</span> <span class="hljs-keyword">in</span> kwargs:
preprocess_kwargs[<span class="hljs-string">&quot;second_text&quot;</span>] = kwargs[<span class="hljs-string">&quot;second_text&quot;</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">&quot;label&quot;</span>: label, <span class="hljs-string">&quot;score&quot;</span>: score, <span class="hljs-string">&quot;logits&quot;</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">&quot;pair-classification&quot;</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">&quot;pair-classification&quot;</span>, model=<span class="hljs-string">&quot;sgugger/finetuned-bert-mrpc&quot;</span>)`,wrap:!1}}),Q=new y({props:{code:"Y2xhc3NpZmllci5wdXNoX3RvX2h1YiglMjJ0ZXN0LWR5bmFtaWMtcGlwZWxpbmUlMjIp",highlighted:'classifier.push_to_hub(<span class="hljs-string">&quot;test-dynamic-pipeline&quot;</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">&quot;{your_username}/test-dynamic-pipeline&quot;</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.