---
title: "Building a RAG knowledge base | SurrealDB University"
description: "Build a small RAG knowledge base - embeddings, semantic search, structured filters, a citation graph, and the assembled prompt - using nothing but the surreal…"
url: https://surrealdb.com/learn/ai/rag-knowledge-base
---

![Course content preview](https://surrealdb.com/assets/static/course-ai.LEsq_J_G.avif)

Course chapters

[Back to courses](https://surrealdb.com/learn) [SurrealDB for AI Engineers](https://surrealdb.com/learn/ai) [AI foundations](https://surrealdb.com/learn/ai/ai-foundations) [Vector embeddings and search](https://surrealdb.com/learn/ai/vector-embeddings) [Full-text search and BM25](https://surrealdb.com/learn/ai/fulltext-search-bm25) [Building a RAG knowledge base](https://surrealdb.com/learn/ai/rag-knowledge-base) [Hybrid search and reranking](https://surrealdb.com/learn/ai/hybrid-search-reranking) [Building an agent memory store](https://surrealdb.com/learn/ai/agent-memory-store) [Text-to-SurQL: agentic prompt engineering](https://surrealdb.com/learn/ai/text-to-surrealql) [Many sources and agents, one context layer](https://surrealdb.com/learn/ai/multi-source-context-layer) [Chunking strategies](https://surrealdb.com/learn/ai/chunking-strategies) [Evaluating retrieval quality](https://surrealdb.com/learn/ai/evaluating-retrieval) [Graph RAG beyond one hop](https://surrealdb.com/learn/ai/graph-rag-multi-hop) Certificate Pending

# Building a RAG knowledge base

## What RAG is, and why it exists

**Retrieval-augmented generation** is the pattern this lesson builds, and the name describes the order of operations: retrieve first, then generate, with the retrieved text sitting in the prompt as the model writes its answer.

It exists because of the two facts [lesson 01](https://surrealdb.com/learn/ai/ai-foundations) opened with. A model's context window is its whole world at inference time, and a model asked for something the window doesn't contain will produce a plausible continuation anyway. Prompting doesn't fix either of those. What you can change is what occupies the window, so the answer arrives in the prompt instead of hoping the model already knows it. Retraining would be the other option, and that's the wrong tool: it costs orders of magnitude more, it cannot be done per-request, and knowledge that changes daily would need it done daily.

An everyday analogy for this is a new colleague who is excellent at the work and has never seen your codebase. Their skill is not in question; what they need is the relevant files open in front of them before they answer. The model brings the skill, retrieval brings the files.

That leaves a search problem in front of every generation. RAG is the arrangement, and everything from here is about doing the retrieval well.

### So what decides what to search for?

In this lesson, nothing does. The user's question is embedded and that vector *is* the query, so no judgement is made about what to look for. It works because a question and its answer tend to sit near each other in meaning space, which is the property [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) demonstrated with the films.

That's also its weak point. A badly phrased question, or one needing two lookups to answer, still gets a single shot at a single vector.

Two models are involved here and they are easy to conflate. The **embedding model** decides where text lands in the space, and therefore what retrieval finds at all; the **generation model** only writes an answer from whatever arrived. So retrieval quality is almost entirely the embedding model's doing, and moving to a stronger LLM improves the prose while changing nothing about what was found. That is why [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) spends its closing section on choosing an embedding model and this one does not.

Handing the choice of query to the model is a different design, and [lesson 07](https://surrealdb.com/learn/ai/text-to-surrealql) builds it: the agent writes its own query instead of inheriting the user's phrasing. The generation model's judgement starts to matter there, and a new way to go wrong arrives with it, because a query the model invented can be confidently wrong in ways an embedded question cannot.

## Why RAG on SurrealDB

A typical RAG stack stores vectors in one system, documents in another, and relationships in a third. Every write has to reach all of them, and every read stitches the results back together in application code.

SurrealDB keeps those in one engine. The same record holds your text, its metadata, **and** its embedding; the same query can rank by vector similarity, filter on a typed field, and walk a graph of relationships. Retrieval logic then lives in a single query instead of three round-trips.

## Step 1 - start a server

The vectors below are tiny and hand-written, small enough to check by eye, with the swap to a real model covered at the end of the lesson. [Lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) introduced the HNSW index and the `<|K, EF|>` operator that these queries lean on; if you skipped it, the queries will still run, you will just be taking the index on trust.

An in-memory instance in its own terminal is authenticated and throwaway, which is fine for a tutorial:

```bash
surreal start --user root --pass secret
```

As in [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings), the database resets when you stop the process.

## Step 2 - define the schema

A document is one retrievable chunk of knowledge: its text, a `category` we can filter on, and the `embedding` vector we search over.

```surql
DEFINE TABLE OVERWRITE document SCHEMAFULL;

DEFINE FIELD OVERWRITE title     ON document TYPE string;
DEFINE FIELD OVERWRITE body      ON document TYPE string;
DEFINE FIELD OVERWRITE category  ON document TYPE "database" | "ml" | "web" | "devops";
DEFINE FIELD OVERWRITE embedding ON document TYPE array<float, 4>;

DEFINE INDEX OVERWRITE hnsw_embedding ON document
    FIELDS embedding
    HNSW DIMENSION 4
    DIST COSINE;

DEFINE INDEX OVERWRITE idx_category ON document FIELDS category;
```

That's the same **HNSW index** as [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings), approximate nearest neighbours over 4-dimensional vectors, cosine distance, stored as `F32`. [Lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) covers what each parameter does and how to tune it; here we just need it working.

What's new is the second index. `idx_category` is an ordinary index on a typed string field, and it's the reason the filtered query in Step 4 stays fast; a standalone vector store has nowhere to put it.

Save the statements above as `schema.surql`, starting the file with `OPTION IMPORT`, which `surreal import` requires:

Bash

PowerShell

```bash
surreal import --endpoint http://localhost:8000 \
  --user root --pass secret --ns ai --db rag schema.surql
```

## Step 3 - seed some documents

Each document gets a 4-dimensional embedding. To keep things legible the four numbers are topic axes (`[ databases, machine-learning, web, devops ]`), hand-picked so that similar documents sit close together. A real model produces hundreds or thousands of dimensions that nobody would ever read by eye, but the geometry is exactly the same.

```surql
CREATE document:vec_index SET
    title     = "Vector indexes in SurrealDB",
    category  = "database",
    embedding = [0.90, 0.50, 0.10, 0.10],
    body      = "How HNSW indexes make approximate nearest-neighbour search fast.";

CREATE document:embeddings SET
    title     = "Embeddings for semantic search",
    category  = "ml",
    embedding = [0.60, 0.80, 0.10, 0.10],
    body      = "Turning text into vectors so similar meanings sit close together.";

CREATE document:rocksdb SET
    title     = "RocksDB storage engine internals",
    category  = "database",
    embedding = [0.85, 0.10, 0.05, 0.40],
    body      = "The LSM-tree engine behind SurrealDB's persistent storage.";

-- ...and five more, in full below
```

We also record which documents cite which, as a graph. A `cites` edge means the source references the target, which is what lets retrieval follow relationships later.

```surql
RELATE document:embeddings->cites->document:vec_index;
RELATE document:embeddings->cites->document:transformers;
RELATE document:vec_index ->cites->document:rocksdb;
RELATE document:finetune  ->cites->document:transformers;
RELATE document:graphql   ->cites->document:react;
```

Load the seed the same way:

**The complete `seed.surql` - eight documents with their bodies, plus the citation graph** 

```surql
OPTION IMPORT;

CREATE document:vec_index    SET title = "Vector indexes in SurrealDB",      category = "database", embedding = [0.90, 0.50, 0.10, 0.10], body = "How HNSW indexes make approximate nearest-neighbour search fast.";
CREATE document:embeddings   SET title = "Embeddings for semantic search",   category = "ml",       embedding = [0.60, 0.80, 0.10, 0.10], body = "Turning text into vectors so similar meanings sit close together.";
CREATE document:rocksdb      SET title = "RocksDB storage engine internals", category = "database", embedding = [0.85, 0.10, 0.05, 0.40], body = "The LSM-tree engine behind SurrealDB's persistent storage.";
CREATE document:transformers SET title = "Training transformer models",      category = "ml",       embedding = [0.10, 0.95, 0.05, 0.10], body = "Attention, tokenisation, and the training loop for transformers.";
CREATE document:finetune     SET title = "Fine-tuning LLMs on a budget",      category = "ml",       embedding = [0.10, 0.90, 0.05, 0.40], body = "LoRA and quantisation to adapt a base model cheaply.";
CREATE document:react        SET title = "Building a React dashboard",        category = "web",      embedding = [0.05, 0.10, 0.95, 0.10], body = "Component state and data fetching for an analytics dashboard.";
CREATE document:graphql      SET title = "GraphQL API gateways",              category = "web",      embedding = [0.10, 0.10, 0.70, 0.50], body = "Schema stitching and gateways in front of microservices.";
CREATE document:k8s          SET title = "Kubernetes autoscaling",            category = "devops",   embedding = [0.10, 0.10, 0.10, 0.95], body = "Horizontal pod autoscaling driven by custom metrics.";

-- Citation graph: a `cites` edge means the source document references the
-- target. This is the multi-model payoff - the same store that does vector
-- search also walks relationships, so retrieval can follow citations.
RELATE document:embeddings->cites->document:vec_index;
RELATE document:embeddings->cites->document:transformers;
RELATE document:vec_index ->cites->document:rocksdb;
RELATE document:finetune  ->cites->document:transformers;
RELATE document:graphql   ->cites->document:react;
```

Bash

PowerShell

```bash
surreal import --endpoint http://localhost:8000 \
  --user root --pass secret --ns ai --db rag seed.surql
```

## Step 4 - retrieve

The SQL shell takes the query file on stdin:

Bash

PowerShell

```bash
surreal sql --endpoint ws://localhost:8000 \
  --user root --pass secret --ns ai --db rag --pretty < queries.surql
```

Every query uses the same query vector, standing in for the question *"How do vector databases work?"*, strong on the database and machine-learning axes:

```surql
LET $q = [0.90, 0.60, 0.10, 0.10];
```

> As in [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings), `queries.surql` keeps each statement on a single line; the versions below are formatted for readability.

### Query 1 - basic nearest-neighbour search

This is straight KNN, exactly as in [lesson 02](https://surrealdb.com/learn/ai/vector-embeddings): `<|3, 40|>` asks the index for the 3 nearest neighbours, and `vector::distance::knn()` reads back the cosine distance it computed: **smaller is closer**.

```surql
SELECT title, category, vector::distance::knn() AS dist
FROM document
WHERE embedding <|3, 40|> $q
ORDER BY dist;
```

Output

```surql
[
    { title: 'Vector indexes in SurrealDB',      category: 'database', dist: 0.0032 },
    { title: 'Embeddings for semantic search',   category: 'ml',       dist: 0.0560 },
    { title: 'RocksDB storage engine internals', category: 'database', dist: 0.1570 }
]
```

The three returned documents are exactly the ones near the database/ML corner, and the React, Kubernetes and GraphQL documents never even enter the ranking.

### Query 2 - scored results with a relevance threshold

The RAG-specific part comes next. [Lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) showed that `1 - distance` turns a cosine distance into a 0-1 similarity, and what a knowledge base does with it is set a **floor**. The score goes in a subquery, and everything below the threshold drops out.

```surql
SELECT title, category, score FROM (
    SELECT title, category, (1 - vector::distance::knn()) AS score
    FROM document
    WHERE embedding <|5, 40|> $q
)
WHERE score >= 0.9
ORDER BY score DESC;
```

Output

```surql
[
    { title: 'Vector indexes in SurrealDB',    category: 'database', score: 0.9968 },
    { title: 'Embeddings for semantic search', category: 'ml',       score: 0.9440 }
]
```

We asked for the five nearest, but only two clear the `0.9` bar. A simple, effective way to keep weak matches out of your prompt context.

### Query 3 - filter, rank, and walk the graph

Here's what a standalone vector database can't do in one query: rank by similarity, **filter on a typed field**, and **walk the citation graph** to pull in related context, all at once.

```surql
SELECT
    title,
    category,
    ->cites->document.title AS cites,
    vector::distance::knn() AS dist
FROM document
WHERE category = 'database' AND embedding <|2, 40|> $q
ORDER BY dist;
```

Output

```surql
[
    {
        title: 'Vector indexes in SurrealDB',
        category: 'database',
        cites: [ 'RocksDB storage engine internals' ],
        dist: 0.0032
    },
    {
        title: 'RocksDB storage engine internals',
        category: 'database',
        cites: [],
        dist: 0.1570
    }
]
```

The `WHERE category = 'database'` clause restricts the candidates, the `<|2, 40|>` ranks them by similarity, and `->cites->document.title` follows the graph to surface what each result references. In a real pipeline you'd hand both the top hit *and* its cited sources to the model - richer context, one query, no joins in application code.

### Query 4 - render the documents into the prompt

Everything up to here has been retrieval, which is only the first word of the RAG acronym. This step is the second word: the surviving documents are rendered into a single block of text, and that block goes into the prompt above the user's question.

```surql
(SELECT title, body, score FROM (
    SELECT title, body, (1 - vector::distance::knn()) AS score
    FROM document
    WHERE embedding <|5, 40|> $q
) WHERE score >= 0.9 ORDER BY score DESC)
    .map(|$d| "## " + $d.title + "\n" + $d.body)
    .join("\n\n");
```

```markdown
## Vector indexes in SurrealDB
How HNSW indexes make approximate nearest-neighbour search fast.

## Embeddings for semantic search
Turning text into vectors so similar meanings sit close together.
```

Both of those paragraphs are `body` fields, written out in Step 3 and returned here untouched. The model is handed text you wrote, not text it recalled. That's the augmentation. Dropped into a prompt under a line like *"Answer using only these documents:"*, they are what the model reads before it writes anything.

Asked *"How do vector databases work?"* with nothing retrieved, a model answers from its weights: fluent, general, attributable to nothing, and wrong in the places your own documentation has moved on since training. Asked the same question with the block above in the window, it answers from two documents you chose, can cite, and can update tonight. The model did not change between those two answers, and neither did the prompt's wording. Only the contents of the window did.

You can see the difference for yourself without leaving the shell, because the whole prompt is one more string concatenation:

```surql
LET $question = "How do vector databases work?";

RETURN "Answer using only these documents:\n\n"
    + (SELECT title, body, score FROM (
          SELECT title, body, (1 - vector::distance::knn()) AS score
          FROM document
          WHERE embedding <|5, 40|> $q
      ) WHERE score >= 0.9 ORDER BY score DESC)
        .map(|$d| "## " + $d.title + "\n" + $d.body)
        .join("\n\n")
    + "\n\nQuestion: " + $question;
```

```text
Answer using only these documents:

## Vector indexes in SurrealDB
How HNSW indexes make approximate nearest-neighbour search fast.

## Embeddings for semantic search
Turning text into vectors so similar meanings sit close together.

Question: How do vector databases work?
```

Paste that into any model, then paste the bare question into a fresh session, and read the two answers side by side. The ungrounded one will be longer, more confident and full of detail this database never mentioned. The grounded one will be shorter, will stay inside HNSW and embeddings, and will be checkable line by line against two documents you wrote. Neither answer is printed here on purpose, since a made-up example of a bad answer would prove nothing that you can't prove better in thirty seconds.

That also settles which step is which letter. Query 1 is the **retrieval**. The threshold in Query 2 and the block here are the **augmentation**, and they are where accuracy is won or lost, because a weak match that clears the bar becomes something the model treats as fact. The **generation** happens in whatever model you post the finished prompt to, which is the one part of the loop this lesson never runs.

## From toy vectors to a real model

The only thing separating this from a production knowledge base is where the embeddings come from. Switching to a real model takes four steps:

1. \1.

   Pick an embedding model and note its dimensionality, for example `text-embedding-3-small` at 1536, or an open model at 384/768/1024. [Lesson 02](https://surrealdb.com/learn/ai/vector-embeddings) ends with a section on choosing one and what the choice costs.
2. \2.

   Change `DIMENSION 4` in `schema.surql` to match - that's the only schema edit.
3. \3.

   At write time, send each document's `body` to the model and store the returned vector in `embedding`.
4. \4.

   At query time, embed the user's question with the **same** model and pass that vector as `$q`.

Everything else (the index, the KNN operator, the scoring, the graph hop) stays exactly as you see it here.

## Where this goes next

You've now built a working RAG retrieval layer - vectors, filters and a graph - inside a single database. It retrieves on the semantic half of the problem only, though, so a question like *"refund for order 8823"* still has a term in it that no embedding handles well. [Lesson 05](https://surrealdb.com/learn/ai/hybrid-search-reranking) runs this retriever alongside the BM25 one from [lesson 03](https://surrealdb.com/learn/ai/fulltext-search-bm25) and fuses the two rankings into one.

At a glance

**You are on**

Chapter 4 of 11

**Chapters**

11

**Format**

Text, with queries you can run

**Runs in**

SurrealDB Studio, in the browser

**Cost**

Free

**Certificate**

On completion

[Next: Hybrid search and reranking](https://surrealdb.com/learn/ai/hybrid-search-reranking)

## Continue

### [Full-text search and BM25](https://surrealdb.com/learn/ai/fulltext-search-bm25)

Previous

### [Hybrid search and reranking](https://surrealdb.com/learn/ai/hybrid-search-reranking)

Next lesson

THE PLATFORM

## Everything an application and its agents know. Five surfaces, one engine.

Database

Document, graph, vector, time-series and relational in one engine.

![Five data models as dotted tiles: documents, graph, vector, time-series and relational](https://surrealdb.com/assets/static/platform-database.DUdumYDz.avif)

Read more

[Database](https://surrealdb.com/surrealdb)

Agent Memory

What an agent learns, with its source and its time, in the same engine.

![A timeline of remembered facts, each with its source](https://surrealdb.com/assets/static/platform-agent-memory.B4RNjvbX.avif)

Read more

[Agent Memory](https://surrealdb.com/agent-memory)

Cloud

Managed clusters in the regions you choose, scaled on demand.

![Clusters in three regions on a world map, each running or scaling](https://surrealdb.com/assets/static/platform-cloud.--QZnaVi.avif)

Read more

[Cloud](https://surrealdb.com/cloud)

Studio

Query, explore and design the schema from the browser.

![A SurrealQL query in Studio and the schema graph under it](https://surrealdb.com/assets/static/platform-studio.7ykBFNLq.avif)

Read more

[Studio](https://surrealdb.com/studio)

MCP

Every model that speaks MCP reaches the database and the memory directly.

![Three models connected through MCP to the database and Agent Memory](https://surrealdb.com/assets/static/platform-mcp.D_oH0_wm.avif)

Read more

[MCP](https://surrealdb.com/mcp)

IN PRODUCTION

## Trusted at scale. Samsung, Nvidia, Verizon, Tencent, and Walmart run on SurrealDB.

14,000+

Developers building on SurrealDB Cloud

4M+

Developers building on SurrealDB worldwide

FROM THE TEAMS

> SurrealDB gives us a foundation where we can unify semantic search, knowledge graphs, and AI-driven decision making without stitching together multiple systems. Collapsing responsibility into SurrealDB has become our default engineering posture.

*Justin Foley*

VP of Engineering, Later

```json
{"@context":"https://schema.org","@type":"Course","name":"SurrealDB for AI Engineers","description":"An eleven-lesson course from calling an LLM API to an agent that retrieves by meaning, remembers what it learned, writes its own queries, and can prove its retrieval works - all against one database.","url":"https://surrealdb.com/learn/ai","inLanguage":"en","isAccessibleForFree":false,"provider":{"@type":"Organization","name":"SurrealDB","url":"https://surrealdb.com"},"hasPart":[{"@type":"LearningResource","name":"SurrealDB for AI Engineers","url":"https://surrealdb.com/learn/ai"},{"@type":"LearningResource","name":"AI foundations","url":"https://surrealdb.com/learn/ai/ai-foundations"},{"@type":"LearningResource","name":"Vector embeddings and search","url":"https://surrealdb.com/learn/ai/vector-embeddings"},{"@type":"LearningResource","name":"Full-text search and BM25","url":"https://surrealdb.com/learn/ai/fulltext-search-bm25"},{"@type":"LearningResource","name":"Building a RAG knowledge base","url":"https://surrealdb.com/learn/ai/rag-knowledge-base"},{"@type":"LearningResource","name":"Hybrid search and reranking","url":"https://surrealdb.com/learn/ai/hybrid-search-reranking"},{"@type":"LearningResource","name":"Building an agent memory store","url":"https://surrealdb.com/learn/ai/agent-memory-store"},{"@type":"LearningResource","name":"Text-to-SurQL: agentic prompt engineering","url":"https://surrealdb.com/learn/ai/text-to-surrealql"},{"@type":"LearningResource","name":"Many sources and agents, one context layer","url":"https://surrealdb.com/learn/ai/multi-source-context-layer"},{"@type":"LearningResource","name":"Chunking strategies","url":"https://surrealdb.com/learn/ai/chunking-strategies"},{"@type":"LearningResource","name":"Evaluating retrieval quality","url":"https://surrealdb.com/learn/ai/evaluating-retrieval"},{"@type":"LearningResource","name":"Graph RAG beyond one hop","url":"https://surrealdb.com/learn/ai/graph-rag-multi-hop"}]}
```

```json
{"@context":"https://schema.org","@type":"LearningResource","name":"Building a RAG knowledge base","description":"Build a small RAG knowledge base - embeddings, semantic search, structured filters, a citation graph, and the assembled prompt - using nothing but the surreal CLI.","url":"https://surrealdb.com/learn/ai/rag-knowledge-base","learningResourceType":"lesson","isPartOf":{"@type":"Course","name":"SurrealDB for AI Engineers","url":"https://surrealdb.com/learn/ai"},"position":5}
```

```json
{"@context":"https://schema.org","@type":"Organization","@id":"https://surrealdb.com/#organization","name":"SurrealDB","url":"https://surrealdb.com","logo":"https://surrealdb.com/assets/static/logo.BG7_TG2b.svg","description":"SurrealDB is the context and memory layer for AI agents. A multi-model database for documents, graphs, vectors, and time-series.","foundingDate":"2022","legalName":"SurrealDB Ltd","identifier":{"@type":"PropertyValue","propertyID":"GB-COH","value":"13615201"},"address":{"@type":"PostalAddress","streetAddress":"3rd Floor, 1 Ashley Road","addressLocality":"Altrincham","addressRegion":"Cheshire","postalCode":"WA14 2DT","addressCountry":"GB"},"contactPoint":[{"@type":"ContactPoint","contactType":"customer support","email":"support@surrealdb.com","url":"https://surrealdb.com/contact","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"sales","email":"info@surrealdb.com","url":"https://surrealdb.com/contact","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"security","email":"security@surrealdb.com","url":"https://surrealdb.com/.well-known/security.txt","availableLanguage":"English"},{"@type":"ContactPoint","contactType":"legal","email":"legal@surrealdb.com","url":"https://surrealdb.com/legal","availableLanguage":"English"}],"hasCertification":[{"@type":"Certification","name":"SOC 2 Type 2"},{"@type":"Certification","name":"GDPR"},{"@type":"Certification","name":"Cyber Essentials Plus"},{"@type":"Certification","name":"ISO 27001"}],"owns":[{"@type":"SoftwareApplication","name":"SurrealDB","url":"https://surrealdb.com/surrealdb"},{"@type":"SoftwareApplication","name":"Agent Memory","url":"https://surrealdb.com/agent-memory"}],"knowsAbout":["multi-model databases","document databases","graph databases","vector search","time-series databases","SurrealQL","Agent Memory","real-time databases","embedded databases","context layer","graph ontology","distributed database","knowledge graphs","distributed transaction protocols","highly-scalable databases"],"sameAs":["https://www.wikidata.org/wiki/Q124316308","https://github.com/surrealdb/surrealdb","https://twitter.com/surrealdb","https://www.youtube.com/@surrealdb","https://www.linkedin.com/company/surrealdb","https://discord.gg/surrealdb","https://www.reddit.com/r/surrealdb","https://www.instagram.com/surrealdb","https://medium.com/surrealdb","https://dev.to/surrealdb"]}
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://surrealdb.com"},{"@type":"ListItem","position":2,"name":"Learn","item":"https://surrealdb.com/learn"},{"@type":"ListItem","position":3,"name":"Rag knowledge base","item":"https://surrealdb.com/learn/ai/rag-knowledge-base"}]}
```
