Prompt
How do I set up an LLM API provider for semantic search over internal documents?
Latest observation
To set up an LLM API provider for semantic search over internal documents, you usually build a pipeline with four parts:
- Ingest documents
- Create embeddings
- Store them in a vector database
- Retrieve relevant chunks and optionally rerank / answer with an LLM
Here’s a practical setup.
1) Pick an LLM/embedding provider
For semantic search, you need an embedding model more than a chat model.
Common options:
- OpenAI — strong general-purpose embeddings
- Cohere — good embeddings and reranking
- Anthropic — excellent for generation, but embeddings are typically handled via another provider
- Google Gemini / Vertex AI
- Azure OpenAI
- AWS Bedrock
- Open-source via Hugging Face / local models
If you want a straightforward managed setup, choose:
- Embeddings: OpenAI or Cohere
- Vector DB: Pinecone, Weaviate, pgvector, Milvus, or Elasticsearch
- Answering model: same provider or a chat model of your choice
2) Decide the architecture
A common semantic search architecture:
Offline indexing flow
- Collect internal docs: PDFs, docs, wiki pages, tickets, emails
- Extract text
- Split into chunks
- Generate embeddings for each chunk
- Store:
- embedding vector
- chunk text
- metadata (doc title, URL, permissions, date, department)
Query flow
- User enters search query
- Embed query with same embedding model
- Retrieve nearest vectors from vector DB
- Optional:
- rerank top results
- filter by metadata and permissions
- generate answer with an LLM using retrieved chunks
3) Prepare and chunk documents
You should not embed whole documents unless they’re small. Split them into chunks like:
- 200–800 tokens per chunk
- 10–20% overlap
- Keep document structure if possible
Store metadata for each chunk:
doc_idchunk_idsourcetitlecreated_atacl/permissionsdepartmenturl
This helps with filtering and access control.
4) Create embeddings
Example with OpenAI-style embedding usage:
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")
text = "Internal policy says all requests must be approved by finance."
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
embedding = response.data[0].embedding
print(len(embedding))
Use the same embedding model for:
- indexing documents
- embedding user queries
Consistency matters.
5) Store vectors in a vector database
Popular choices:
Managed
- Pinecone
- Weaviate Cloud
Self-hosted / database-native
- pgvector in PostgreSQL
- Milvus
- Elasticsearch / OpenSearch vector search
A vector DB record usually contains:
idembeddingtextmetadata
Example schema conceptually:
{
"id": "doc123_chunk4",
"embedding": [0.12, 0.98, ...],
"text": "The reimbursement policy requires receipts...",
"metadata": {
"doc_id": "doc123",
"title": "Expense Policy",
"department": "Finance"
}
}
6) Implement retrieval
At query time:
- Embed the query
- Search the vector DB for top-k nearest neighbors
- Optionally apply metadata filters
- Optionally rerank results with an LLM or reranker model
Pseudo-flow:
query = "How do I submit travel expenses?"
query_embedding = embed(query)
results = vector_db.search(
vector=query_embedding,
top_k=5,
filter={"department": "Finance"}
)
If your internal documents have permissions, apply them before returning results.
7) Add an LLM for answer generation, if needed
If you want search + answer, use RAG (Retrieval-Augmented Generation):
- Retrieve the best chunks
- Pass them to the LLM with a prompt like:
- “Answer using only the provided context”
- “Cite sources”
- “If unsure, say you don’t know”
Example prompt structure:
Context:
1. [Policy excerpt 1]
2. [Policy excerpt 2]
Question:
How do I submit travel expenses?
Answer:
This gives users a direct answer, not just search results.
8) Add access control and security
For internal documents, this is critical.
Best practices:
- Store document-level permissions in metadata
- Filter retrieval by user identity/groups
- Encrypt data at rest and in transit
- Avoid sending sensitive docs to an external provider unless approved
- Consider redaction before embedding for highly sensitive content
- Log queries carefully to avoid leaking secrets
If you have strict compliance needs, consider:
- Azure OpenAI in your tenant
- AWS Bedrock
- Self-hosted embeddings and vector DB
9) Improve quality
Helpful enhancements:
- Hybrid search: combine keyword + vector search
- Reranking: improves top result quality
- Chunk tuning: adjust chunk size and overlap
- Metadata filters: department, date, doc type
- Synonym expansion: useful for internal jargon
- Evaluation set: test queries with known good answers
10) Minimal implementation stack
A simple, solid stack could be:
- Document processing: Python + unstructured / pypdf / docx parser
- Embeddings: OpenAI or Cohere
- Vector DB: pgvector or Pinecone
- Answering model: GPT-style chat model
- API layer: FastAPI
- Auth: SSO / OAuth / JWT with ACL checks
11) Example end-to-end flow
- Upload internal PDF
- Extract text
- Split into chunks
- Embed chunks
- Save in vector DB with permissions
- User searches “vacation carryover policy”
- Embed query
- Retrieve top relevant chunks for that user
- Show search results or generate answer
- Return citations
12) Things to watch out for
- Poor PDF text extraction
- Huge chunks that reduce retrieval precision
- Missing metadata/permissions
- Not using the same embedding model for indexing and search
- Overreliance on generation without retrieval
- Sending confidential docs to unapproved third-party APIs
If you want, I can also give you:
- a specific provider recommendation based on your cloud stack,
- a working Python example using OpenAI + pgvector,
- or a system design diagram for semantic search over internal docs.
Observation history
Unlock observation history
Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.
How did Obsurfable measure this prompt?
Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.
Which AI systems does Obsurfable collect answers from?
OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.