Buckets:
| import{s as it,f as Ze,n as ot,o as nt}from"../chunks/scheduler.37c15a92.js";import{S as rt,i as pt,g as o,s,r as d,A as ut,h as n,f as l,c as i,j as D,u as f,x as p,k as r,y as ct,a,v as h,d as y,t as w,w as b}from"../chunks/index.2bf4358c.js";import{C as F}from"../chunks/CodeBlock.4e987730.js";import{C as mt}from"../chunks/CourseFloatingBanner.9ff4c771.js";import{H as st,E as dt}from"../chunks/getInferenceSnippets.24b50994.js";function ft(He){let M,O,A,ee,g,te,j,le,J,qe="Iniziamo installando Gradio! Essendo una libreria di Python, è sufficiente eseguire:",ae,T,_e="<code>$ pip install gradio</code>",se,x,We=`Puoi usare Gradio ovunque, dalla tua IDE Python preferita, ai Jupyter notebook o anche in Google Colab 🤯! | |
| Quindi, installa Gradio in qualsiasi posto in cui usi Python!`,ie,v,Ve="Iniziamo con un semplice esempio “Hello World” per prendere familiarità con la sintassi di Gradio:",oe,$,ne,G,Re="Analizziamo il codice qui sopra:",re,I,Pe="<li>Per prima cosa, definiamo una funzione chiamata <code>greet()</code>. In questo caso, si tratta di una semplice funzione che aggiunge “Hello” prima di un nome (<em>name</em>), ma questa può essere in generale <em>qualsiasi</em> funzione in Python. Ad esempio, nelle applicazioni di machine learning, questa funzione <em>chiamerebbe un modello per fare una previsione</em> su un input e restituirebbe l’output.</li> <li>Creaiamo puoi una <code>Interface</code> (<em>Interfaccia</em>) di Gradio con tre argomenti, <code>fn</code>, <code>inputs</code>, e <code>outputs</code>. Questi argomenti definiscono la funzione di predizione e il <em>tipo</em> di componenti di ingresso e di uscita che desideriamo. Nel nostro caso, entrambi i componenti sono semplici caselle di testo.</li> <li>Chiamiamo poi il metodo <code>launch()</code> sul <code>Interface</code> creata.</li>",pe,k,Se='Se si esegue questo codice, l’interfaccia qui sotto apparirà automaticamente all’interno di un Jupyter/Colab notebook, o comparirà in un browser <strong><a href="http://localhost:7860/" rel="nofollow">http://localhost:7860</a></strong> se lanciato in uno script.',ue,u,Qe,ce,C,Ee="Prova subito a utilizzare questa GUI con il tuo nome o con un altro input!",me,B,Xe=`Si noterà che in questa GUI, Gradio ha riconosciuto automaticamente il nome del parametro di input (<code>name</code>) | |
| e lo applica come etichetta in cima alla casella di testo. E se si volesse cambiarlo? | |
| O se si volesse personalizzare la casella di testo in qualche altro modo? In questo caso, si può | |
| istanziare una classe che rappresenti il componente in input.`,de,U,Ye="Si osservi l’esempio seguente:",fe,z,he,c,Le,ye,Z,Ne=`Qui abbiamo creato una casella di testo di input con un’etichetta (<code>label</code>), un segnaposto (<code>placeholder</code>) e un numero di righe stabilito (<code>lines</code>). | |
| Si potrebbe fare lo stesso per la casella di testo in output, ma per ora ci fermiamo qui.`,we,H,Fe=`Abbiamo visto che con poche righe di codice, Gradio consente di creare una semplice interfaccia intorno a qualsiasi funzione | |
| con qualsiasi tipo di input o output. In questa sezione abbiamo iniziato con una | |
| semplice casella di testo, ma nelle prossime sezioni tratteremo altri tipi di input e output. Vediamo ora di inserire un po’ di NLP in un’applicazione Gradio.`,be,q,Me,_,Ae="Costruiamo ora una semplice interfaccia che consenta di dimostrare come funziona un modello di <strong>generazione del testo</strong> come GPT-2.",ge,W,Ke=`Caricheremo il nostro modello usando la funzione <code>pipeline()</code> di 🤗 Transformers. | |
| Se hai bisogno di un rapido ripasso, puoi tornare a <a href="/course/chapter1/3#text-generation">quella sezione nel Capitolo 1</a>.`,je,V,De="Per prima cosa, definiamo una funzione di predizione che riceve un prompt di testo e restituisce il testo completato:",Je,R,Te,P,Oe="Questa funzione completa le richieste fornite dall’utente e puoi eseguirla con qualche tuo input per vedere come funziona. Ecco un esempio (potresti ottenere un risultato diverso):",xe,S,ve,Q,$e,E,et="Ora che abbiamo una funzione per generare previsioni, possiamo creare e lanciare una <code>Interface</code> nello stesso modo in cui abbiamo fatto prima:",Ge,X,Ie,Y,tt="Ecco fatto! Ora è possibile utilizzare questa interfaccia per generare testo utilizzando il modello GPT-2 come mostrato qui sotto 🤯.",ke,m,lt,Ce,L,at="Continua a leggere per scoprire come costruire altri tipi di demo con Gradio!",Be,N,Ue,K,ze;return g=new st({props:{title:"Creare la tua prima demo",local:"creare-la-tua-prima-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/chapter9/section2.ipynb"},{label:"Aws Studio",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/chapter9/section2.ipynb"}]}}),$=new F({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">"Hello "</span> + name | |
| demo = gr.Interface(fn=greet, inputs=<span class="hljs-string">"text"</span>, outputs=<span class="hljs-string">"text"</span>) | |
| demo.launch()`,wrap:!1}}),z=new F({props:{code:"aW1wb3J0JTIwZ3JhZGlvJTIwYXMlMjBnciUwQSUwQSUwQWRlZiUyMGdyZWV0KG5hbWUpJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTIySGVsbG8lMjAlMjIlMjAlMkIlMjBuYW1lJTBBJTBBJTBBJTIzJTIwV2UlMjBpbnN0YW50aWF0ZSUyMHRoZSUyMFRleHRib3glMjBjbGFzcyUwQXRleHRib3glMjAlM0QlMjBnci5UZXh0Ym94KGxhYmVsJTNEJTIyVHlwZSUyMHlvdXIlMjBuYW1lJTIwaGVyZSUzQSUyMiUyQyUyMHBsYWNlaG9sZGVyJTNEJTIySm9obiUyMERvZSUyMiUyQyUyMGxpbmVzJTNEMiklMEElMEFnci5JbnRlcmZhY2UoZm4lM0RncmVldCUyQyUyMGlucHV0cyUzRHRleHRib3glMkMlMjBvdXRwdXRzJTNEJTIydGV4dCUyMikubGF1bmNoKCk=",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">"Hello "</span> + name | |
| <span class="hljs-comment"># We instantiate the Textbox class</span> | |
| textbox = gr.Textbox(label=<span class="hljs-string">"Type your name here:"</span>, placeholder=<span class="hljs-string">"John Doe"</span>, lines=<span class="hljs-number">2</span>) | |
| gr.Interface(fn=greet, inputs=textbox, outputs=<span class="hljs-string">"text"</span>).launch()`,wrap:!1}}),q=new st({props:{title:"🤖 Includere le predizioni del modello",local:"-includere-le-predizioni-del-modello",headingTag:"h2"}}),R=new F({props:{code:"ZnJvbSUyMHRyYW5zZm9ybWVycyUyMGltcG9ydCUyMHBpcGVsaW5lJTBBJTBBbW9kZWwlMjAlM0QlMjBwaXBlbGluZSglMjJ0ZXh0LWdlbmVyYXRpb24lMjIpJTBBJTBBJTBBZGVmJTIwcHJlZGljdChwcm9tcHQpJTNBJTBBJTIwJTIwJTIwJTIwY29tcGxldGlvbiUyMCUzRCUyMG1vZGVsKHByb21wdCklNUIwJTVEJTVCJTIyZ2VuZXJhdGVkX3RleHQlMjIlNUQlMEElMjAlMjAlMjAlMjByZXR1cm4lMjBjb21wbGV0aW9u",highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline | |
| model = pipeline(<span class="hljs-string">"text-generation"</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">"generated_text"</span>] | |
| <span class="hljs-keyword">return</span> completion`,wrap:!1}}),S=new F({props:{code:"cHJlZGljdCglMjJNeSUyMGZhdm9yaXRlJTIwcHJvZ3JhbW1pbmclMjBsYW5ndWFnZSUyMGlzJTIyKQ==",highlighted:'<span class="hljs-function"><span class="hljs-title">predict</span><span class="hljs-params">(<span class="hljs-string">"My favorite programming language is"</span>)</span></span>',wrap:!1}}),Q=new F({props:{code:"JTNFJTNFJTIwTXklMjBmYXZvcml0ZSUyMHByb2dyYW1taW5nJTIwbGFuZ3VhZ2UlMjBpcyUyMEhhc2tlbGwuJTIwSSUyMHJlYWxseSUyMGVuam95ZWQlMjB0aGUlMjBIYXNrZWxsJTIwbGFuZ3VhZ2UlMkMlMjBidXQlMjBpdCUyMGRvZXNuJ3QlMjBoYXZlJTIwYWxsJTIwdGhlJTIwZmVhdHVyZXMlMjB0aGF0JTIwY2FuJTIwYmUlMjBhcHBsaWVkJTIwdG8lMjBhbnklMjBvdGhlciUyMGxhbmd1YWdlLiUyMEZvciUyMGV4YW1wbGUlMkMlMjBhbGwlMjBpdCUyMGRvZXMlMjBpcyUyMGNvbXBpbGUlMjB0byUyMGElMjBieXRlJTIwYXJyYXku",highlighted:'>> 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'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}}),X=new F({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">"text"</span>, outputs=<span class="hljs-string">"text"</span>).launch()`,wrap:!1}}),N=new dt({props:{source:"https://github.com/huggingface/course/blob/main/chapters/it/chapter9/2.mdx"}}),{c(){M=o("meta"),O=s(),A=o("p"),ee=s(),d(g.$$.fragment),te=s(),d(j.$$.fragment),le=s(),J=o("p"),J.textContent=qe,ae=s(),T=o("p"),T.innerHTML=_e,se=s(),x=o("p"),x.textContent=We,ie=s(),v=o("p"),v.textContent=Ve,oe=s(),d($.$$.fragment),ne=s(),G=o("p"),G.textContent=Re,re=s(),I=o("ul"),I.innerHTML=Pe,pe=s(),k=o("p"),k.innerHTML=Se,ue=s(),u=o("iframe"),ce=s(),C=o("p"),C.textContent=Ee,me=s(),B=o("p"),B.innerHTML=Xe,de=s(),U=o("p"),U.textContent=Ye,fe=s(),d(z.$$.fragment),he=s(),c=o("iframe"),ye=s(),Z=o("p"),Z.innerHTML=Ne,we=s(),H=o("p"),H.textContent=Fe,be=s(),d(q.$$.fragment),Me=s(),_=o("p"),_.innerHTML=Ae,ge=s(),W=o("p"),W.innerHTML=Ke,je=s(),V=o("p"),V.textContent=De,Je=s(),d(R.$$.fragment),Te=s(),P=o("p"),P.textContent=Oe,xe=s(),d(S.$$.fragment),ve=s(),d(Q.$$.fragment),$e=s(),E=o("p"),E.innerHTML=et,Ge=s(),d(X.$$.fragment),Ie=s(),Y=o("p"),Y.textContent=tt,ke=s(),m=o("iframe"),Ce=s(),L=o("p"),L.textContent=at,Be=s(),d(N.$$.fragment),Ue=s(),K=o("p"),this.h()},l(e){const t=ut("svelte-u9bgzb",document.head);M=n(t,"META",{name:!0,content:!0}),t.forEach(l),O=i(e),A=n(e,"P",{}),D(A).forEach(l),ee=i(e),f(g.$$.fragment,e),te=i(e),f(j.$$.fragment,e),le=i(e),J=n(e,"P",{"data-svelte-h":!0}),p(J)!=="svelte-1kcxbqu"&&(J.textContent=qe),ae=i(e),T=n(e,"P",{"data-svelte-h":!0}),p(T)!=="svelte-sv8g3f"&&(T.innerHTML=_e),se=i(e),x=n(e,"P",{"data-svelte-h":!0}),p(x)!=="svelte-1h87863"&&(x.textContent=We),ie=i(e),v=n(e,"P",{"data-svelte-h":!0}),p(v)!=="svelte-g0ql64"&&(v.textContent=Ve),oe=i(e),f($.$$.fragment,e),ne=i(e),G=n(e,"P",{"data-svelte-h":!0}),p(G)!=="svelte-4froyl"&&(G.textContent=Re),re=i(e),I=n(e,"UL",{"data-svelte-h":!0}),p(I)!=="svelte-1ir6309"&&(I.innerHTML=Pe),pe=i(e),k=n(e,"P",{"data-svelte-h":!0}),p(k)!=="svelte-1slgw3n"&&(k.innerHTML=Se),ue=i(e),u=n(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),D(u).forEach(l),ce=i(e),C=n(e,"P",{"data-svelte-h":!0}),p(C)!=="svelte-jylajh"&&(C.textContent=Ee),me=i(e),B=n(e,"P",{"data-svelte-h":!0}),p(B)!=="svelte-d8u4xy"&&(B.innerHTML=Xe),de=i(e),U=n(e,"P",{"data-svelte-h":!0}),p(U)!=="svelte-4firqo"&&(U.textContent=Ye),fe=i(e),f(z.$$.fragment,e),he=i(e),c=n(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),D(c).forEach(l),ye=i(e),Z=n(e,"P",{"data-svelte-h":!0}),p(Z)!=="svelte-eepfk"&&(Z.innerHTML=Ne),we=i(e),H=n(e,"P",{"data-svelte-h":!0}),p(H)!=="svelte-1os2nng"&&(H.textContent=Fe),be=i(e),f(q.$$.fragment,e),Me=i(e),_=n(e,"P",{"data-svelte-h":!0}),p(_)!=="svelte-7iy06b"&&(_.innerHTML=Ae),ge=i(e),W=n(e,"P",{"data-svelte-h":!0}),p(W)!=="svelte-1bodsle"&&(W.innerHTML=Ke),je=i(e),V=n(e,"P",{"data-svelte-h":!0}),p(V)!=="svelte-1uhkpc2"&&(V.textContent=De),Je=i(e),f(R.$$.fragment,e),Te=i(e),P=n(e,"P",{"data-svelte-h":!0}),p(P)!=="svelte-1jk4usz"&&(P.textContent=Oe),xe=i(e),f(S.$$.fragment,e),ve=i(e),f(Q.$$.fragment,e),$e=i(e),E=n(e,"P",{"data-svelte-h":!0}),p(E)!=="svelte-kegr5g"&&(E.innerHTML=et),Ge=i(e),f(X.$$.fragment,e),Ie=i(e),Y=n(e,"P",{"data-svelte-h":!0}),p(Y)!=="svelte-1tt2799"&&(Y.textContent=tt),ke=i(e),m=n(e,"IFRAME",{src:!0,frameborder:!0,height:!0,title:!0,class:!0,allow:!0,sandbox:!0}),D(m).forEach(l),Ce=i(e),L=n(e,"P",{"data-svelte-h":!0}),p(L)!=="svelte-107ph84"&&(L.textContent=at),Be=i(e),f(N.$$.fragment,e),Ue=i(e),K=n(e,"P",{}),D(K).forEach(l),this.h()},h(){r(M,"name","hf:doc:metadata"),r(M,"content",ht),Ze(u.src,Qe="https://course-demos-hello-world.hf.space")||r(u,"src",Qe),r(u,"frameborder","0"),r(u,"height","250"),r(u,"title","Gradio app"),r(u,"class","container p-0 flex-grow space-iframe"),r(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"),r(u,"sandbox","allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"),Ze(c.src,Le="https://course-demos-hello-world-custom.hf.space")||r(c,"src",Le),r(c,"frameborder","0"),r(c,"height","300"),r(c,"title","Gradio app"),r(c,"class","container p-0 flex-grow space-iframe"),r(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"),r(c,"sandbox","allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"),Ze(m.src,lt="https://course-demos-gpt-2.hf.space")||r(m,"src",lt),r(m,"frameborder","0"),r(m,"height","300"),r(m,"title","Gradio app"),r(m,"class","container p-0 flex-grow space-iframe"),r(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"),r(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),a(e,O,t),a(e,A,t),a(e,ee,t),h(g,e,t),a(e,te,t),h(j,e,t),a(e,le,t),a(e,J,t),a(e,ae,t),a(e,T,t),a(e,se,t),a(e,x,t),a(e,ie,t),a(e,v,t),a(e,oe,t),h($,e,t),a(e,ne,t),a(e,G,t),a(e,re,t),a(e,I,t),a(e,pe,t),a(e,k,t),a(e,ue,t),a(e,u,t),a(e,ce,t),a(e,C,t),a(e,me,t),a(e,B,t),a(e,de,t),a(e,U,t),a(e,fe,t),h(z,e,t),a(e,he,t),a(e,c,t),a(e,ye,t),a(e,Z,t),a(e,we,t),a(e,H,t),a(e,be,t),h(q,e,t),a(e,Me,t),a(e,_,t),a(e,ge,t),a(e,W,t),a(e,je,t),a(e,V,t),a(e,Je,t),h(R,e,t),a(e,Te,t),a(e,P,t),a(e,xe,t),h(S,e,t),a(e,ve,t),h(Q,e,t),a(e,$e,t),a(e,E,t),a(e,Ge,t),h(X,e,t),a(e,Ie,t),a(e,Y,t),a(e,ke,t),a(e,m,t),a(e,Ce,t),a(e,L,t),a(e,Be,t),h(N,e,t),a(e,Ue,t),a(e,K,t),ze=!0},p:ot,i(e){ze||(y(g.$$.fragment,e),y(j.$$.fragment,e),y($.$$.fragment,e),y(z.$$.fragment,e),y(q.$$.fragment,e),y(R.$$.fragment,e),y(S.$$.fragment,e),y(Q.$$.fragment,e),y(X.$$.fragment,e),y(N.$$.fragment,e),ze=!0)},o(e){w(g.$$.fragment,e),w(j.$$.fragment,e),w($.$$.fragment,e),w(z.$$.fragment,e),w(q.$$.fragment,e),w(R.$$.fragment,e),w(S.$$.fragment,e),w(Q.$$.fragment,e),w(X.$$.fragment,e),w(N.$$.fragment,e),ze=!1},d(e){e&&(l(O),l(A),l(ee),l(te),l(le),l(J),l(ae),l(T),l(se),l(x),l(ie),l(v),l(oe),l(ne),l(G),l(re),l(I),l(pe),l(k),l(ue),l(u),l(ce),l(C),l(me),l(B),l(de),l(U),l(fe),l(he),l(c),l(ye),l(Z),l(we),l(H),l(be),l(Me),l(_),l(ge),l(W),l(je),l(V),l(Je),l(Te),l(P),l(xe),l(ve),l($e),l(E),l(Ge),l(Ie),l(Y),l(ke),l(m),l(Ce),l(L),l(Be),l(Ue),l(K)),l(M),b(g,e),b(j,e),b($,e),b(z,e),b(q,e),b(R,e),b(S,e),b(Q,e),b(X,e),b(N,e)}}}const ht='{"title":"Creare la tua prima demo","local":"creare-la-tua-prima-demo","sections":[{"title":"🤖 Includere le predizioni del modello","local":"-includere-le-predizioni-del-modello","sections":[],"depth":2}],"depth":1}';function yt(He){return nt(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class Jt extends rt{constructor(M){super(),pt(this,M,yt,ft,it,{})}}export{Jt as component}; | |
Xet Storage Details
- Size:
- 17.3 kB
- Xet hash:
- ca73ea55e508623b61d70a6a0c1e10fa35b8a7dcc99ef41efc796d61ccbf6e61
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.