Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display machine learning demos from Replicate.com #257

Merged
merged 21 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions browse/static/css/arXiv.css
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,47 @@ p.tagline {

/*END Papers With Code css*/

/*BEGIN Replicate CSS*/

.replicate-model {
margin-bottom: 20px;
padding: 15px 0;
display: block;
display: flex;
}

.replicate-model-image {
width: 100px;
height: 100px;
object-position: center;
object-fit: cover;
flex-grow: 0;
flex-shrink: 0;
}

.replicate-model-details {
padding: 10px 15px;
vertical-align: top;
}

.replicate-model-details-heading {
margin: 0;
padding: 0;
}

.replicate-model-prediction-count {
opacity: 0.5;
}

.replicate-model-prediction-icon {
height:.9rem;
width:.9rem;
margin-right: 0;
margin-top: -.15rem;
}

/*END Replicate CSS*/

/*LABS in TABS on ABS*/
/*CSS-only, responsive tabbed display */
#labstabs {
Expand Down
87 changes: 87 additions & 0 deletions browse/static/js/replicate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Labs integration for displaying machine learning demos from replicate.com

(function() {
const container = document.getElementById("replicate-output")
const containerAlreadyHasContent = container.innerHTML.trim().length > 0

// This script is invoked every time the Labs toggle is toggled, even when
// it's toggled to disabled. So this check short-circuits the script if the
// container already has content.
if (containerAlreadyHasContent) {
container.innerHTML = ""
container.setAttribute("style", "display:none")
return
} else {
container.setAttribute("style", "display:block")
}

// Get the arXiv paper ID from the URL, e.g. "2103.17249"
// (this can be overridden for testing by passing a override_paper_id query parameter in the URL)
const params = new URLSearchParams(document.location.search)
const arxivPaperId = params.get("override_paper_id") || window.location.pathname.split('/').reverse()[0]
if (!arxivPaperId) return

const replicateHost = "https://replicate.com"
const replicateApiUrl = `${replicateHost}/api/v1/models?arxiv_paper_id=${arxivPaperId}`

// Search the Replicate API for models that implement this paper
fetch(replicateApiUrl).then(response => {
if (response.ok) {
return response.json()
} else {
console.error(`Unable to fetch model data from ${replicateHost}`)
return Promise.reject(response.status)
}
})
.then(data => render(data))
.catch(error => console.log(error))

// Generate HTML, sanitize it to prevent XSS, and inject into the DOM
function render({ models }) {
container.innerHTML = window.DOMPurify.sanitize(`
${noModelsFound(models)}
${models.map(model => renderModel(model))}
`)
}

function noModelsFound(models) {
if (models.length === 0) {
return `<p>
No demos found for this article. You can <a href="https://replicate.com/docs/arxiv?utm_source=arxiv&arxiv_paper_id=${arxivPaperId}">add one here</a>.
</p>`
} else {
return ``
}
}

function renderModel(model) {
return `
<div class="replicate-model">
<a href="${model.absolute_url}?utm_source=arxiv">
<img src="${model.cover_image}" class="replicate-model-image" />
</a>
<div class="replicate-model-details">
<a href="${model.absolute_url}?utm_source=arxiv">
<h3 class="replicate-model-details-heading">${model.username}/${model.name}</h3>
</a>
<p>${model.description}</p>

<p class="replicate-model-prediction-count">
${rocketIcon()}
${new Intl.NumberFormat().format(Number(model.prediction_count || 0))}
run${Number(model.prediction_count) === 1 ? "" : "s"}
</p>
</div>
</div>
`
}

function rocketIcon() {
return `
<svg class="replicate-model-prediction-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill-rule="evenodd" d="M20.322.75a10.75 10.75 0 00-7.373 2.926l-1.304 1.23A23.743 23.743 0 0010.103 6.5H5.066a1.75 1.75 0 00-1.5.85l-2.71 4.514a.75.75 0 00.49 1.12l4.571.963c.039.049.082.096.129.14L8.04 15.96l1.872 1.994c.044.047.091.09.14.129l.963 4.572a.75.75 0 001.12.488l4.514-2.709a1.75 1.75 0 00.85-1.5v-5.038a23.741 23.741 0 001.596-1.542l1.228-1.304a10.75 10.75 0 002.925-7.374V2.499A1.75 1.75 0 0021.498.75h-1.177zM16 15.112c-.333.248-.672.487-1.018.718l-3.393 2.262.678 3.223 3.612-2.167a.25.25 0 00.121-.214v-3.822zm-10.092-2.7L8.17 9.017c.23-.346.47-.685.717-1.017H5.066a.25.25 0 00-.214.121l-2.167 3.612 3.223.679zm8.07-7.644a9.25 9.25 0 016.344-2.518h1.177a.25.25 0 01.25.25v1.176a9.25 9.25 0 01-2.517 6.346l-1.228 1.303a22.248 22.248 0 01-3.854 3.257l-3.288 2.192-1.743-1.858a.764.764 0 00-.034-.034l-1.859-1.744 2.193-3.29a22.248 22.248 0 013.255-3.851l1.304-1.23zM17.5 8a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zm-11 13c.9-.9.9-2.6 0-3.5-.9-.9-2.6-.9-3.5 0-1.209 1.209-1.445 3.901-1.49 4.743a.232.232 0 00.247.247c.842-.045 3.534-.281 4.743-1.49z"></path>
</svg>
`
}

})();
44 changes: 43 additions & 1 deletion browse/static/js/toggle-labs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ $(document).ready(function() {

var scripts = {
"paperwithcode": $('#paperwithcode-toggle').data('script-url') + "?20210727",
"replicate": $('#replicate-toggle').data('script-url'),
"litmaps": $('#litmaps-toggle').data('script-url'),
"scite": $('#scite-toggle').data('script-url'),
"connectedpapers": $('#connectedpapers-toggle').data('script-url'),
Expand All @@ -28,11 +29,27 @@ $(document).ready(function() {

var pwcEnabled = true;

const currentCategory = $('.current')?.text()?.toLowerCase();
const demoCategories = [
"cs", // Computer Science
"eess", // Electrical Engineering and Systems Science
"stat" // Statistics
]

const demosEnabled = currentCategory && demoCategories.some(category => currentCategory.startsWith(category));

if (demosEnabled) {
document.getElementById("labstabs-demos-input").removeAttribute("disabled");
document.getElementById("labstabs-demos-label").style.display = "block";
}

var replicateEnabled = demosEnabled

var labsCookie = Cookies.getJSON("arxiv_labs");
if (labsCookie) {
has_enabled = false;
if ( labsCookie["last_tab"] ){
$("input#"+labsCookie["last_tab"]).click();
$(`input#${labsCookie["last_tab"]}:not([disabled])`).click();
}
for (var key in labsCookie) {
if (labsCookie[key] && labsCookie[key] == "enabled") {
Expand All @@ -58,6 +75,12 @@ $(document).ready(function() {
$.cachedScript(scripts["paperwithcode"]).done(function(script, textStatus) {
console.log(textStatus);
});
} else if (key === "replicate-toggle") {
$.cachedScript(scripts["replicate"]).done(function(script, textStatus) {
// console.log(textStatus, "replicate (on cookie check)");
}).fail(function() {
console.error("failed to load replicate script (on cookie check)", arguments)
});
} else if (key === "connectedpapers-toggle") {
$.cachedScript(scripts["connectedpapers"]).done(function(script, textStatus) {
console.log(textStatus);
Expand All @@ -67,6 +90,9 @@ $(document).ready(function() {
if (key === "paperwithcode-toggle") {
pwcEnabled = false;
}
if (key === "replicate-toggle") {
replicateEnabled = false;
}
}
}
} else {
Expand All @@ -79,6 +105,16 @@ $(document).ready(function() {
console.log(textStatus);
});
}

if(replicateEnabled){
$("#replicate-toggle.lab-toggle").toggleClass("enabled",true);
$.cachedScript(scripts["replicate"]).done(function(script, textStatus) {
// console.log(textStatus, "replicate (on load)");
}).fail(function() {
console.error("failed to load replicate script (on load)", arguments)
});;
}

// record last-clicked tab
$("div.labstabs input[name='tabs']").on("click", function() {
var labsCookie = Cookies.getJSON("arxiv_labs") || {};
Expand Down Expand Up @@ -123,6 +159,12 @@ $(document).ready(function() {
$.cachedScript(scripts["paperwithcode"]).done(function(script, textStatus) {
console.log(textStatus);
});
} else if ($(this).attr("id") == "replicate-toggle") {
$.cachedScript(scripts["replicate"]).done(function(script, textStatus) {
// console.log(textStatus, "replicate (on lab toggle)");
}).fail(function() {
console.error("failed to load replicate script (on lab toggle)", arguments)
});
} else if ($(this).attr("id") == "connectedpapers-toggle") {
$.cachedScript(scripts["connectedpapers"]).done(function(script, textStatus) {
console.log(textStatus);
Expand Down
1 change: 1 addition & 0 deletions browse/templates/abs/abs.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{# <link rel="stylesheet" type="text/css" media="screen" href="{{ url_for('static', filename='css/paperwithcode.css') }}" /> #}
<script src="//code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="//cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js" type="text/javascript"></script>
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js"></script>
<script src="{{ url_for('static', filename='js/toggle-labs.js') }}?20210728" type="text/javascript"></script>
<script src="{{ url_for('static', filename='js/cite.js') }}" type="text/javascript"></script>
{%- endif %}
Expand Down
36 changes: 32 additions & 4 deletions browse/templates/abs/labs_tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,37 @@ <h1>Code and Data Associated with this Article</h1>
<div id="pwc-data-output"></div>
</div>

<!--
hide the "Demos" tab by default, and conditionally display it using
JavaScript on pages in specific categories like `cs`, `eess``, and `stat`
-->
<input type="radio" name="tabs" id="labstabs-demos-input" disabled>
<label for="labstabs-demos-input" id="labstabs-demos-label" style="display:none">Demos</label>
<div class="tab">
<h1>Demos Associated with this Article</h1>
<div class="toggle">
<div class="columns is-mobile lab-row">
<div class="column lab-switch">
<label class="switch">
<input
id="replicate-toggle"
data-script-url="{{ url_for('static', filename='js/replicate.js') }}"
type="checkbox" class="lab-toggle" aria-labelledby="label-for-replicate">
<span class="slider"></span>
<span class="is-sr-only">Replicate Demos Toggle</span>
</label>
</div>
<div class="column lab-name">
<span id="label-for-replicate">Replicate Demos</span> <em>(<a href="https://labs.arxiv.org/" target="_blank">What is this?</a>)</em>
</div>
</div>
</div>
<div id="replicate-output"></div>
</div>


<input type="radio" name="tabs" id="tabthree">
<label for="tabthree">Related Papers</label>
<input type="radio" name="tabs" id="tabfour">
<label for="tabfour">Related Papers</label>
<div class="tab">
<h1>Recommenders and Search Tools</h1>
<div class="toggle">
Expand Down Expand Up @@ -138,8 +166,8 @@ <h1>Recommenders and Search Tools</h1>
</div>


<input type="radio" name="tabs" id="tabfour">
<label for="tabfour">
<input type="radio" name="tabs" id="tabfive">
<label for="tabfive">
About arXivLabs
</label>
<div class="tab">
Expand Down