Buckets:

rtrm's picture
download
raw
17.2 kB
import{s as it,f as _e,n as nt,o as rt}from"../chunks/scheduler.37c15a92.js";import{S as ot,i as pt,g as n,s,r as d,A as ut,h as r,f as a,c as i,j as K,u as f,x as p,k as o,y as ct,a as l,v as w,d as h,t as y,w as b}from"../chunks/index.2bf4358c.js";import{C as N}from"../chunks/CodeBlock.4e987730.js";import{C as mt}from"../chunks/CourseFloatingBanner.6add7356.js";import{H as st,E as dt}from"../chunks/getInferenceSnippets.ebf8be91.js";function ft(We){let M,O,F,ee,g,te,J,ae,j,He="Să începem prin instalarea Gradio! Întrucât este un pachet Python, pur și simplu rulează:",le,x,Ve="<code>$ pip install gradio</code>",se,T,Se=`Puteți rula Gradio oriunde, fie din IDE-ul tău Python preferat, în notebook-urile Jupyter sau chiar în Google Colab 🤯!
Deci instalați Gradio oriunde rulați Python!`,ie,v,ze="Să începem cu un exemplu simplu “Hello World” pentru a ne familiariza cu sintaxa Gradio:",ne,G,re,$,Pe="Să parcurgem codul de mai sus:",oe,C,Xe="<li>Mai întâi, definim o funcție numită <code>greet()</code>. În acest caz, este o funcție simplă care adaugă “Hello” înaintea numelui tău, dar poate fi <em>orice</em> funcție Python în general. De exemplu, în aplicațiile de machine learning, această funcție ar <em>apela un model pentru a face o predicție</em> pe o intrare și ar returna ieșirea.</li> <li>Apoi, creăm o <code>Interface</code> Gradio cu trei argumente, <code>fn</code>, <code>inputs</code>, și <code>outputs</code>. Aceste argumente definesc funcția de predicție, precum și <em>tipul</em> componentelor de intrare și ieșire pe care le-am dori. În cazul nostru, ambele componente sunt cutii de text simple.</li> <li>Apoi apelăm metoda <code>launch()</code> pe <code>Interface</code>-ul pe care l-am creat.</li>",pe,I,Qe='Dacă rulați acest cod, interfața de mai jos va apărea automat într-un notebook Jupyter/Colab, sau va apărea într-un browser la <strong><a href="http://localhost:7860/" rel="nofollow">http://localhost:7860</a></strong> dacă rulează dintr-un script.',ue,u,Re,ce,B,Ye="Încercați să folosiți această interfață grafică chiar acum cu numele vostru sau cu alte intrări!",me,k,qe=`Veți observa că în această interfață grafică, Gradio a dedus automat numele parametrului de intrare (<code>name</code>)
și l-a aplicat ca etichetă deasupra cutiei de text. Ce se întâmplă dacă doriți să schimbați asta?
Sau dacă doriți să personalizați cutia de text în alt fel? În acest caz, puteți
instanția un obiect de clasă care reprezintă componenta de intrare.`,de,U,Ae="Priviți exemplul de mai jos:",fe,Z,we,c,Le,he,_,Ee=`Aici, am creat o cutie de text de intrare cu o etichetă, un placeholder și un număr setat de linii.
Ați putea face același lucru pentru cutia de text de ieșire, dar o vom lăsa pentru mai târziu.`,ye,W,Ne=`Am văzut că cu doar câteva linii de cod, Gradio vă permite să creați o interfață simplă în jurul oricărei funcții
cu orice tip de intrări sau ieșiri. În această secțiune, am început cu o
cutie de text simplă, dar în următoarele secțiuni, vom acoperi alte tipuri de intrări și ieșiri. Să aruncăm acum o privire la includerea unor NLP într-o aplicație Gradio.`,be,H,Me,V,Fe="Să construim acum o interfață simplă care vă permite să demonstrați un model de <strong>generare de text</strong> ca GPT-2.",ge,S,De=`Vom încărca modelul nostru folosind funcția <code>pipeline()</code> din 🤗 Transformers.
Dacă aveți nevoie de o reîmprospătare rapidă, puteți să vă întoarceți la <a href="/course/chapter1/3#text-generation">acea secțiune din Capitolul 1</a>.`,Je,z,Ke="Primul, definim o funcție de predicție care primește un prompt de text și returnează completarea textului:",je,P,xe,X,Oe="Această funcție completează prompt-urile pe care le furnizați, și puteți să o rulați cu propriile prompt-uri de intrare pentru a vedea cum funcționează. Iată un exemplu (este posibil să obțineți o completare diferită):",Te,Q,ve,R,Ge,Y,et="Acum că avem o funcție pentru generarea predicțiilor, putem crea și lansa o <code>Interface</code> în același mod în care am făcut mai devreme:",$e,q,Ce,A,tt="Asta e! Acum puteți folosi această interfață pentru a genera text folosind modelul GPT-2 așa cum se arată mai jos 🤯.",Ie,m,at,Be,L,lt="Continuați să citiți pentru a vedea cum să construiți alte tipuri de demo-uri cu Gradio!",ke,E,Ue,D,Ze;return g=new st({props:{title:"Construirea primului tău demo",local:"building-your-first-demo",headingTag:"h1"}}),J=new mt({props:{chapter:9,classNames:"absolute z-10 right-0 top-0",notebooks:[{label:"Google Colab",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/en/chapter9/section2.ipynb"},{label:"Aws Studio",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter9/section2.ipynb"}]}}),G=new N({props:{code:"aW1wb3J0JTIwZ3JhZGlvJTIwYXMlMjBnciUwQSUwQSUwQWRlZiUyMGdyZWV0KG5hbWUpJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTIySGVsbG8lMjAlMjIlMjAlMkIlMjBuYW1lJTBBJTBBJTBBZGVtbyUyMCUzRCUyMGdyLkludGVyZmFjZShmbiUzRGdyZWV0JTJDJTIwaW5wdXRzJTNEJTIydGV4dCUyMiUyQyUyMG91dHB1dHMlM0QlMjJ0ZXh0JTIyKSUwQSUwQWRlbW8ubGF1bmNoKCk=",highlighted:`<span class="hljs-keyword">import</span> gradio <span class="hljs-keyword">as</span> gr
<span class="hljs-keyword">def</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params">name</span>):
<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Hello &quot;</span> + name
demo = gr.Interface(fn=greet, inputs=<span class="hljs-string">&quot;text&quot;</span>, outputs=<span class="hljs-string">&quot;text&quot;</span>)
demo.launch()`,wrap:!1}}),Z=new N({props:{code:"aW1wb3J0JTIwZ3JhZGlvJTIwYXMlMjBnciUwQSUwQSUwQWRlZiUyMGdyZWV0KG5hbWUpJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTIySGVsbG8lMjAlMjIlMjAlMkIlMjBuYW1lJTBBJTBBJTBBJTIzJTIwSW5zdGFuJUM4JTlCaWVtJTIwY2xhc2ElMjBUZXh0Ym94JTBBdGV4dGJveCUyMCUzRCUyMGdyLlRleHRib3gobGFiZWwlM0QlMjJUYXN0YSVDOCU5QmklMjBudW1lbGUlMjBhaWNpJTNBJTIyJTJDJTIwcGxhY2Vob2xkZXIlM0QlMjJKb2huJTIwRG9lJTIyJTJDJTIwbGluZXMlM0QyKSUwQSUwQWdyLkludGVyZmFjZShmbiUzRGdyZWV0JTJDJTIwaW5wdXRzJTNEdGV4dGJveCUyQyUyMG91dHB1dHMlM0QlMjJ0ZXh0JTIyKS5sYXVuY2goKQ==",highlighted:`<span class="hljs-keyword">import</span> gradio <span class="hljs-keyword">as</span> gr
<span class="hljs-keyword">def</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params">name</span>):
<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Hello &quot;</span> + name
<span class="hljs-comment"># Instanțiem clasa Textbox</span>
textbox = gr.Textbox(label=<span class="hljs-string">&quot;Tastați numele aici:&quot;</span>, placeholder=<span class="hljs-string">&quot;John Doe&quot;</span>, lines=<span class="hljs-number">2</span>)
gr.Interface(fn=greet, inputs=textbox, outputs=<span class="hljs-string">&quot;text&quot;</span>).launch()`,wrap:!1}}),H=new st({props:{title:"🤖 Includerea predicțiilor modelului",local:"including-model-predictions",headingTag:"h2"}}),P=new N({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMHBpcGVsaW5lJTBBJTBBbW9kZWwlMjAlM0QlMjBwaXBlbGluZSglMjJ0ZXh0LWdlbmVyYXRpb24lMjIpJTBBJTBBJTBBZGVmJTIwcHJlZGljdChwcm9tcHQpJTNBJTBBJTIwJTIwJTIwJTIwY29tcGxldGlvbiUyMCUzRCUyMG1vZGVsKHByb21wdCklNUIwJTVEJTVCJTIyZ2VuZXJhdGVkX3RleHQlMjIlNUQlMEElMjAlMjAlMjAlMjByZXR1cm4lMjBjb21wbGV0aW9u",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline
model = pipeline(<span class="hljs-string">&quot;text-generation&quot;</span>)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">predict</span>(<span class="hljs-params">prompt</span>):
completion = model(prompt)[<span class="hljs-number">0</span>][<span class="hljs-string">&quot;generated_text&quot;</span>]
<span class="hljs-keyword">return</span> completion`,wrap:!1}}),Q=new N({props:{code:"cHJlZGljdCglMjJNeSUyMGZhdm9yaXRlJTIwcHJvZ3JhbW1pbmclMjBsYW5ndWFnZSUyMGlzJTIyKQ==",highlighted:'<span class="hljs-function"><span class="hljs-title">predict</span><span class="hljs-params">(<span class="hljs-string">&quot;My favorite programming language is&quot;</span>)</span></span>',wrap:!1}}),R=new N({props:{code:"JTNFJTNFJTIwTXklMjBmYXZvcml0ZSUyMHByb2dyYW1taW5nJTIwbGFuZ3VhZ2UlMjBpcyUyMEhhc2tlbGwuJTIwSSUyMHJlYWxseSUyMGVuam95ZWQlMjB0aGUlMjBIYXNrZWxsJTIwbGFuZ3VhZ2UlMkMlMjBidXQlMjBpdCUyMGRvZXNuJ3QlMjBoYXZlJTIwYWxsJTIwdGhlJTIwZmVhdHVyZXMlMjB0aGF0JTIwY2FuJTIwYmUlMjBhcHBsaWVkJTIwdG8lMjBhbnklMjBvdGhlciUyMGxhbmd1YWdlLiUyMEZvciUyMGV4YW1wbGUlMkMlMjBhbGwlMjBpdCUyMGRvZXMlMjBpcyUyMGNvbXBpbGUlMjB0byUyMGElMjBieXRlJTIwYXJyYXku",highlighted:'&gt;&gt; My favorite programming language <span class="hljs-keyword">is</span> Haskell. I really enjoyed <span class="hljs-keyword">the</span> Haskell language, <span class="hljs-keyword">but</span> <span class="hljs-keyword">it</span> doesn&#x27;t have all <span class="hljs-keyword">the</span> features <span class="hljs-keyword">that</span> can be applied <span class="hljs-keyword">to</span> any other language. For example, all <span class="hljs-keyword">it</span> <span class="hljs-keyword">does</span> <span class="hljs-keyword">is</span> compile <span class="hljs-keyword">to</span> a byte array.',wrap:!1}}),q=new N({props:{code:"aW1wb3J0JTIwZ3JhZGlvJTIwYXMlMjBnciUwQSUwQWdyLkludGVyZmFjZShmbiUzRHByZWRpY3QlMkMlMjBpbnB1dHMlM0QlMjJ0ZXh0JTIyJTJDJTIwb3V0cHV0cyUzRCUyMnRleHQlMjIpLmxhdW5jaCgp",highlighted:`<span class="hljs-keyword">import</span> gradio <span class="hljs-keyword">as</span> gr
gr.Interface(fn=predict, inputs=<span class="hljs-string">&quot;text&quot;</span>, outputs=<span class="hljs-string">&quot;text&quot;</span>).launch()`,wrap:!1}}),E=new dt({props:{source:"https://github.com/huggingface/course/blob/main/chapters/rum/chapter9/2.mdx"}}),{c(){M=n("meta"),O=s(),F=n("p"),ee=s(),d(g.$$.fragment),te=s(),d(J.$$.fragment),ae=s(),j=n("p"),j.textContent=He,le=s(),x=n("p"),x.innerHTML=Ve,se=s(),T=n("p"),T.textContent=Se,ie=s(),v=n("p"),v.textContent=ze,ne=s(),d(G.$$.fragment),re=s(),$=n("p"),$.textContent=Pe,oe=s(),C=n("ul"),C.innerHTML=Xe,pe=s(),I=n("p"),I.innerHTML=Qe,ue=s(),u=n("iframe"),ce=s(),B=n("p"),B.textContent=Ye,me=s(),k=n("p"),k.innerHTML=qe,de=s(),U=n("p"),U.textContent=Ae,fe=s(),d(Z.$$.fragment),we=s(),c=n("iframe"),he=s(),_=n("p"),_.textContent=Ee,ye=s(),W=n("p"),W.textContent=Ne,be=s(),d(H.$$.fragment),Me=s(),V=n("p"),V.innerHTML=Fe,ge=s(),S=n("p"),S.innerHTML=De,Je=s(),z=n("p"),z.textContent=Ke,je=s(),d(P.$$.fragment),xe=s(),X=n("p"),X.textContent=Oe,Te=s(),d(Q.$$.fragment),ve=s(),d(R.$$.fragment),Ge=s(),Y=n("p"),Y.innerHTML=et,$e=s(),d(q.$$.fragment),Ce=s(),A=n("p"),A.textContent=tt,Ie=s(),m=n("iframe"),Be=s(),L=n("p"),L.textContent=lt,ke=s(),d(E.$$.fragment),Ue=s(),D=n("p"),this.h()},l(e){const t=ut("svelte-u9bgzb",document.head);M=r(t,"META",{name:!0,content:!0}),t.forEach(a),O=i(e),F=r(e,"P",{}),K(F).forEach(a),ee=i(e),f(g.$$.fragment,e),te=i(e),f(J.$$.fragment,e),ae=i(e),j=r(e,"P",{"data-svelte-h":!0}),p(j)!=="svelte-1mpeo5m"&&(j.textContent=He),le=i(e),x=r(e,"P",{"data-svelte-h":!0}),p(x)!=="svelte-sv8g3f"&&(x.innerHTML=Ve),se=i(e),T=r(e,"P",{"data-svelte-h":!0}),p(T)!=="svelte-520pa4"&&(T.textContent=Se),ie=i(e),v=r(e,"P",{"data-svelte-h":!0}),p(v)!=="svelte-4jn981"&&(v.textContent=ze),ne=i(e),f(G.$$.fragment,e),re=i(e),$=r(e,"P",{"data-svelte-h":!0}),p($)!=="svelte-1xbc56o"&&($.textContent=Pe),oe=i(e),C=r(e,"UL",{"data-svelte-h":!0}),p(C)!=="svelte-15fxna1"&&(C.innerHTML=Xe),pe=i(e),I=r(e,"P",{"data-svelte-h":!0}),p(I)!=="svelte-16bxfe1"&&(I.innerHTML=Qe),ue=i(e),u=r(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),K(u).forEach(a),ce=i(e),B=r(e,"P",{"data-svelte-h":!0}),p(B)!=="svelte-1alr80z"&&(B.textContent=Ye),me=i(e),k=r(e,"P",{"data-svelte-h":!0}),p(k)!=="svelte-n6ssxj"&&(k.innerHTML=qe),de=i(e),U=r(e,"P",{"data-svelte-h":!0}),p(U)!=="svelte-c38i6u"&&(U.textContent=Ae),fe=i(e),f(Z.$$.fragment,e),we=i(e),c=r(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),K(c).forEach(a),he=i(e),_=r(e,"P",{"data-svelte-h":!0}),p(_)!=="svelte-1owvoh1"&&(_.textContent=Ee),ye=i(e),W=r(e,"P",{"data-svelte-h":!0}),p(W)!=="svelte-1iwn3vl"&&(W.textContent=Ne),be=i(e),f(H.$$.fragment,e),Me=i(e),V=r(e,"P",{"data-svelte-h":!0}),p(V)!=="svelte-jnkv4s"&&(V.innerHTML=Fe),ge=i(e),S=r(e,"P",{"data-svelte-h":!0}),p(S)!=="svelte-1nba4r4"&&(S.innerHTML=De),Je=i(e),z=r(e,"P",{"data-svelte-h":!0}),p(z)!=="svelte-1b21s7l"&&(z.textContent=Ke),je=i(e),f(P.$$.fragment,e),xe=i(e),X=r(e,"P",{"data-svelte-h":!0}),p(X)!=="svelte-fypnda"&&(X.textContent=Oe),Te=i(e),f(Q.$$.fragment,e),ve=i(e),f(R.$$.fragment,e),Ge=i(e),Y=r(e,"P",{"data-svelte-h":!0}),p(Y)!=="svelte-1xbnsa1"&&(Y.innerHTML=et),$e=i(e),f(q.$$.fragment,e),Ce=i(e),A=r(e,"P",{"data-svelte-h":!0}),p(A)!=="svelte-1t7r68r"&&(A.textContent=tt),Ie=i(e),m=r(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),K(m).forEach(a),Be=i(e),L=r(e,"P",{"data-svelte-h":!0}),p(L)!=="svelte-7qxizh"&&(L.textContent=lt),ke=i(e),f(E.$$.fragment,e),Ue=i(e),D=r(e,"P",{}),K(D).forEach(a),this.h()},h(){o(M,"name","hf:doc:metadata"),o(M,"content",wt),_e(u.src,Re="https://course-demos-hello-world.hf.space")||o(u,"src",Re),o(u,"frameborder","0"),o(u,"height","250"),o(u,"title","Gradio app"),o(u,"class","container p-0 flex-grow space-iframe"),o(u,"allow","accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"),o(u,"sandbox","allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"),_e(c.src,Le="https://course-demos-hello-world-custom.hf.space")||o(c,"src",Le),o(c,"frameborder","0"),o(c,"height","300"),o(c,"title","Gradio app"),o(c,"class","container p-0 flex-grow space-iframe"),o(c,"allow","accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"),o(c,"sandbox","allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"),_e(m.src,at="https://course-demos-gpt-2.hf.space")||o(m,"src",at),o(m,"frameborder","0"),o(m,"height","300"),o(m,"title","Gradio app"),o(m,"class","container p-0 flex-grow space-iframe"),o(m,"allow","accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"),o(m,"sandbox","allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads")},m(e,t){ct(document.head,M),l(e,O,t),l(e,F,t),l(e,ee,t),w(g,e,t),l(e,te,t),w(J,e,t),l(e,ae,t),l(e,j,t),l(e,le,t),l(e,x,t),l(e,se,t),l(e,T,t),l(e,ie,t),l(e,v,t),l(e,ne,t),w(G,e,t),l(e,re,t),l(e,$,t),l(e,oe,t),l(e,C,t),l(e,pe,t),l(e,I,t),l(e,ue,t),l(e,u,t),l(e,ce,t),l(e,B,t),l(e,me,t),l(e,k,t),l(e,de,t),l(e,U,t),l(e,fe,t),w(Z,e,t),l(e,we,t),l(e,c,t),l(e,he,t),l(e,_,t),l(e,ye,t),l(e,W,t),l(e,be,t),w(H,e,t),l(e,Me,t),l(e,V,t),l(e,ge,t),l(e,S,t),l(e,Je,t),l(e,z,t),l(e,je,t),w(P,e,t),l(e,xe,t),l(e,X,t),l(e,Te,t),w(Q,e,t),l(e,ve,t),w(R,e,t),l(e,Ge,t),l(e,Y,t),l(e,$e,t),w(q,e,t),l(e,Ce,t),l(e,A,t),l(e,Ie,t),l(e,m,t),l(e,Be,t),l(e,L,t),l(e,ke,t),w(E,e,t),l(e,Ue,t),l(e,D,t),Ze=!0},p:nt,i(e){Ze||(h(g.$$.fragment,e),h(J.$$.fragment,e),h(G.$$.fragment,e),h(Z.$$.fragment,e),h(H.$$.fragment,e),h(P.$$.fragment,e),h(Q.$$.fragment,e),h(R.$$.fragment,e),h(q.$$.fragment,e),h(E.$$.fragment,e),Ze=!0)},o(e){y(g.$$.fragment,e),y(J.$$.fragment,e),y(G.$$.fragment,e),y(Z.$$.fragment,e),y(H.$$.fragment,e),y(P.$$.fragment,e),y(Q.$$.fragment,e),y(R.$$.fragment,e),y(q.$$.fragment,e),y(E.$$.fragment,e),Ze=!1},d(e){e&&(a(O),a(F),a(ee),a(te),a(ae),a(j),a(le),a(x),a(se),a(T),a(ie),a(v),a(ne),a(re),a($),a(oe),a(C),a(pe),a(I),a(ue),a(u),a(ce),a(B),a(me),a(k),a(de),a(U),a(fe),a(we),a(c),a(he),a(_),a(ye),a(W),a(be),a(Me),a(V),a(ge),a(S),a(Je),a(z),a(je),a(xe),a(X),a(Te),a(ve),a(Ge),a(Y),a($e),a(Ce),a(A),a(Ie),a(m),a(Be),a(L),a(ke),a(Ue),a(D)),a(M),b(g,e),b(J,e),b(G,e),b(Z,e),b(H,e),b(P,e),b(Q,e),b(R,e),b(q,e),b(E,e)}}}const wt='{"title":"Construirea primului tău demo","local":"building-your-first-demo","sections":[{"title":"🤖 Includerea predicțiilor modelului","local":"including-model-predictions","sections":[],"depth":2}],"depth":1}';function ht(We){return rt(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class jt extends ot{constructor(M){super(),pt(this,M,ht,ft,it,{})}}export{jt as component};

Xet Storage Details

Size:
17.2 kB
·
Xet hash:
8b8ff1660f3842ec6eae3689d4f67c110b4f02d340f8eeeb9379803eb9550437

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.