AI / LLM DevelopmentHow to Create Embeddings With an LLM API 2026 By Team CJ August 13, 202626 viewsShareTweet 0Creating embeddings with an LLM API is a practical way to turn text into searchable semantic representations for AI applications. Instead of relying only on exact keyword matches, an embedding-based system can compare the meaning of text and find related content.In this tutorial, you will learn how to create embeddings with an LLM API using Python. You will generate an embedding for one piece of text, process multiple documents, compare vectors with cosine similarity, clean and chunk content, store useful metadata, and prepare the pipeline for semantic search, vector databases, and RAG applications.The examples use OpenAI’s text-embedding-3-small model. Always verify the current model name, limits, dimensions, and pricing in the provider documentation before using an embedding model in production.What You Will BuildYou will build a small Python embedding pipeline that can:Send text to an embedding API.Receive a numerical vector.Inspect the generated vector.Generate embeddings for multiple documents.Compare two pieces of text using cosine similarity.Prepare clean content for indexing.Split long documents into meaningful chunks.Store metadata alongside vectors.Prepare the architecture for a vector database or RAG system.The goal is to understand the architecture instead of hiding the process behind a framework. The same approach can later be connected to PostgreSQL with pgvector, another vector database, or a complete retrieval-augmented generation pipeline.What Is an Embedding?An embedding is a list of numbers produced by a machine-learning model. These numbers are not intended to be read by a person. They represent useful information about the meaning and relationships contained in the input.Related pieces of text can occupy nearby positions in an embedding model’s vector space. For example:“How can I make my website faster?”“How do I improve page loading performance?”The words are different, but the questions express a closely related idea. A semantic retrieval system can compare their vectors and identify that relationship.Embeddings are different from generated answers. An embedding endpoint produces a numerical representation of text. Your application then decides how to use that representation for search, recommendations, classification, clustering, or retrieval.Choose an Embedding Model for an LLM APIBefore you create embeddings with an LLM API, choose a model that fits your application.The example in this tutorial uses OpenAI’s text-embedding-3-small, which is designed for embedding tasks such as search, clustering, recommendations, anomaly detection, and classification.A critical rule is consistency. Documents and queries used for retrieval should be represented in a compatible vector space. Record the model name and vector dimensions with your indexed data so you know how every vector was generated.If you later change embedding models, plan a re-indexing process. Do not casually mix vectors generated by unrelated models or incompatible vector spaces.Create the Python ProjectCreate a virtual environment and install the official Python SDK.python -m venv .venvActivate the environment on Windows:.venv\Scripts\activateOn macOS or Linux:source .venv/bin/activateInstall the SDK:pip install openaiKeep your API key outside your source code. Environment variables are suitable for local development, while a managed secret store is better for production.Never publish an API key in a tutorial repository, browser JavaScript, screenshots, or public Git history.Create Your First Embedding With an LLM APIThe first step to create embeddings with an LLM API is to send a text string to the embedding endpoint.from openai import OpenAI client = OpenAI() text = "How can I improve website performance?" response = client.embeddings.create( model="text-embedding-3-small", input=text ) vector = response.data[0].embedding print("Vector length:", len(vector)) print("First five values:", vector[:5])The SDK reads the API key from the environment. This keeps credentials out of your Python source file.For example, your application might receive the following input:How can I improve website performance?The embedding endpoint converts that text into a numerical vector. Your application can then store the vector or compare it with other vectors.Understand the Embedding ResponseThe response contains embedding data. The vector itself is a sequence of floating-point values.The vector length depends on the selected model and any supported dimensions option. Do not hard-code a dimension simply because an example on the internet uses that value.Instead, inspect the actual vector during development:print(len(vector))If the vector will be stored in a vector database, the database column dimension must match the vectors you generate.It is also useful to store the model name with each indexed record. This makes future migrations easier because you can identify which model produced each vector.Generate Multiple Embeddings With an LLM APIReal applications normally index many pieces of content. Instead of sending a separate request for every short sentence, you can send multiple input strings in a controlled batch.texts = [ "How to improve website loading speed", "How to create a PHP login system", "How to build a React application", "How to configure WordPress caching" ] response = client.embeddings.create( model="text-embedding-3-small", input=texts ) for item, text in zip(response.data, texts): print(text) print("Vector length:", len(item.embedding))Batching is especially useful during a large initial indexing job.However, batching does not mean sending unlimited content in one request. Respect the provider’s token limits, rate limits, and request limits. For large collections, process documents in controlled batches and record successful and failed items.Compare Two Texts With Cosine SimilarityAfter you create embeddings with an LLM API, a common next step is comparing vectors.Cosine similarity measures the orientation of two vectors. It is commonly used to estimate how closely two embeddings are related.from math import sqrt def cosine_similarity(a, b): dot = sum(x * y for x, y in zip(a, b)) na = sqrt(sum(x * x for x in a)) nb = sqrt(sum(y * y for y in b)) if na == 0 or nb == 0: return 0.0 return dot / (na * nb)You could create two embeddings and compare them:text_a = "How can I improve website speed?" text_b = "How do I make my web page load faster?" response = client.embeddings.create( model="text-embedding-3-small", input=[text_a, text_b] ) vector_a = response.data[0].embedding vector_b = response.data[1].embedding score = cosine_similarity(vector_a, vector_b) print("Similarity:", score)A similarity score is useful for ranking related content, but it should not be treated as a universal confidence percentage. A high similarity score does not guarantee that a document contains the correct answer.Clean Text Before Creating EmbeddingsEmbedding quality depends partly on what you send to the model.For website content, remove unnecessary material such as:Navigation menusRepeated footersCookie noticesTracking fragmentsBroken HTMLRepeated interface textUnrelated boilerplatePreserve useful context such as the article title and section heading.For example, this is more useful:Image Optimization Convert large images to WebP and AVIF to reduce page weight and improve loading performance.than a page fragment containing navigation menus, cookie notices, unrelated buttons, and repeated footer content.Clean input helps the embedding represent the subject you actually want users to retrieve.Chunk Long DocumentsDo not automatically embed an entire 2,000-word article as one vector if users may ask questions about individual sections.Instead, split long documents into meaningful chunks.A good chunk should:Be understandable on its own.Represent one coherent subject.Preserve important context.Avoid unnecessary repeated text.Be connected to its source metadata.For example, a tutorial can be divided into chunks such as:Tutorial: Create a Python RAG Application Section: Install Dependencies Section: Generate Embeddings Section: Store Vectors Section: Search Documents Section: Generate an AnswerStore information such as the document ID, title, section, chunk number, URL, and original text alongside the vector.When search finds a relevant chunk, your application can display the correct source and send the relevant passage to an LLM.Create a Reusable Embedding FunctionOnce you create embeddings with an LLM API in a real application, avoid repeating the API call throughout your code.Create a reusable function so validation, model selection, logging, and error handling can live in one place.def create_embedding(client, text, model="text-embedding-3-small"): if not isinstance(text, str): raise TypeError("text must be a string") text = text.strip() if not text: raise ValueError("text cannot be empty") response = client.embeddings.create( model=model, input=text ) return response.data[0].embeddingYou can then call it from different parts of your application:vector = create_embedding( client, "How do I improve website performance?" ) print("Vector length:", len(vector))In production, add bounded retry behavior for transient network failures and rate limits. Do not blindly retry invalid requests forever. Record failures and place failed documents into a retry queue when appropriate.Store Metadata With VectorsA vector without its source is difficult to use.When you create embeddings with an LLM API for a content library, store useful metadata alongside every vector.A record might contain:tutorial_id title canonical_url technology difficulty tutorial_series section chunk_number content_version language embedding_model vectorFor example:technology = PHP difficulty = Intermediate content_type = TutorialMetadata allows your application to filter results.A user could search semantically while also applying filters such as:Beginner JavaScript tutorialsor:WordPress troubleshootingThis combination of semantic retrieval and metadata filtering can make search results more useful.Create Embeddings With an LLM API for SearchOnce documents have embeddings, a semantic search workflow usually follows this pattern:User question ↓ Create query embedding ↓ Search stored vectors ↓ Rank similar chunks ↓ Apply metadata filters ↓ Return relevant sourcesFor example, a user might search:How can I make my website load faster?The application creates an embedding for the question. It then compares that query vector with document vectors and retrieves the most relevant chunks.This approach can find content even when the query does not contain the exact words used in the original article.Prepare Embeddings for a Vector DatabaseFor a small prototype, vectors can be inspected directly in Python. A production system normally needs persistent storage.After you create embeddings with an LLM API, you can store the vectors in a vector-capable database.PostgreSQL with pgvector is one practical option for developers who already use PostgreSQL. Other vector databases can also be used depending on your application requirements.The basic architecture becomes:Website content ↓ Clean and normalize ↓ Split into chunks ↓ Create embeddings ↓ Store vectors + metadata ↓ Create query embedding ↓ Vector search ↓ Retrieve relevant chunksOnce retrieval works, the same pipeline can become the retrieval layer of a RAG application.Cost and PerformanceEmbedding costs depend on input tokens and the selected model.Before indexing a large content library, estimate the number of tokens involved. Cache embeddings for unchanged content and regenerate vectors only when the source text changes.For example, keep a content hash:document_id content_hash embedding_model vectorWhen the content hash has not changed, the application can skip unnecessary API requests.Batch ingestion jobs can also reduce overhead. Monitor API usage and measure embedding latency separately from vector-database latency.This helps identify whether performance problems come from the embedding API, database search, preprocessing, or another part of the pipeline.Evaluate Embedding Search Before ScalingDo not index thousands or millions of documents before checking whether your retrieval system works.Create a small evaluation set containing realistic questions.For example:How do I improve LCP? How do I add a PHP login? How can I upload files with React? How do I configure WordPress caching?Label which documents or sections should be relevant.Include:Paraphrased questionsShort questionsTechnical phrasesBeginner wordingLong questionsUnrelated questionsQuestions that should return no useful resultAfter changing your preprocessing, chunking strategy, embedding model, database index, or ranking logic, run the same evaluation set again.This gives you a measurable baseline instead of relying on one or two examples.Common MistakesSeveral mistakes can reduce the reliability of an embedding system.Hard-Coding API KeysNever place an API key directly in source code that may be published.Use environment variables or a managed secret store.Mixing Embedding ModelsDocuments and queries should use compatible embeddings. If you change models, plan a migration and re-index the affected content.Ignoring Vector DimensionsThe database vector dimension must match the vectors being stored.Embedding Noisy Website ContentNavigation, repeated footers, cookie notices, and unrelated interface text can make retrieval less useful.Regenerating Every VectorDo not regenerate vectors for unchanged content. Use content hashes or versions to detect changes.Treating Similarity as TruthA similarity score indicates a relationship between representations. It does not prove that the retrieved content is correct.Ignoring EvaluationAdding more documents does not automatically improve search. Retrieval quality depends on source content, chunking, metadata, model choice, ranking, and evaluation.Build an Idempotent Indexing PipelineA production embedding pipeline should be idempotent.Give every document and chunk a stable identifier. Store a content hash and the embedding model name.When a page has not changed:Skip embeddingWhen a page has changed:Regenerate affected chunksThis reduces API costs and makes indexing faster.It also gives you a clean migration path if you later choose another embedding model.Use a Batch Worker for Large CollectionsFor a large content library, avoid embedding every page from a normal web request.A background worker can:Read pending documents.Clean and chunk the content.Create controlled embedding batches.Call the embedding API.Save successful vectors.Record failures.Retry temporary failures.Mark completed documents.Keep retry logic bounded.A temporary network failure can be retried. An invalid input should be corrected rather than retried forever.If one document fails, do not stop the entire indexing job. Put the failed item into a retry queue and continue processing the remaining documents.Design the Pipeline as Separate ComponentsA reliable embedding system becomes easier to maintain when it separates:Content ingestion ↓ Preprocessing ↓ Chunking ↓ Embedding generation ↓ Vector storage ↓ Retrieval ↓ User interfaceEach stage should have a clear input and output.This modular design makes debugging easier because a failure can be isolated to one stage. It also allows you to replace a component without rewriting the entire application.For example, you could change the vector database without changing your content-cleaning logic.Improve the User ExperienceA technically correct retrieval system can still be frustrating if results are difficult to scan.Return useful information such as:Tutorial titleShort excerptCategoryDifficultyTechnologySource URLFor a Q&A system, show the sources used to construct the answer.Good retrieval should reduce the number of searches a visitor needs to perform, not simply demonstrate that vectors are working.Plan for FailureAn embedding provider can temporarily become unavailable. A database can become slow. A document can fail during ingestion. A user can submit unsupported content.Use:TimeoutsBounded retriesLoggingValidationGraceful fallback responsesRetry queuesIf the AI layer fails, a normal website search or tutorial index should remain available when possible.If one document fails indexing, do not stop the entire indexing job.A resilient architecture assumes that individual components can fail and provides a controlled way to recover.Document the Embedding SystemAI systems evolve quickly, so document the important implementation details.Record:Embedding modelVector dimensionsChunking rulesDatabase schemaIndex typeRetrieval filtersEvaluation queriesEnvironment variablesRe-indexing procedureContent versioning strategyThis documentation helps the next developer understand how the system works and how to migrate it safely.Related ResourcesContinue with the CodexJunction guide on How to Create a Semantic Search Feature With Embeddings.For implementation reference, consult the official OpenAI Embeddings documentation, NumPy documentation, and PostgreSQL documentation.ConclusionLearning how to create embeddings with an LLM API gives you the foundation for building semantic search, recommendations, document retrieval, classification systems, and RAG applications.The basic workflow is straightforward:Text ↓ Clean content ↓ Create embeddings ↓ Store vectors and metadata ↓ Create an embedding for the user query ↓ Search similar vectors ↓ Retrieve useful content ↓ Use the retrieved content in your applicationThe difficult part is not simply generating a vector. A reliable system also requires clean source content, meaningful chunks, consistent models, useful metadata, efficient storage, evaluation, error handling, and a clear re-indexing strategy.Start with a small evaluation dataset and a simple Python implementation. Once retrieval quality is measurable, you can scale the pipeline to a vector database and eventually connect it to a complete RAG application.
AI / LLM DevelopmentHow to Build an AI-Powered Content Summarizer With Python: Beginner’s Guide 2026 By Team CJAugust 13, 20260