Skip to content

Embeddings Visualized as Colors

Mixing p5 and embeddings!

Wouldn't it be cool to not only visualize embeddings in a 2d space, but also be able to see the differences between them?

Here's a p5 experiment that does just that! I convert embeddings to colors and then place each of the 1536 vector numbers next to one another. The results are pretty neat!

It seems that a few indexes of the vectors stay strongly constant no matter what quote I pass in. These are visualized below by the strong yellow, pink, and purple cells. Why might this be the case?

Images Generated by Code

generated by...

According to Seneca, God (think Jupiter) sets us back not to punish us but to give us an opportunity to do something courageous and thereby increase our chances of attaining “the highest possible excellence.” God, Seneca explains, hardens, reviews, and disciplines those who have won his approval and love; but those whom he seems to favor, whom he seems to spare, he is keeping soft against the misfortunes that are to come. You are wrong if you think anyone has been exempted from ill; the man who has known happiness for many a year will receive his share some day; whoever seems to have been set free from this has only been granted a delay We should therefore be flattered if we encounter setbacks. Paradoxically, it is evidence that we have caught the attention of God—indeed, that he regards us as a candidate for achieving human excellence. God, says Seneca, knows that “a man needs to be put to the test if he is to gain self-knowledge” and that “only by trying does he learn what his capacities are.”

generated by...

Estimates are corporate currency that trade right up the ladder. If your team refuses to provide you estimates, you can bet that your peers (competitors, if you’re an opportunist) aren’t having the same struggles. Do you want to be the only one without estimates for your boss, who wants her aggregate estimates from all of the dev managers? Do you want her to be sitting in a meeting with her boss, with a single miss on her estimate sheet where her competitors have all of their estimates in? Someone somewhere in the food chain is making a call based on all of those estimates, and that call is a pure matter of self-interest. That person wants to make a bold prediction or strategic play and turn out to be right. Everyone below them in the food chain needs to furnish the best possible information to make this as likely as possible. Good estimates and predictions are how you scratch a superior’s back, with the implicit promise that the superior will then scratch yours. Do you notice something interesting here? If this were a game of musical chairs, then when the music stopped, the line-level developer would be standing. Everyone else in the corporate hierarchy trades in guesses and predictions, strategy and machinations, orders and instructions. The developers are the only ones that trade in actual output. Theirs is the only tangible contribution to the whole pyramid. And significantly, theirs is the only narrative that cannot easily be spun. Being defined by output rather than spun narrative is the essence of the delivery trap.

generated by...

“A lie told once remains a lie, but a lie told a thousand times becomes the truth.”


const embedding = [0.002166514,-0.01843581,-0.0026706716,...] // 1536 from ada-embedding

const min = Math.min(...embedding);
const max = Math.max(...embedding);

const settings = {
  p5: { p5 },
  animate: false,

canvasSketch(({ p5 }) => {
  return ({ p5 }) => {
    // create a grid of squares from embeddings.length
    // assign each square a color from the embedding value

    function mapToRGB(value) {
      return ((value - min) / (max - min)) * 255;

    const rgbValues =;

    const extractRGBValues = (rgbString) => {
      const rgb = rgbString.replace(/[^\d,]/g, "").split(",");
      return => parseInt(value));

    const colors = [];
    for (let i = 0; i < rgbValues.length; i += 3) {
      const r = Math.round(rgbValues[i] || 0);
      const g = Math.round(rgbValues[i + 1] || 0);
      const b = Math.round(rgbValues[i + 2] || 0);
      colors.push(`rgb(${r}, ${g}, ${b})`);

    p5.createCanvas(512, 512);
    p5.drawingContext.setLineDash([0.7, 17]);

    // convert the 512 color values into a grid of squares of 16 x 32
    for (let i = 0; i < 32; i++) {
      for (let j = 0; j < 16; j++) {
        const index = i * 16 + j;
        // if color at colors[index] is less than 128,128,128 add a stroke line around the square -- get # from rgb string ex.rgb(196, 190, 191)

        if (extractRGBValues(colors[index]).some((value) => value < 187)) {
          // random 50% white, 50% black stroke
          p5.stroke(p5.random([0, 255]));
          // p5.stroke(0);
        } else {
        p5.rect(i * 16, j * 32, 16, 32);
}, settings); is a reader-supported published Zettelkasten. Both free and paid subscriptions are available. If you want to support my work, the best way is by taking out a paid subscription.