Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: AI

AI

Asking for an embedding

To search by meaning, your app needs each text's embedding. ai.embed(text, as: V) asks the model that ai: { models: } calls embedding for a text's embedding, a V. ai.embed_all(texts, as: V) asks for the embeddings of a list of texts at once, in the same order.

The text is a value built on Text, or a Markdown, never one that may be none. V is a vector type with dimensions:, as many as embedding_dimensions: says the model makes. So a model that changes length is caught before a column holds two kinds of vector. Here the model runs on this machine:

example
application {    connections: {        local_model: {            driver: Driver.openai_compatible            url: config.model_url        }    }    ai: {        connection: local_model        models: {            default: config.drafting_model            embedding: config.search_model        }        embedding_dimensions: 768        limits: {            per_day: {                tokens: 2000000            }        }    }}
example
/// A question's meaning, as the configured embedding model makes it.type QuestionMeaning = Vector {    dimensions: 768}

Like ai.generate, it is an outside call only an action makes. The action maps each of its three failures to a failure of the app's, of kind unavailable:

example
use support/types { CustomerQuestion, QuestionMeaning }use support/failures { AssistantUnavailable }/// What a customer's question means, to search the help articles with.action meaning_of(asked: CustomerQuestion) fails AssistantUnavailable -> QuestionMeaning {    return attempt ai.embed(asked, as: QuestionMeaning) {        timed_out: AssistantUnavailable        over_budget: AssistantUnavailable        too_long: AssistantUnavailable    }}

What the server is sent for "Does your sourdough contain sesame?":

text
POST http://localhost:8000/v1/embeddings{"input": ["Does your sourdough contain sesame?"], "model": "nomic-ai/nomic-embed-text-v1.5"}
  • Each vector is read as V, through json.read's decoding. So a vector of another length, or one of zeros where V compares by cosine, never becomes a V. It means the model isn't the one ai: says, and the call is misconfigured. The built-in driver never asks a model for fewer dimensions: it sends model and input alone.

  • The failures:

    • timed_out: no answer within timeout:, 5 seconds unless you write one. It is counted once in a route's deadline.
    • too_long: a text longer than the model takes, or more than 100 texts in one embed_all. Nothing is sent.
    • over_budget: the call would pass a limit (Budgets).

    ai.embed_all of no texts gives no vectors, without asking.

  • In a test, the ai fake makes each embedding from the text's SHA-256 and the test's seed. The same text always gives the same vector of unit length, and two texts give vectors far apart, so a search for a text finds what was stored for the same text. fakes: { ai.embed: [...] } scripts the failures of ai.embed and ai.embed_all calls, in the order they are made:

example
use support/types { QuestionMeaning }use support/failures { AssistantUnavailable }test "the same question always means the same" {    var asked: QuestionMeaning = attempt meaning_of("Does your sourdough contain sesame?")    var asked_twice: QuestionMeaning = attempt meaning_of("Does your sourdough contain sesame?")    var other: QuestionMeaning = attempt meaning_of("Do you deliver to Jersey?")    assert asked == asked_twice    assert ai.distance(asked, other) > 0.5}test "a question the model can't embed in time goes to a person" {    fakes: {        ai.embed: [timed_out]    }    assert meaning_of("Sesame?") fails AssistantUnavailable}

Markdown for agents: /docs/asking-for-an-embedding.md.Built from Jadpo main at a707efb.