Skip to content

Commit

Permalink
chore(docs): add playground
Browse files Browse the repository at this point in the history
  • Loading branch information
hanxiao committed May 12, 2022
1 parent 3804367 commit 53efd44
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 0 deletions.
191 changes: 191 additions & 0 deletions docs/_static/demo-embed.html
@@ -0,0 +1,191 @@
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>

<div id="demo-embed">
<table class="embeddingInput">

<tr>
<td>Hover on an image</td>
<td>
<div class="gallery">
<img @mouseover="query='https://picsum.photos/id/'+image.id+'/50'" class="gallery-image"
:src="'https://picsum.photos/id/'+image.id+'/80'" v-for="image in images">
</div>
</td>
</tr>
<tr>
<td>Input a sentence (or an image URL)</td>
<td><textarea v-model="query"
placeholder="Input a sentence or an image URL"
style="width: 80%"
rows="6"
maxlength="1000">
</textarea></td>
</tr>
</table>


<div v-if="query && embedding" class="embeddingChart">

<div>
<p>Done in {{elapsed}}ms</p>
<span>Showing embedding for</span>
<span>
<img class="thumbnail" v-if="isUrl" :src="query" :alt="query + 'is not a valid image'">
<code v-else>{{query}}</code>
</span>
</div>

<div class="embeddingBlock" v-for="value in embedding" v-bind:style="{opacity: normalize_value(value)}"
v-bind:title="value">
<span v-if="showValue">{{value.toString().charAt(3)}}</span>
</div>

<div>

<input type="checkbox" id="checkbox" v-model="showValue"/>
<label for="checkbox">Show embedding values (that visually make no sense but people like it as it was doing
some real science stuff)</label>
</div>

</div>
</div>

<style>
#demo-embed {
font-family: var(--font-stack) !important;
}

.gallery-image:hover {
opacity: 100%;
}

.gallery-image {
opacity: 50%;
transition: opacity 0.3s;
-webkit-transition: opacity 0.3s;
cursor: pointer;
}

.thumbnail {
max-width: 150px;
max-height: 150px;
}


.embeddingBlock {
width: 8px;
height: 8px;
display: inline-flex;
background: green;
border-style: solid;
border-color: white;
border-width: 1px;
font-size: 1vmin;
color: white;
text-align: center;
vertical-align: middle;
justify-content: center;
align-items: center;
transition: opacity 0.3s;
-webkit-transition: opacity 0.3s;
cursor: pointer;
}

.embeddingBlock:hover {
border-color: green;
}


</style>

<script>
function randomIntFromInterval(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min)
}

var app = new Vue({
el: '#demo-embed',
data: {
serverAddress: `http://demo-cas.jina.ai:51001`,
query: 'First do it, then do it right, then do it better',
embedding: [1, 1, 1],
max_embed_value: 0,
min_embed_value: 0,
elapsed: 0,
showValue: true,
images: []
},
computed: {
isUrl: function () {
let url;

try {
url = new URL(this.query);
} catch (_) {
return false;
}

return url.protocol === "http:" || url.protocol === "https:";
},
// get only
payload: function () {
return {
data: [this.isUrl ? {
uri: this.query
} : {
text: this.query
}],
exec_endpoint: '/',
}
}
},
mounted: function () {
this.$nextTick(function () {
app.callJina();

$.getJSON("https://picsum.photos/v2/list?page=" + randomIntFromInterval(1, 10) + "&limit=40", function (json) {
app.images = json
});

})
},
watch: {
query: function (newQ, oldQ) {
this.callJina()
}
},
methods: {
normalize_value(val) {
r = (val - this.min_embed_value) / (this.max_embed_value - this.min_embed_value)
r = (r * 10).toFixed(0) / 10
return r
},
callJina: function () {

$.ajax({
type: "POST",
url: this.serverAddress + "/post",
data: JSON.stringify(this.payload),
contentType: "application/json; charset=utf-8",
dataType: "json",
}).success(function (data, textStatus, jqXHR) {
// data.data[0].embedding
app.embedding = data.data[0].embedding
app.max_embed_value = Math.max.apply(null, app.embedding)
app.min_embed_value = Math.min.apply(null, app.embedding)

date1 = new Date(data.routes[0].startTime)
date2 = new Date(data.routes[0].endTime)
app.elapsed = date2 - date1

console.log('returned!')

}).fail(function () {
console.error("bad connection!")
});
}
}
})

</script>
8 changes: 8 additions & 0 deletions docs/index.md
Expand Up @@ -171,6 +171,14 @@ user-guides/faq
```

```{toctree}
:caption: Playground
:hidden:
playground/embedding
```


```{toctree}
:caption: Developer References
Expand Down
9 changes: 9 additions & 0 deletions docs/playground/embedding.md
@@ -0,0 +1,9 @@
# Text & Image Embedding

Embedding is a basic task in CLIP-as-service. It means converting your input sentence or image into a fixed-length vector. In this demo, you can choose a picture, input a sentence in the textbox, or copy-paste your image URL into the text box to get a rough feeling how CLIP-as-service works.

This is *not* a search task. The images are random stock images and are related to any search results, they are mainly for saving your time on finding some random internet cat pictures.

The model is `ViT-L/14-336px` on one GPU.

<iframe frameborder="0" allowtransparency="true" scrolling="no" src="../../_static/demo-embed.html" style="overflow:hidden;overflow-x:hidden;overflow-y:hidden;height:100vh;width:100%"></iframe>

0 comments on commit 53efd44

Please sign in to comment.