Public
Edited
Jan 3, 2023
2 stars
Insert cell
Insert cell
viewof q = Inputs.text({ placeholder: "Search for blog entry", submit: true })
Insert cell
(results.length &&
md`## [${results[0].title}](https://simonwillison.net/e/${results[0].id})

${results[0].body.slice(0, 1000)}`) ||
md``
Insert cell
similarEntries &&
md`## Similar posts\n\n${similarEntries
.map(
(entry) => `- [${entry.title}](https://simonwillison.net/e/${entry.id})`
)
.join("\n")}`
Insert cell
results = (q &&
(
await fetch(
`https://datasette.simonwillison.net/simonwillisonblog.json?sql=${encodeURIComponent(
searchSql
)}&search=${encodeURIComponent(q)}&_shape=array`
)
).json()) ||
[]
Insert cell
searchSql = `select
blog_entry.id,
blog_entry.title,
blog_entry.slug,
blog_entry.body,
blog_entry.created
from
blog_entry
join blog_entry_fts on blog_entry.rowid = blog_entry_fts.rowid
where
blog_entry_fts match escape_fts(:search)
order by
blog_entry_fts.rank
limit
1`
Insert cell
blog.db
select id, embedding from embeddings
Insert cell
floats = new Float32Array(embedding[0].embedding.buffer)
Insert cell
documents = embedding.map(({ id, embedding }) => ({
id,
embedding: new Float32Array(embedding.buffer)
}))
Insert cell
function cosineSimilarity(vec1, vec2) {
let dotProduct = 0;
let norm1 = 0;
let norm2 = 0;

for (let i = 0; i < vec1.length; i++) {
dotProduct += vec1[i] * vec2[i];
norm1 += vec1[i] ** 2;
norm2 += vec2[i] ** 2;
}

return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}
Insert cell
function findSimilar(documentId) {
let vector;
try {
vector = documents.filter((d) => d.id == documentId)[0].embedding;
} catch {
return [];
}
// Calculate cosine similarity for every other document
let similarities = documents
.filter((d) => d.id != documentId)
.map((doc) => ({
...doc,
score: cosineSimilarity(doc.embedding, vector)
}));
similarities.sort((a, b) => b.score - a.score);
return similarities.slice(0, 10);
}
Insert cell
similar = findSimilar("" + results[0].id)
Insert cell
where = similar.map((d) => d.id).join(", ")
Insert cell
whens = similar.map((d, i) => `when ${d.id} then ${i}`).join("\n ")
Insert cell
entrySql = `
select * from blog_entry
where id in (${where})
order by case id
${whens}
end
`
Insert cell
similarEntries = (similar.length &&
(
await fetch(
`https://datasette.simonwillison.net/simonwillisonblog.json?sql=${encodeURIComponent(
entrySql
)}&_shape=array`
)
).json()) ||
[]
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more