RAG (Files & Search)

View as Markdown

RAG (Retrieval-Augmented Generation)

Upload documents, generate embeddings, and query them semantically — all through client.rag.

Quick upload

The uploadFile convenience method handles both the init call and the PUT to the signed URL in one step:

1import { MeshAPI } from "meshapi-node-sdk";
2import fs from "fs";
3
4const client = new MeshAPI({ baseUrl: "https://api.meshapi.ai", token: "rsk_..." });
5
6const upload = await client.rag.uploadFile({
7 file_name: "handbook.pdf",
8 mime_type: "application/pdf",
9 content: fs.readFileSync("handbook.pdf"),
10});
11
12console.log("File ID:", upload.file_id);

Two-step upload

Use initUpload when you want to control the PUT yourself:

1const upload = await client.rag.initUpload({
2 file_name: "handbook.pdf",
3 mime_type: "application/pdf",
4 embed: false,
5});
6
7// PUT bytes directly to the signed URL (no auth header needed)
8await fetch(upload.signed_url, {
9 method: "PUT",
10 body: fs.readFileSync("handbook.pdf"),
11 headers: { "Content-Type": "application/pdf" },
12});

Trigger embedding

1const resp = await client.rag.embed({ file_ids: [upload.file_id] });
2for (const r of resp.results) {
3 console.log(r.file_id, r.embedding_status);
4}

Poll until ready

1const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
2
3while (true) {
4 const status = await client.rag.get(upload.file_id);
5 if (status.embedding_status === "ready") break;
6 if (status.embedding_status === "failed") {
7 throw new Error(`Embedding failed: ${status.last_error_code}`);
8 }
9 await sleep(3_000);
10}
1const results = await client.rag.search({
2 query: "What is the refund policy?",
3 top_k: 5,
4 file_ids: [upload.file_id], // omit to search all files
5});
6
7for (const r of results.results) {
8 console.log(`[${r.score.toFixed(3)}] ${r.text}`);
9}

Search options

FieldTypeNotes
querystringPlain-language question
top_knumberResults to return (1–50, default 5)
file_idsstring[]Restrict to specific files
filterobjectMatch on metadata key-value pairs
date_fromnumberUnix timestamp — only chunks created after
date_tonumberUnix timestamp — only chunks created before

List files

1const list = await client.rag.list({ limit: 50 });
2console.log(`${list.total} total files`);
3for (const f of list.files) {
4 console.log(f.file_id, f.upload_status, f.embedding_status);
5}

RAG chat

Combine search results with a chat completion:

1const results = await client.rag.search({
2 query: "What is the refund policy?",
3 top_k: 3,
4});
5const context = results.results.map((r) => r.text).join("\n\n");
6
7const reply = await client.chat.completions.create({
8 model: "openai/gpt-4o-mini",
9 messages: [
10 { role: "system", content: `Answer using only the context below.\n\n${context}` },
11 { role: "user", content: "What is the refund policy?" },
12 ],
13});
14console.log(reply.choices[0]?.message.content);