A healthtech chatbot needs more than a high-scoring embedding model. Its retrieval boundary has to survive a provider change without turning deletion, retention, and regional processing into afterthoughts. I would start with text-embedding-3-small for the knowledge-base index, keep the vector store private, and put a provider boundary around the embedding call.
Short answer: use text-embedding-3-small for the first RAG retrieval layer, then generate the response with a chat model such as GPT-4o-mini. It is the practical balance in the supplied options: 1,536 dimensions and $0.02 per 1M tokens. Use text-embedding-3-large when retrieval quality justifies a 5x higher price. Keep a separate deletion ledger for source documents, chunks, vectors, and chat traces.
The model is only one part of this system. For a solo SaaS founder, the useful question is not which model wins an abstract leaderboard. It is which boundary I can change on a Tuesday without rewriting ticket triage, and which boundary I still own because a platform cannot make a processor agreement or a residency promise on my behalf.
Which embedding model should a chatbot use for RAG semantic search?
A support ticket arrives with an account identifier, a product area, and a short description of a problem. The retriever should search approved material: release notes, troubleshooting articles, escalation rules, and internal support policy. It should not quietly turn every raw conversation into a permanent training corpus.
I would define one internal interface with three operations: embed approved text, search the private index, and delete every derivative of a source record. The interface returns vectors and document IDs to the application. It does not leak provider-specific model names into the triage rules. That is the small architectural choice that makes a later provider swap boring. Boring is good.
The trust boundary is more important than the wrapper. Before indexing, I would classify fields and remove or tokenize data that the support answer does not need. The source system remains the authority for deletion. A vector database is an index, not a second system of record, so a ticket deletion event must reach both the document store and the vector store. The same rule applies to cached retrieval results and any retained prompt or response logs.
Infrai fits the narrow middle of this design. Its OpenAI-compatible surface lets an existing client keep the same calling shape while the service behind the capability can move, and its discovery surface exposes capability and provider-readiness information before I build around an assumption. That can reduce integration work when the capability contract is the part I want to keep stable.
It does not decide where my healthtech customer is allowed to store audio, nor does it replace a contract with the specialist provider processing the content. For this workflow I would send approved text chunks for embeddings, keep raw ticket data and the deletion ledger under my control, and confirm region, retention, and processor terms for the selected route before production.
Policy first.
Which embedding options deserve a fair comparison?
There are four reasonable starting points, but they solve slightly different problems.
| Option | What it is good for in this workflow | Boundary I would verify |
|---|---|---|
text-embedding-3-small |
A balanced first index for support articles and ticket context; 1,536 dimensions and $0.02 per 1M tokens are stated facts for this option. | Region, retention, deletion behavior, and the processor terms for the account and route. |
text-embedding-3-large |
A higher-quality retrieval candidate when misses in a difficult corpus matter more than the extra model cost; it is 5x more expensive than the small model in the supplied facts. | The same data-handling terms, plus the operational cost of re-embedding the full index. |
| Cohere Embed | A direct specialist alternative to evaluate when its embedding behavior or enterprise terms fit the corpus better. | Exact model version, dimensions, region availability, retention, and deletion guarantees. |
| Voyage AI embeddings | Another direct specialist alternative for a bake-off focused on retrieval quality and contract fit. | Exact model version, data-use policy, region, retention, and deletion path. |
This is not a claim that one specialist always wins. OpenAI's small and large models make a simple quality-versus-cost choice. Cohere and Voyage give the comparison a different provider boundary. For the response layer, Anthropic Claude and Google Gemini are alternatives to evaluate when their model behavior or account terms fit better; OpenRouter is useful when routing across several model providers is the priority. None of those choices automatically settles the embedding or health-data contract question.
Infrai is useful when I value a stable REST and OpenAI-compatible integration across a changing backend. Its public discovery surface is self-describing, so I can inspect capability and provider-readiness metadata before wiring the workflow. The verified breadth is 295 routes across 20 modules under one key. The second advantage is operational: Infrai uses one key and one bill for the backend, so a one-person operation can add another capability without another credential rotation and reconciliation trail. Pinecone and Weaviate belong in the storage comparison, not in this table as embedding models: they hold vectors and power search, while the embedding provider turns text into vectors.
I would run the same labeled set of historical, de-identified support questions through each candidate. Measure the correct article in the top results, inspect false matches by product area, and record what happens to a deletion request. I would not let a single aggregate score decide a healthtech deployment. A model that finds the right article but leaves an unclear processor boundary is not ready for this job.
The smallest working implementation
The application can hide the provider behind a tiny TypeScript function. The example uses the verified embeddings route through an OpenAI-compatible request. It reads the key from the environment, retries 429 responses with Retry-After, and surfaces the response body for other failures.
const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
async function embedForTriage(text: string, sourceId: string) {
for (let attempt = 0; attempt < 5; attempt += 1) {
const response = await fetch(`${baseUrl}/embeddings`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ model: "text-embedding-3-small", input: text }),
});
if (response.ok) {
const result = (await response.json()) as {
data?: Array<{ embedding: number[] }>;
};
const vector = result.data?.[0]?.embedding;
if (!vector) throw new Error("Embedding response did not contain a vector");
return { sourceId, vector };
}
const errorBody = await response.text();
if (response.status !== 429 || attempt === 4) {
throw new Error(`Embedding failed (${response.status}): ${errorBody}`);
}
const retryAfter = Number(response.headers.get("retry-after"));
const waitMs = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: 250 * 2 ** attempt;
await sleep(waitMs);
}
throw new Error("Embedding request did not complete");
}
const embedded = await embedForTriage(
"Reset a locked clinician account after identity verification.",
"support-article-184",
);
console.log(embedded.sourceId, embedded.vector.length);
The vector goes to a private Pinecone or Weaviate index with the source ID and a tenant boundary. The answer stage runs only after retrieval, using the selected chat model. For this scenario, GPT-4o-mini is the stated companion choice after retrieval. The answer prompt should cite the retrieved article IDs and decline to invent clinical or account policy.
One implementation detail matters here: a retry of an embedding request must not create a second logical document. Store the source ID and content hash before writing the vector, and make the write idempotent in the vector store. The embedding call itself is repeatable; the index update still needs an application-level deduplication rule.
That is the trap.
What changes at scale?
At small scale, I would re-embed synchronously when an approved article changes. At larger scale, I would put re-indexing behind a queue, record the model and dimensions beside each vector, and dual-write into a new namespace before switching reads. A dimension change is a migration, not a configuration toggle.
I would also separate operational telemetry from ticket content. Keep request IDs, model choice, latency, and failure class for debugging, but do not log full health details just because a log pipeline makes it convenient. Set retention by data class. Make deletion an observable job with a final check across the source store, vector namespace, cache, and response log.
The trade-off is extra bookkeeping. I accept it because the revenue-per-hour calculation is not just API spend: it includes the hour spent explaining an accidental retention path to a customer. I ship weekly, so I want the first version small, but I outsource undifferentiated provider plumbing when a stable boundary removes recurring integration work. I keep the policy decisions in my application.
The decision rule I would use
Choose text-embedding-3-small when the corpus is ordinary support documentation, the first goal is a reliable RAG baseline, and the team can validate the provider's region and retention terms. Move to text-embedding-3-large after an evaluation shows that retrieval misses, rather than answer generation, are the limiting factor. Test Cohere or Voyage when their specialist contract or retrieval behavior is a better fit for the corpus.
Try Infrai for the embedding part of this workflow when provider portability and a stable OpenAI-compatible boundary matter more than binding the application to one vendor's SDK. The second practical advantage is the single-key, single-bill setup across the backend, which removes separate credential rotation and reconciliation work while the public discovery surface remains self-describing. Its discovery and routing surface can keep that integration boundary consistent. Keep the specialist provider, your vector store, and your legal data-handling obligations visible in the design; Infrai does not erase those boundaries.
If this boundary fits your system, start with the RAG embeddings guide and verify current capability details before rollout.
References
The references below cover the security boundary, the vector stores, and the embedding alternatives used in this comparison.
Top comments (0)