Skip to main content
Follow this short guide to get up and running with the Isaacus API by embedding your first legal query and document with Kanon 2 Embedder, the world’s most accurate legal AI embedder. If you’re looking to perform tasks other than embedding with the Isaacus API (e.g., reranking, extractive question answering or universal classification), follow the first two steps of this guide to set up your account and API client, and then check out the capabilities section of our documentation for information on how to use our API for those tasks.

1. Set up your account

Head to the Isaacus Platform to create a new account. Once signed up, add a payment method to claim your free credits. After adding a payment method, create a new API key. Make sure to keep your API key safe. You won’t be able to see it again after you create it. But don’t worry, you can always generate a new one.

2. Install the Isaacus API client

Now that your account is set up, install our Python or server-side JavaScript/TypeScript API client (or check out our API reference if you’re not using either of those languages).
pip install isaacus

3. Embed a document

With our API client installed, let’s embed our first legal query and document. To start, you need to initialize the client with your API key. You can do this by setting the ISAACUS_API_KEY environment variable or by passing it directly, which is what we’re doing in this example.
from isaacus import Isaacus

client = Isaacus(api_key="PASTE_YOUR_API_KEY_HERE") # Or `AsyncIsaacus(api_key="...")` if you'd like to use our async client.
Next, let’s grab a legal document to embed. For this example, we’ll use GitHub’s terms of service.
tos = client.get(path="https://examples.isaacus.com/github-tos.md", cast_to=str)
We’re going to embed the terms of service using Kanon 2 Embedder, the world’s most accurate legal AI embedder. What is an embedder? An embedder is an AI model that converts content into a highly compressed numerical representation, known as an embedding, that can be compared mathematically with other embeddings to quantify how similar they are in meaning. Embeddings are used to power semantic search engines, text classification, and cluster analysis as well as the retrieval component of retrieval-augmented generation (RAG) applications. Right now, we’re interested in retrieving the GitHub terms of service given a search query about it. To do that, we’ll first embed the document using the .embeddings.create() method of our API client. We’ll also make sure to flag that we’re embedding a document by setting the task parameter to "retrieval/document". This will help our embedder produce an embedding that is optimized specifically for being retrieved. We recommend always setting the task parameter to either "retrieval/document" or "retrieval/query" when using our embedders for retrieval tasks, even if the text in question is not strictly a document or a query, so long as one text is being treated as something to be retrieved, and the other as something to retrieve it with.
document_response = client.embeddings.create(
    model="kanon-2-embedder",
    texts=tos, # You can pass a single text or a list of texts here.
    task="retrieval/document",
)
Since we only passed a single document to the embedder, let’s unpack the first embedding result, accessible at document_response.embeddings[0], in addition to our usage statistics.
document_embedding_data = document_response.embeddings[0]
document_embedding = document_embedding_data.embedding
document_index = document_embedding_data.index

document_embedding_usage = document_response.usage
document_response.embeddings is an array of embedding results, sorted in the same order as the input texts. Each embedding result contains embedding, which is the actual embedding, and index, which is the index of the input text that the embedding corresponds to (starting from 00). document_response.usage contains statistics about the usage of resources in the process of generating the embedding. document_response.usage.input_tokens will give you the number of tokens inputted into the embedder, which you can cross-reference with our pricing to estimate the cost of embedding the document (excluding applicable taxes). Now, let’s embed two search queries, one that is clearly relevant to the document and another that is clearly irrelevant. This time we set our task parameter to "retrieval/query" to indicate that we’re embedding a search query.
query_responses = client.embeddings.create(
    model="kanon-2-embedder",
    texts=[
        "What are GitHub's billing policies?", # This is a relevant query.
        "What are Microsoft's billing policies?", # This is an irrelevant query.
    ],
    task="retrieval/query",
)

query_embeddings = query_responses.embeddings
relevant_query_embedding = query_embeddings[0].embedding
irrelevant_query_embedding = query_embeddings[1].embedding
To assess the relevance of the queries to the document, we can compute the cosine similarity between their embeddings and the document embedding. Cosine similarity measures how similar two sets of numbers are (specifically, the cosine of the angle between two vectors in an inner product space). In theory, it ranges from 1-1 to 11, with 11 indicating that the vectors are identical, 00 indicating that they are orthogonal (i.e., completely dissimilar), and 1-1 indicating that they are diametrically opposed. In practice, however, it tends to range from 00 to 11 for text embeddings (since they are usually non-negative). Our embedders have been optimized such that the cosine similarity of the embeddings they produce roughly corresponds to how similar the original texts are in meaning. Unlike our universal classifiers, however, our embedders’ scores have not been calibrated to be interpreted as probabilities, only as relative measures of similarity, making them most useful for ranking search results. For the sake of convenience, our Python example uses numpy’s dot function to compute the dot product of our embeddings (which is equivalent to their cosine similarity since all our embeddings are L2-normalized). If you prefer, you can use another library to compute the cosine similarity of the embeddings (e.g., torch via torch.nn.functional.cosine_similarity), or you could write your own implementation (as we do for our JavaScript example).
import numpy as np

relevant_similarity = np.dot(relevant_query_embedding, document_embedding)
irrelevant_similarity = np.dot(irrelevant_query_embedding, document_embedding)

print(f"Similarity of relevant query to the document: {relevant_similarity * 100:.2f}")
print(f"Similarity of irrelevant query to the document: {irrelevant_similarity * 100:.2f}")
The output should look something like this:
Similarity of relevant query to the document: 52.87
Similarity of irrelevant query to the document: 24.86
As you should see, the relevant query has a much higher similarity score to the document than the irrelevant query, indicating that our embedder has successfully captured the semantic meaning of the texts. And that’s it! You’ve just successfully embedded a legal document and queries using the Isaacus API.

4. Next steps

Beyond the examples we’ve shared here, there’s a lot more that you can do with the Isaacus API. To learn how to take full advantage of the API, you can check out our:
  1. Capabilities section, which covers the full range of tasks the Isaacus API supports, including embedding, reranking, extractive question answering and universal classification.
  2. API reference, which documents how to interface with our API and the endpoints and parameters that are available.
  3. Pricing section, which shows just how affordable our API is.
If you’re ever unsure about how to use the Isaacus API or if you have any other questions, we also encourage you to reach out to us. We’re always happy to help.
I