Lesson illustration

Generating Text Embeddings with OpenAI API

Hello! In our previous lesson, we built the conceptual foundation for an agent's long-term memory by exploring what text embeddings are and how they capture semantic meaning in a high-dimensional vector space. We established that this numerical representation is the key to enabling machines to "understand" and compare text.

Today, we transition from the "what" to the "how." This lesson is all about practice. Our objective is to generate text embeddings using an API like OpenAI's. You will write Python code to call the embeddings endpoint, convert text into vectors, and see how this process works on both single strings and larger datasets. This is the first practical step in building the Retrieval-Augmented Generation (RAG) system that will give our future e-commerce agent a powerful, searchable knowledge base.

The Embeddings API Endpoint

Just as you've used the openai Python library to interact with the Chat Completions API, we will use the same library to access the Embeddings API. The process is very similar: you authenticate, prepare your input, and make a request to a specific endpoint.

The overall workflow we are beginning to implement looks like this:

{"type":"image","url":"https://cdn.prod.website-files.com/6064b31ff49a2d31e0493af1/66d7ef1af0b93a6983763f91_AD_4nXeh1zDTNEqu4Q5HW4CByGVRVtHHnJqOeLmWoKq508v8a04FRDMc7ikZQSbRoAXaS7iRdLXw9CtvRdZxxUBTU3kWQFEoeF_c6TXjOeCE1m669KEyvMcxKxTqQZqKNA6KpMHohfpumTZABovZazmP4HqEztA.png","caption":"This diagram shows the end-to-end process for creating a knowledge base. Source documents are converted into text, which an embedding engine (like OpenAI's) transforms into vectors. These vectors, along with the original text and metadata, are then stored in a database for later retrieval.","isV2":true,"blockId":"bc6b3398-534c-425d-a703-33a67e5e840b","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



In this lesson, we are focused on the central part of this diagram: taking source text and using the OpenAI Embedding Engine to create vectors.

{"type":"image","url":"https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2024/01/30/ml-15931-image001.png","caption":"As a quick reminder, the embedding model takes text as input and produces a numerical vector as output. Texts with similar meanings, like 'New York' and 'Paris', will have vectors that are numerically closer to each other than to dissimilar concepts like 'Animal' or 'Horse'.","isV2":true,"blockId":"be15dd0f-fad6-4eb7-b6d8-ef37e9feb860","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



To generate an embedding, you will primarily use the client.embeddings.create() method from the OpenAI Python client. The two most important parameters are:

  • model: The name of the embedding model you want to use.
  • input: The text you want to embed. This can be a single string or a list of strings for batch processing.

Let's look at the official documentation for the basic API call structure.

{"type":"reading","par_intro":"The official OpenAI API documentation provides the most direct and accurate examples. This section shows the fundamental API call in Python.","par_directions":"In the document, find the section <span data-type=\"resource_reading_textrange\" data-resource-subitem-id=\"3683e6e4\" data-range-start=\"How to get embeddings\" data-range-end=\"embeddings API endpoint\">How to get embeddings</span>. Focus on the Python code snippet. Observe how the `client.embeddings.create` method is called and note the structure of the JSON response that is returned. Pay particular attention to how the actual vector is accessed via `response.data[0].embedding`.","learning_duration":"5 minutes","url":"https://developers.openai.com/api/docs/guides/embeddings/","title":"Vector embeddings | OpenAI API","isV2":true,"blockId":"ed6d477e-e4ce-43f6-b43f-80862481e38f","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



As you saw in the documentation, the API call is straightforward. Assuming you have your OPENAI_API_KEY configured as an environment variable (as we did in Module 1), the code looks like this:

from openai import OpenAI
client = OpenAI()




# The text we want to embed
text_to_embed = "Organic Cotton Crewneck T-Shirt"




# Call the API
response = client.embeddings.create(
    input=text_to_embed,
    model="text-embedding-3-small"
)




# Extract the embedding vector
embedding_vector = response.data[0].embedding

print(f"Embedding vector for '{text_to_embed}':")



# Print the first 5 dimensions for brevity
print(embedding_vector[:5]) 
print(f"Vector dimensions: {len(embedding_vector)}")

Running this code would produce an output showing the first few numbers of the vector and its total size. For the text-embedding-3-small model, this is a list of 1536 floating-point numbers.

{
  "type": "exercise",
  "id": "8ee41dde-a5a2-4067-9dfe-17c994144965"
}

Choosing the Right Embedding Model

OpenAI provides several embedding models, each with different performance, cost, and dimensionality characteristics. The choice of model is a trade-off you'll often make in a business context.

The official documentation provides a helpful comparison table.

{"type":"reading","par_intro":"This reading will help you understand the available model options.","par_directions":"Please read the section titled <span data-type=\"resource_reading_textrange\" data-resource-subitem-id=\"16835b85\" data-range-start=\"Embedding models\" data-range-end=\"8192\">Embedding models</span>. The table compares the new third-generation models (`-3-small`, `-3-large`) with the previous generation model (`ada-002`) on cost and performance.","learning_duration":"3 minutes","url":"https://developers.openai.com/api/docs/guides/embeddings/","title":"Vector embeddings | OpenAI API","isV2":true,"blockId":"5cae7081-40ed-4f5c-bddd-00c82e0a9f3e","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



For most applications, including the ones we'll build in this course, text-embedding-3-small offers an excellent balance. It's highly performant, significantly cheaper than its larger counterpart, and outperforms the older ada-002 model. We will use it as our default.

Batch Processing for Efficiency

Imagine you have an entire product catalog with thousands of items to embed for your e-commerce agent. Making a separate API call for each product would be slow and inefficient. Fortunately, the embeddings API is designed for batching. You can pass a list of strings to the input parameter in a single API call.

The following guide provides a clear example of generating embeddings for multiple texts at once and introduces a function to compare them.

{"type":"reading","par_intro":"This article from Deepnote provides a practical, self-contained example of batching embedding requests and comparing the results.","par_directions":"Read the section <span data-type=\"resource_reading_textrange\" data-resource-subitem-id=\"da461106\" data-range-start=\"Working with embeddings for semantic search\" data-range-end=\"like K-means in the vector space, to discover topics.\">Working with embeddings</span>. Pay close attention to the Python code block under the \"Example – generating and using embeddings\" sub-heading. Notice how a list of three strings is passed to the `input` parameter of `openai.Embedding.create`.\n\nThe example also defines a `cosine_similarity` function to measure the \"distance\" between the resulting vectors. This is a crucial concept that we will explore in depth in our very next lesson, but seeing it here gives you a preview of *why* we are generating these vectors.","learning_duration":"10 minutes","url":"https://deepnote.com/blog/ultimate-guide-to-openai-python-library-in-python","title":"Ultimate guide to OpenAI library in Python","isV2":true,"blockId":"98c2dd44-6106-4bb2-96fa-60bfb53d1468","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



Let's adapt that example for our e-commerce context. Suppose we want to see how semantically similar different product titles are:

import numpy as np
from openai import OpenAI

client = OpenAI()

def cosine_similarity(v1, v2):
    """Calculates the cosine similarity between two vectors."""
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

product_titles = [
    "Men's Classic Leather Wallet",
    "Slim Bifold Wallet with RFID Blocking",
    "Gourmet Dark Chocolate Bar (70% Cacao)",
]

response = client.embeddings.create(
    input=product_titles,
    model="text-embedding-3-small"
)




# Extract the embedding vectors from the response
embeddings = [item.embedding for item in response.data]




# Compare the similarity between the product titles
sim_1_2 = cosine_similarity(embeddings[0], embeddings[1]) # Wallet vs. Wallet
sim_1_3 = cosine_similarity(embeddings[0], embeddings[2]) # Wallet vs. Chocolate

print(f"Similarity between '{product_titles[0]}' and '{product_titles[1]}': {sim_1_2:.4f}")
print(f"Similarity between '{product_titles[0]}' and '{product_titles[2]}': {sim_1_3:.4f}")

If you were to run this code, you would see a high similarity score (e.g., > 0.8) for the two wallet descriptions and a very low score (e.g., < 0.3) when comparing a wallet to a chocolate bar. This demonstrates the power of embeddings to capture meaning beyond simple keyword matching.

{
  "type": "exercise",
  "id": "3a08a6be-f260-4f87-aba5-c77fe9a26983"
}

A Practical E-commerce Example: Embedding Product Reviews

Now, let's combine these ideas into a more robust workflow relevant to your goals. A common task in e-commerce is analyzing customer feedback. Let's say you have a CSV file of product reviews and you want to prepare them for semantic analysis or search. This involves reading the data, creating embeddings for each review, and storing them for future use.

The OpenAI documentation provides an excellent walkthrough using a dataset of Amazon food reviews. Given your experience with Python, you will recognize the use of the pandas library to handle the data.

{"type":"reading","par_intro":"This example demonstrates a complete, practical workflow for embedding a real-world dataset. It's a template you can adapt for many business automation tasks.","par_directions":"Please read the section titled Obtaining the embeddings. Study the Python code provided. Note how it:\n1.  Uses `pandas` to read a CSV file.\n2.  Combines two text columns (`Summary` and `Text`) into a single input string.\n3.  Defines a reusable `get_embedding` function.\n4.  Applies this function to every row in the DataFrame to create a new column containing the embedding vectors.\n5.  Saves the augmented DataFrame to a new CSV file.","learning_duration":"10 minutes","url":"https://developers.openai.com/api/docs/guides/embeddings/","title":"Vector embeddings | OpenAI API","isV2":true,"blockId":"f60bd9ab-3d82-4e6a-b992-e9b6f0c0998f","lessonId":"7b015f83-d74e-47d9-8d05-6acb63b5fc66"}



This workflow is a powerful pattern. You could use it to embed your entire Walmart product catalog, customer support tickets, or marketing materials, creating a rich, searchable knowledge base for your autonomous agent.

A Note on Cost and Performance

Two final points on practical usage:

  1. Token Cost: The embeddings API, like the chat API, is priced based on the number of input tokens. For large datasets, it's wise to be mindful of costs. You can use the tiktoken library, which we touched on in Module 1, to count the tokens in your text before sending it to the API. This can help you estimate costs and batch your requests effectively.

  2. Dimensionality: As mentioned, text-embedding-3-small produces vectors with 1536 dimensions. Storing millions of these large vectors can become expensive and computationally intensive. The new v3 models from OpenAI include a dimensions parameter in the API call, allowing you to request shorter vectors (e.g., 256 or 512 dimensions). This can significantly reduce costs and speed up similarity calculations, often with minimal impact on performance for many tasks. This is an advanced optimization to keep in mind as you scale your applications.

{
  "type": "exercise",
  "id": "367c0db6-a775-442e-beca-92d7e58a84e4"
}

Conclusion

In this lesson, we put theory into practice. You have now learned how to programmatically generate semantic text embeddings using the OpenAI API.

Here are the key takeaways:

  • You can generate embeddings using the client.embeddings.create() method from the openai Python library.
  • The text-embedding-3-small model provides a great balance of cost and performance for most use cases.
  • Batching requests by passing a list of strings to the input parameter is far more efficient than making individual API calls.
  • The workflow of reading data with pandas, applying an embedding function, and saving the results is a reusable pattern for building knowledge bases from structured data like CSV files.

You are now equipped to turn any body of text into a machine-readable format. But what do we do with these millions of numbers? In our next lesson, we will answer that question by diving into vector similarity search, the technique that allows us to query our new vector database to find the most relevant information.

Can't find a good explanation? Sign up and we'll make it for you