{"id":77,"date":"2026-09-16T23:25:18","date_gmt":"2026-09-16T15:25:18","guid":{"rendered":"https:\/\/wp.qoraapi.com\/ai-embeddings-rag\/"},"modified":"2026-09-20T03:53:13","modified_gmt":"2026-09-19T19:53:13","slug":"ai-embeddings-rag","status":"publish","type":"post","link":"https:\/\/qoraapi.com\/blog\/ai-embeddings-rag\/","title":{"rendered":"AI Embeddings Explained: Vectors, Similarity, and Building Your First RAG"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>Embeddings<\/strong> are how you turn text into something a computer can search by meaning rather than by matching words. An embedding model reads a string of text and returns a fixed-length vector of floats \u2014 typically a few hundred to a few thousand numbers \u2014 such that semantically similar texts produce vectors that are close together in that space. Once you have that, &#8220;find me the document most relevant to this question&#8221; becomes &#8220;find me the vector closest to this question&#8217;s vector&#8221;, and the rest of a RAG system falls into place.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide covers what embeddings actually are, how to call them through an AI API, how similarity search works, and how to build a minimal retrieval-augmented generation (RAG) pipeline that fetches the right context before asking a model to answer. The code runs unmodified against any <a href=\"https:\/\/qoraapi.com\/blog\/openai-compatible-api-guide\/\">OpenAI-compatible endpoint<\/a>, and the patterns fit naturally into the rest of this site&#8217;s guides on <a href=\"https:\/\/qoraapi.com\/blog\/reduce-ai-api-costs\/\">cost<\/a>, <a href=\"https:\/\/qoraapi.com\/blog\/ai-function-calling-tool-use\/\">function calling<\/a>, and <a href=\"https:\/\/qoraapi.com\/blog\/ai-api-rate-limits-429-errors\/\">rate limits<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"why-embeddings\">Why embeddings matter<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keyword search finds documents that share words with the query; embeddings find documents that share <em>meaning<\/em>. The difference is felt the moment a user types something a writer never phrased that way. &#8220;How do I cancel my plan?&#8221; and &#8220;What is the cancellation policy?&#8221; have no shared words but the same answer \u2014 and an embedding search surfaces it without anyone hand-writing a synonym list.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Three properties of embeddings matter in practice:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Similarity is geometric.<\/strong> Two vectors being &#8220;close&#8221; means their dot product (or cosine similarity) is high. You do not need a model at query time to find a match \u2014 a fast nearest-neighbour search over a few thousand vectors takes milliseconds.<\/li>\n\n<li><strong>Embeddings are cheap to compute once you have them.<\/strong> A typical 1,000-token passage embeds in tens of milliseconds and costs fractions of a cent. Re-embed only when the model or the content changes.<\/li>\n\n<li><strong>You embed any text the model can read.<\/strong> Documents, support tickets, code snippets, product descriptions \u2014 the same vector space, the same similarity function, the same retrieval.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-embeddings-work\">How embeddings work in practice<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When you send text to an embeddings endpoint, the provider&#8217;s model returns a JSON object with a fixed-length vector \u2014 typically 1536 or 3072 numbers for modern OpenAI models. Two texts that mean similar things produce vectors that point in similar directions; unrelated texts produce vectors that point in unrelated directions. The exact geometry is not interpretable, but the angle between two vectors reliably correlates with how semantically related the texts are.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is the entire mental model. The arithmetic behind it (transformer encoders, contrastive training, projection layers) does not matter for using embeddings well \u2014 only the invariants do: similar in \u2192 close vectors out, different in \u2192 far vectors out.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"call-the-api\">Calling the embeddings API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The OpenAI-compatible contract for embeddings is one of the simplest in the API: POST a list of strings, get a list of vectors back. This works against OpenAI directly, against any relay that exposes the same endpoint, and against smaller specialised providers:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from openai import OpenAI\n\nclient = OpenAI()\n\nresp = client.embeddings.create(\n    model=\"text-embedding-3-small\",\n    input=[\n        \"How do I cancel my subscription?\",\n        \"What is the refund policy?\",\n        \"Today's weather in Lisbon\",\n    ],\n)\n\nfor i, item in enumerate(resp.data):\n    print(f\"vector {i}: dim={len(item.embedding)} sample={item.embedding[:4]}\")\n# vector 0: dim=1536 sample=[0.0123, -0.0451, 0.0089, 0.0204]\n# vector 1: dim=1536 sample=[0.0118, -0.0438, 0.0091, 0.0211]\n# vector 2: dim=1536 sample=[-0.0302, 0.0152, 0.0612, -0.0088]<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Three properties to notice. Vectors 0 and 1 (both about customer service) are very close \u2014 sample values are similar; vector 2 (about weather) is far. The model used here is a small, fast, cheap one \u2014 fine for most retrieval workloads, with a vector dimension of 1536. Larger models produce higher-dimensional vectors (3072 for the equivalent &#8220;large&#8221; variant) that can capture finer distinctions at a higher cost.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"similarity\">Similarity: cosine and dot product<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two ways to compare vectors: dot product (sum of element-wise products) and cosine similarity (the dot product divided by the lengths of both vectors). For normalised embeddings \u2014 those that already lie on the unit sphere \u2014 the two are equivalent. Most modern embedding models return vectors that are either pre-normalised or close enough that cosine is the right choice; computing it is straightforward:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import math\n\ndef cosine(a, b):\n    dot = sum(x * y for x, y in zip(a, b))\n    na  = math.sqrt(sum(x * x for x in a))\n    nb  = math.sqrt(sum(y * y for y in b))\n    return dot \/ (na * nb)\n\nq = client.embeddings.create(model=\"text-embedding-3-small\",\n                             input=\"cancel my subscription\").data[0].embedding\n\ndocs = [\n    \"How do I cancel my plan?\",\n    \"What is your refund policy?\",\n    \"Today is sunny in Lisbon.\",\n]\ndoc_vecs = client.embeddings.create(model=\"text-embedding-3-small\",\n                                    input=docs).data\n\nfor text, vec in zip(docs, doc_vecs):\n    print(f\"{cosine(q, vec.embedding):.3f}  {text}\")\n# 0.873  How do I cancel my plan?\n# 0.781  What is your refund policy?\n# 0.412  Today is sunny in Lisbon.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The ranking is what you would expect: cancellation is closest to the query, refund policy is next (related domain), weather is far. Cosine returns a value between -1 and 1; for embeddings, anything above ~0.7 is usually a meaningful match.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"chunking\">Chunking: how to split documents for embedding<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A 50-page PDF does not embed as one vector \u2014 embeddings models have token limits, and a single vector that tries to represent the entire document averages away the parts that matter. The standard solution is to split the document into <em>chunks<\/em>, embed each chunk separately, and retrieve the chunks that match a query. Four chunking strategies cover most production needs:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Fixed-size windows.<\/strong> Split every N tokens with M tokens of overlap. Simple, predictable, and a fine default. Start with N=500, M=50.<\/li>\n\n<li><strong>Sentence or paragraph boundaries.<\/strong> Split where the text naturally divides, keeping each chunk semantically self-contained. Better retrieval quality, less predictable size.<\/li>\n\n<li><strong>Heading-based.<\/strong> Use the document&#8217;s own structure \u2014 markdown headers, HTML <code>&lt;h2&gt;<\/code> tags, PDF sections \u2014 as chunk boundaries. Excellent for structured documents.<\/li>\n\n<li><strong>Semantic splitting.<\/strong> Embed sentences one at a time, then merge adjacent sentences whose embeddings are very similar. Sophisticated; worth it only when the simpler strategies underperform.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The overlap parameter (M in the first strategy) matters more than the size of N: it prevents a sentence that happens to span a chunk boundary from being lost. The standard pattern is small overlap (5-10%) so each chunk is mostly unique but no information is silently dropped at the seams.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Chunking strategies compared<\/h3>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th>Strategy<\/th><th>How it splits<\/th><th>Best for<\/th><th>Watch out for<\/th><\/tr><\/thead><tbody><tr><td>Fixed-size<\/td><td>Every N tokens, with a small overlap<\/td><td>Homogeneous prose, quick prototypes<\/td><td>Cuts sentences and tables in half<\/td><\/tr><tr><td>Sentence \/ paragraph<\/td><td>On natural language boundaries<\/td><td>Articles, documentation, support tickets<\/td><td>Very uneven chunk sizes<\/td><\/tr><tr><td>Recursive<\/td><td>Tries paragraphs, then sentences, then characters<\/td><td>Most mixed-format corpora &mdash; a good default<\/td><td>Needs tuning of the size thresholds<\/td><\/tr><tr><td>Structure-aware<\/td><td>On headings, sections, code blocks, table rows<\/td><td>Markdown, HTML, and PDFs with clear structure<\/td><td>Requires a parser per format<\/td><\/tr><tr><td>Semantic<\/td><td>Where embedding similarity between adjacent passages drops<\/td><td>Dense reference material, transcripts<\/td><td>Extra embedding cost and complexity<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"minimal-rag\">A minimal RAG pipeline<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">RAG \u2014 retrieval-augmented generation \u2014 is just three steps on top of what you already have: embed the query, fetch the closest chunks, ask a model to respond with the chunks as context. Here is the simplest possible end-to-end version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import numpy as np\nfrom openai import OpenAI\n\nclient = OpenAI()\n\nINDEX = []  # list of (chunk_text, embedding_vector) pairs\n\ndef index_documents(docs):\n    \"\"\"Embed and store chunks once at index time.\"\"\"\n    embs = client.embeddings.create(\n        model=\"text-embedding-3-small\", input=docs,\n    )\n    for text, item in zip(docs, embs.data):\n        INDEX.append((text, np.array(item.embedding)))\n\ndef search(query, k=3):\n    \"\"\"Return the k chunks whose embeddings are closest to the query.\"\"\"\n    q = np.array(\n        client.embeddings.create(\n            model=\"text-embedding-3-small\", input=query,\n        ).data[0].embedding\n    )\n    scored = sorted(\n        ((float(q @ v \/ (np.linalg.norm(q) * np.linalg.norm(v))), t)\n         for t, v in INDEX),\n        reverse=True,\n    )\n    return [t for _, t in scored[:k]]\n\ndef answer(question):\n    context = \"\\n\\n\".join(search(question, k=4))\n    resp = client.chat.completions.create(\n        model=\"gpt-4o-mini\",\n        messages=[\n            {\"role\": \"system\", \"content\":\n                \"Answer using the context below. If the answer is not \"\n                \"in the context, say you do not know.\"},\n            {\"role\": \"user\", \"content\":\n                f\"Context:\\n{context}\\n\\nQuestion: {question}\"},\n        ],\n    )\n    return resp.choices[0].message.content\n\n# Index a tiny corpus once.\nindex_documents([\n    \"Refunds are issued within 7 days of cancellation.\",\n    \"Premium plans can be cancelled any time from the dashboard.\",\n    \"Free trials do not require cancellation to end.\",\n    \"Weather in Lisbon today is 22 degrees and sunny.\",\n])\n\nprint(answer(\"How do refunds work?\"))\n# Refunds are issued within 7 days of cancellation.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Three details matter most. First, the corpus is embedded <em>once<\/em> at index time; queries only embed the user&#8217;s question. Second, the model is told to say &#8220;I do not know&#8221; when the context does not contain the answer \u2014 this is the only thing keeping RAG from hallucinating when retrieval fails. Third, the model is the same one you use for chat \u2014 the <a href=\"https:\/\/qoraapi.com\/blog\/openai-compatible-api-guide\/\">OpenAI-compatible contract<\/a> covers both completions and embeddings, so a single endpoint serves both.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"vector-stores\">When you need a real vector store<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The list above is fine for thousands of chunks. Past that, brute-force cosine over every vector is too slow and a real vector index pays off. The choice is between:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Hosted vector databases.<\/strong> Pinecone, Weaviate Cloud, Qdrant Cloud, etc. Operate the index for you, charge by storage and queries, scale to millions of vectors without engineering work.<\/li>\n\n<li><strong>Self-hosted libraries.<\/strong> FAISS (Meta), Annoy (Spotify), HNSW implementations in pgvector, etc. You run them yourself, often inside an existing database. Free and fast for moderate scale, but you own the operations.<\/li>\n\n<li><strong>Hybrid stores.<\/strong> PostgreSQL with the <code>pgvector<\/code> extension, ElasticSQL with dense_vector, SQLite with sqlite-vec. Convenient when the metadata you want to filter by already lives in a relational database.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The rule of thumb: brute force is fine up to about 10,000 chunks; once you cross 100,000, a real index becomes necessary. A useful hybrid is to combine vector similarity with a metadata filter (region = &#8220;EU&#8221;, date > &#8220;2026-01-01&#8221;) to narrow the candidate set before the expensive similarity computation \u2014 most vector stores support this natively.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"failure-modes\">Common failure modes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Mixed embedding models.<\/strong> If some chunks were embedded with one model and queries with another, similarity is meaningless. Pick one model and stick with it; if you migrate, re-embed the entire corpus.<\/li>\n\n<li><strong>Wrong chunk size.<\/strong> Too small loses context (&#8220;the refund&#8221; without the qualifier); too large averages meaning across too much text. 200-500 tokens is a sensible range for prose.<\/li>\n\n<li><strong>Missing overlap.<\/strong> A sentence that crosses a chunk boundary is split in two, and neither chunk contains its full meaning. Keep 5-10% overlap.<\/li>\n\n<li><strong>Forgetting to normalise.<\/strong> Some vectors are returned pre-normalised, some are not. If you mix dot product and cosine without thinking, results can quietly degrade.<\/li>\n\n<li><strong>Ignoring the prompt.<\/strong> A model given retrieved context and no instruction will confabulate when context is thin. &#8220;If the answer is not in the context, say you do not know&#8221; is the single most useful prompt line in any RAG system.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cost\">Cost and rate limits<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Embeddings are cheap enough that cost is rarely the limiting factor, but the call patterns matter:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Embed the corpus once at index time.<\/strong> Re-embedding on every query is wasteful. Store vectors, reuse them.<\/li>\n\n<li><strong>Batch when embedding in bulk.<\/strong> Most embeddings APIs accept a list of inputs in one request and discount per token. A single call of 1,000 chunks is much cheaper than 1,000 calls of one chunk.<\/li>\n\n<li><strong>Watch the rate limits.<\/strong> Indexing 100,000 chunks can hit the same RPM\/TPM limits as chat completions. See our <a href=\"https:\/\/qoraapi.com\/blog\/ai-api-rate-limits-429-errors\/\">rate-limits guide<\/a> for the patterns that keep large embedding jobs within quota.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"checklist\">Embeddings and RAG checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Use a single embedding model end-to-end (corpus and queries).<\/li>\n\n<li>Embed chunks of 200-500 tokens with 5-10% overlap.<\/li>\n\n<li>Store vectors alongside a chunk identifier and a back-reference to the source.<\/li>\n\n<li>Cache query embeddings for repeat queries on hot paths.<\/li>\n\n<li>Use cosine similarity; check whether your model returns pre-normalised vectors.<\/li>\n\n<li>Brute-force cosine is fine up to ~10,000 chunks; switch to a vector index beyond that.<\/li>\n\n<li>Tell the generation model to say &#8220;I do not know&#8221; when context is thin.<\/li>\n\n<li>Embed in batches at index time; respect rate limits on the embedding endpoint.<\/li>\n\n<li>Version your index by the embedding model used so re-indexing is auditable.<\/li>\n\n<li>Measure retrieval quality with a small evaluation set before chasing model upgrades.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faq\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-what-are-embeddings\">What are embeddings in an AI API?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Embeddings are vectors \u2014 fixed-length lists of floats \u2014 produced by an embedding model from a piece of text. Semantically similar texts produce vectors that are close in the model&#8217;s vector space, so similarity becomes a fast geometric calculation. They power semantic search, retrieval-augmented generation, clustering, recommendations, and classification with very little code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-dimension\">What dimension should I use?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Whatever your chosen model returns. Smaller models (1536 dimensions) are cheap, fast, and fine for most retrieval workloads. Larger models (3072 dimensions) capture finer distinctions at higher cost and storage. Pick once and stick with it; mixing dimensions across documents and queries silently breaks similarity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-cosine-vs-dot\">Cosine similarity or dot product?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For modern embeddings models that return vectors roughly on the unit sphere, the two are equivalent in ranking. If your model does not normalise its vectors, cosine is the safer default \u2014 it normalises on the fly. For normalised vectors, dot product is faster because it skips the division.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-chunk-size\">How large should a chunk be?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For prose, 200-500 tokens is a sensible range; smaller chunks lose context, larger chunks average away meaning. Keep 5-10% overlap between adjacent chunks so sentences that straddle a boundary are not lost. The exact right size depends on your data \u2014 measure retrieval quality on a small evaluation set before optimising.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-when-vector-store\">When do I need a vector database?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Brute-force cosine over a few thousand vectors is fine for prototypes and small production workloads. Past about 10,000 chunks, brute-force search starts to feel slow at query time; past 100,000, a real index is required. Hosted options (Pinecone, Weaviate Cloud) and self-hosted options (FAISS, pgvector) both work; the choice depends on whether you want to operate the infrastructure yourself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-hallucinate\">Will a RAG system still hallucinate?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, if the model is asked a question the retrieved context does not answer. The single most useful prompt line in any RAG system is telling the model to say &#8220;I do not know&#8221; when the context is thin. Strong retrieval plus that instruction dramatically reduces hallucinations; it does not eliminate them, which is why measuring retrieval quality and answer quality together is part of running RAG in production.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-portable\">Are embeddings OpenAI-compatible across providers?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>\/v1\/embeddings<\/code> endpoint is one of the most standardised parts of the OpenAI-compatible contract \u2014 most relays expose it. The catch is that vectors produced by different models are not interchangeable: even if two providers agree on the wire format, a vector from one model will not compare meaningfully to a vector from another. Pick the model and the provider, and re-embed if you ever migrate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"faq-cost\">Are embeddings expensive?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Usually not. A typical 1,000-token passage embeds in tens of milliseconds and costs fractions of a cent on the small, fast model. The expensive part of a RAG system is almost always the generation step, not the embedding step. See our <a href=\"https:\/\/qoraapi.com\/blog\/reduce-ai-api-costs\/\">guide to reducing AI API costs<\/a> for the broader patterns.<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<p class=\"wp-block-paragraph\">Embeddings turn &#8220;search&#8221; into geometry and &#8220;RAG&#8221; into three steps: embed the corpus once, embed each query at request time, ask the model to answer with the closest chunks as context. The patterns fit together because the <a href=\"https:\/\/qoraapi.com\/blog\/openai-compatible-api-guide\/\">OpenAI-compatible contract<\/a> serves both completions and embeddings, so a single endpoint can power the entire stack. If you want to try embeddings and RAG against multiple models with the same code, create a key at <a href=\"https:\/\/qoraapi.com\/\" target=\"_blank\" rel=\"noopener\">qoraapi.com<\/a> and start with a small corpus \u2014 most of what makes RAG work in production is the indexing and retrieval pipeline, not the model itself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Related reading<\/h3>\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/qoraapi.com\/blog\/production-rag-architecture\/\">Building Production RAG: Chunking, Hybrid Search, and Re-Ranking<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/vector-database-selection\/\">How to Choose a Vector Database for RAG<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/rag-ingestion-pipeline\/\">Building a RAG Ingestion Pipeline: Crawling, Parsing, and Syncing<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/semantic-caching-ai-api\/\">Semantic Caching for AI APIs: Cut Latency and Cost by Up to 60%<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/text-to-sql-ai\/\">Text-to-SQL: Letting Users Query Your Database with AI<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/voice-ai-apis\/\">Building Voice AI Apps: TTS, STT, and Realtime APIs<\/a><\/li><li><a href=\"https:\/\/qoraapi.com\/blog\/context-window-management\/\">Managing the Context Window: Truncation, Summarization, and Sliding Windows<\/a><\/li><\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>A practical guide to embeddings and retrieval-augmented generation: how text becomes vectors, how cosine similarity searches them, and how to build a minimal RAG pipeline in a few hundred lines of code.<\/p>\n","protected":false},"author":1,"featured_media":76,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[5,6,9,7,11],"class_list":["post-77","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-api","tag-ai-api","tag-api-gateway","tag-developer-tools","tag-developers","tag-software-development"],"_links":{"self":[{"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/posts\/77","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/comments?post=77"}],"version-history":[{"count":4,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/posts\/77\/revisions"}],"predecessor-version":[{"id":255,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/posts\/77\/revisions\/255"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/media\/76"}],"wp:attachment":[{"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/media?parent=77"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/categories?post=77"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qoraapi.com\/blog\/wp-json\/wp\/v2\/tags?post=77"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}