Knowledge Base
Add document knowledge to agents for grounded, accurate answers
The knowledge system lets agents retrieve relevant information from PDFs, documents, and text before answering, grounding responses in your own sources.
from praisonaiagents import Agent
agent = Agent(
name="Research Assistant",
instructions="Answer questions using the knowledge base.",
knowledge=["research_paper.pdf", "data.txt"],
)
agent.start("What are the key findings?")The user asks about their documents; the agent embeds, searches, and answers from your PDFs and text.
Key Features
Process PDFs, documents, spreadsheets, images, and raw text
CardMultiple strategies for optimal text segmentation
CardVector-based search with optional reranking
CardUser, agent, and run-specific knowledge scoping
CardOptional relationship extraction and storage
CardAutomatic quality assessment for stored knowledge
Quick Start
- Level 1 โ List of sources (simplest)
Pass a list of files, directories, or inline text and the agent answers from them.
python from praisonaiagents import Agent agent = Agent( name="Research Assistant", instructions="Answer questions using the knowledge base.", knowledge=["research_paper.pdf", "data.txt"], ) agent.start("What are the key findings?") - Level 2 โ Dict (inline config)
Use a dict to pick a vector store while still passing sources inline.
python from praisonaiagents import Agent agent = Agent( name="Research Assistant", instructions="Answer questions using the knowledge base.", knowledge={ "sources": ["research_paper.pdf", "data.txt"], "vector_store": { "provider": "chroma", "config": {"collection_name": "research_docs", "path": ".praison"}, }, }, ) agent.start("What are the key findings?") - Level 3 โ Config class (full control)
Use
KnowledgeConfigfor typed control over chunking, retrieval, and reranking.python from praisonaiagents import Agent, KnowledgeConfig agent = Agent( name="Research Assistant", instructions="Answer questions using the knowledge base.", knowledge=KnowledgeConfig( sources=["research_paper.pdf", "data.txt"], chunking_strategy="semantic", retrieval_k=5, rerank=True, ), ) agent.start("What are the key findings?")
Use a non-OpenAI embedder
By default your knowledge base embeds with OpenAI. Point it at Gemini, Cohere, Ollama, or any mem0-supported provider by setting embedder or embedder_config.
Shorthand
Pass the provider name to use its default embedding model.
from praisonaiagents import Agent, KnowledgeConfig
agent = Agent(
instructions="Answer from the knowledge base.",
knowledge=KnowledgeConfig(
sources=["docs/"],
embedder="gemini", # provider shorthand
),
)
agent.start("What are the key findings?")Full config
Use embedder_config to pin a model or pass provider-specific options.
from praisonaiagents import Agent, KnowledgeConfig
agent = Agent(
instructions="Answer from the knowledge base.",
knowledge=KnowledgeConfig(
sources=["docs/"],
embedder_config={
"provider": "gemini",
"config": {"model": "models/text-embedding-004"},
},
),
)
agent.start("What are the key findings?")Local Ollama
Run embeddings locally with Ollama โ no API key needed.
from praisonaiagents import Agent, KnowledgeConfig
agent = Agent(
instructions="Answer from the knowledge base.",
knowledge=KnowledgeConfig(
sources=["docs/"],
embedder_config={
"provider": "ollama",
"config": {
"model": "nomic-embed-text",
"ollama_base_url": "http://localhost:11434",
},
},
),
)
agent.start("What are the key findings?")Supported providers include openai, gemini, cohere, huggingface, ollama, voyage, and together.
How It Works
| Phase | What happens |
|---|---|
| 1. Add | Documents are chunked, embedded, and stored in the vector store via knowledge.add() |
| 2. Search | knowledge.search(query) embeds the query and returns top-k similar chunks |
| 3. Retrieve | Agent injects the chunks as context before calling the LLM |
| 4. Generate | LLM answers using the retrieved knowledge; responses are grounded in your data |
Configuration Options
KnowledgeConfig SDK ReferenceFull parameter reference for KnowledgeConfig
The most common options at a glance:
| Option | Type | Default | Description |
|---|---|---|---|
sources | list[str] | [] | Files, directories, raw text, or cloud URIs (s3://, gs://, az://, Azure blob HTTPS). Arbitrary web URLs are not ingested. |
embedder | str | "openai" | Provider shorthand. Any value other than "openai" overrides the default (e.g. "gemini", "cohere", "ollama", "huggingface", "voyage"). "openai" means “no override”. |
embedder_config | Dict[str, Any] | None | Full embedder dict {"provider": ..., "config": {...}}. Use it to pin a model or pass provider-specific settings. Merged with embedder when both are given. |
chunking_strategy | str | "semantic" | "fixed" / "semantic" / "sentence" / "paragraph" |
retrieval_k | int | 5 | Number of chunks to retrieve per query |
rerank | bool | False | Apply reranking to improve result order |
Basic Configuration
knowledge_config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "knowledge_base",
"path": ".praison",
"distance_metric": "cosine"
}
},
"embedder": {
"provider": "openai",
"config": {
# Overridden by OPENAI_EMBEDDING_MODEL if set; see /docs/cli/knowledge-cli#environment-variables
"model": "text-embedding-3-small"
}
}
}If your configured backend seems ignored
Configure a mem0 or mongodb vector store on a release before 2026-07-14 and find that searches feel like keyword matching? Your Knowledge instance may have been silently falling back to SQLite. This was a bug (fixed in PR #2982) where the adapter constructors rejected an internal verbose keyword and the resulting TypeError was swallowed.
Check which adapter you actually got:
from praisonaiagents import Knowledge
kb = Knowledge(config={
"vector_store": {
"provider": "mem0",
"config": {"collection_name": "my_docs"},
}
})
print(type(kb.memory).__name__) # 'Mem0Adapter' on the fix; 'SQLiteKnowledgeAdapter' means you're on a buggy release.Upgrade to a release built from main after commit 69d7ecf to fix it. An explicitly-configured backend that fails to initialise now emits a WARNING log โ no more silent degradation:
WARNING praisonaiagents.knowledge.knowledge: Knowledge provider 'mem0' failed to initialize (<reason>); falling back to a different backend. Retrieval quality may be reduced.The configured backend is honoured on releases built after commit 69d7ecf; before that, the same code silently ran on SQLite.
from praisonaiagents import Agent, Knowledge
kb = Knowledge(config={
"vector_store": {
"provider": "mem0",
"config": {"collection_name": "research_docs"},
}
})
agent = Agent(
name="Researcher",
instructions="Answer research questions using the knowledge base.",
knowledge=kb,
)
agent.start("What did we learn about solar output in 2024?")Advanced Configuration with Graph Store
knowledge_config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "knowledge_base",
"path": ".praison"
}
},
"graph_store": {
"provider": "neo4j",
"config": {
"url": "bolt://localhost:7687",
"username": "neo4j",
"password": "password"
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0
}
},
"reranker": {
"enabled": True,
"default_rerank": False
}
}Choosing Sources and Chunking
Pick a source type, then a chunking strategy that matches your content.
The chosen chunker applies to every text source uniformly โ no extension bypasses it (since PraisonAI PR #4831).
Chunking Strategies
kb = Knowledge({
"chunker": {
"name": "token",
"chunk_size": 500,
"chunk_overlap": 50
}
})Best for: Consistent chunk sizes, token-limited models
kb = Knowledge({
"chunker": {
"name": "sentence",
"chunk_size": 10, # sentences per chunk
"min_chunk_size": 3
}
})Best for: Natural text boundaries, Q&A systems
kb = Knowledge({
"chunker": {
"name": "semantic",
"threshold": 0.7,
"min_chunk_size": 100
}
})Best for: Topic-based segmentation, research papers
kb = Knowledge({
"chunker": {
"name": "sdpm",
"max_chunk_size": 1000
}
})Best for: Document structure preservation
Document Processing
Supported File Types
- PDF (.pdf)
- Word (.doc, .docx)
- Text (.txt)
- Markdown (.md)
- RTF (.rtf)
- Excel (.xls, .xlsx)
- CSV (.csv)
- JSON (.json)
- XML (.xml)
- Images (OCR)
- Local HTML files (.html, .htm)
- Raw text strings
Any UTF-8 text file โ source code (.py, .js, .ts, .go, .rs, .java), config files (.yaml, .toml, .sh, .ipynb, .rst), and suffix-less files like Dockerfile or .gitignore. Content is read and chunked; metadata records the real extension.
Indexing a Codebase
Point knowledge=[...] at source files, configs, and suffix-less files โ each UTF-8 text file is read and chunked.
from praisonaiagents import Agent
agent = Agent(
name="Code Reviewer",
instructions="Answer questions about the codebase.",
knowledge=["src/auth.py", "src/config.yaml", "Dockerfile"],
)
agent.start("How does authentication work?")Processing Options
# Add with metadata
kb.add(
"research.pdf",
user_id="user123",
metadata={
"category": "AI Research",
"year": 2024,
"author": "Dr. Smith"
}
)
# Batch processing
documents = ["doc1.pdf", "doc2.txt", "doc3.md"]
for doc in documents:
kb.add(doc, user_id="user123")Handling indexing failures
Indexing errors are surfaced, not swallowed. When the embedding call fails, the CLI exits non-zero and the Python API raises.
from praisonaiagents import Knowledge
kb = Knowledge()
try:
kb.add("research_paper.pdf")
except RuntimeError as e:
# message includes the embedding model and the underlying error, e.g.
# "Failed to generate embedding (model=text-embedding-3-small): 403 model_not_found"
print(f"Indexing failed: {e}")The lower-level ChromaKnowledgeAdapter.add() returns an AddResult instead of raising:
result = adapter.add("Paris is the capital of France.")
if not result.success:
print(result.message) # "Failed to generate embedding (model=โฆ): โฆ"Search degrades gracefully โ a failed embedding is logged at WARNING and the call returns an empty SearchResult rather than raising, so an embedding outage cannot bring down the calling agent.
Search Features
Basic Search
# Simple search
results = kb.search("artificial intelligence", limit=5)
# User-scoped search
results = kb.search(
query="machine learning",
user_id="user123",
limit=10
)Advanced Search Options
# Enable Mem0 reranking for better relevance
results = kb.search(
query="neural networks",
user_id="user123",
rerank=True,
top_k=20 # Retrieve more before reranking
)# Combine keyword and semantic search
results = kb.search(
query="transformer architecture",
user_id="user123",
keyword_search=True, # Better recall
filter_memories=True # Better precision
)# Filter by metadata
results = kb.search(
query="implementation details",
user_id="user123",
filters={
"category": "technical",
"year": {"$gte": 2023}
}
)Memory Integration
When used with agents, knowledge automatically integrates with memory:
agent = Agent(
name="Research Assistant",
knowledge={
"sources": ["papers/"],
"vector_store": {
"provider": "chroma",
"config": {"collection_name": "research_docs"}
}
},
memory=True # Enable memory integration
)
# Knowledge is automatically searched during conversations
response = agent.start("What does the research say about transformers?")Graph Store Features
Graph stores add relationship extraction and connection queries on top of semantic search.
Configuration
knowledge_config = {
"graph_store": {
"provider": "neo4j", # or "memgraph"
"config": {
"url": "bolt://localhost:7687",
"username": "neo4j",
"password": "password"
}
},
"extract_relationships": True
}Relationship Queries
# Find related concepts
results = kb.search_graph(
"What concepts are related to transformers?",
user_id="user123"
)
# Explore connections
results = kb.search_graph(
"How is attention mechanism connected to BERT?",
user_id="user123"
)Best Practices
Match chunk size to your query complexity
Use smaller chunks (100-200 tokens) for precise fact retrieval. Use larger chunks (500-1000 tokens) when answers need more context. Semantic chunking works best for research papers and long-form documents.
Separate collections by domain
Use a different collection_name per knowledge domain (e.g., product_docs, legal_contracts). This prevents cross-contamination and allows targeted filtering by domain.
Use metadata for filtering
Add metadata when indexing documents to enable filters= in searches. Filter by category, year, or author to narrow results without changing query text.
Enable reranking for higher precision
Set rerank=True in kb.search() when you need top-quality results. Reranking retrieves more candidates then scores them for relevance โ best for Q&A and research assistants.
Example: Research Assistant
from praisonaiagents import Agent
from praisonaiagents import Knowledge
# Configure knowledge base
knowledge_config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "research_papers",
"path": ".praison"
}
},
"chunker": {
"name": "semantic",
"threshold": 0.7
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
"reranker": {
"enabled": True
}
}
# Create research assistant
research_agent = Agent(
name="Research Assistant",
instructions="""You are an expert research assistant.
Use the knowledge base to provide accurate, well-sourced answers.
Always cite the specific documents you reference.""",
knowledge={
"sources": ["research_papers"],
**knowledge_config
}
)
# Use the assistant
response = research_agent.start(
"What are the main approaches to AI alignment?"
)
# Direct knowledge queries
kb = research_agent.knowledge
papers = kb.search("alignment techniques", limit=5)
for paper in papers:
print(f"- {paper['text'][:100]}...")
print(f" Source: {paper.get('metadata', {}).get('source')}")Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
praisonai knowledge index exits 1 with no chunks stored | Directory contained no supported file types, or every file failed to extract. | Check the file extensions and re-run with --verbose to see per-file diagnostics. |
AddResult.message: Failed to generate embedding (model=โฆ): 401 | Missing or invalid OPENAI_API_KEY. | Export a valid key: export OPENAI_API_KEY=sk-โฆ. |
AddResult.message: Failed to generate embedding (model=โฆ): 404 model_not_found | OPENAI_EMBEDDING_MODEL is set to a name the provider doesn’t recognise. | Unset it (default is text-embedding-3-small) or set it to a supported model like text-embedding-3-large. |
search() returns empty results for content you just indexed | Embedding failure at index time was masked by an older build. | Upgrade to the latest release (PR #2823); indexing now exits non-zero if nothing was stored. |
| Search is slower or more expensive than expected | OPENAI_EMBEDDING_MODEL=text-embedding-3-large is set. | Switch back to text-embedding-3-small for latency-sensitive apps, or budget for the ~6.5ร cost. |
| MongoDB search returns another tenant’s documents | On releases before PR #3810, the MongoDB adapter silently ignored user_id / agent_id / run_id. | Upgrade to a release built after commit 6b6707c1. The adapter now honors these scopes on both add() and search() for tenant isolation. |
RuntimeError: Chroma persist failed at '<path>' (PanicException: ...) on Agent.start(...) or Knowledge.add(...) | The on-disk sqlite Chroma store at <path> is corrupt, locked by another process, or was written by an incompatible Chroma version. | Delete <path> and re-index, or point knowledge={"vector_store": {"config": {"path": "/a/fresh/dir"}}} at a fresh directory. |
RuntimeError: Knowledge indexing backend crashed on <file> while indexing a directory | The vector-store backend panicked on that file (typically a Chroma rust-binding panic on a corrupt store). | Delete the persist directory or move <file> aside and re-run. |
| Two unrelated projects appear to share the same Knowledge base | You are on a pre-#4422 release where the default path was the cwd-relative string "knowledge_db". | Upgrade to the release built from PraisonAI PR #4422; defaults are now absolute (<project>/.praisonai/knowledge/chroma). |
Windows: Agent(knowledge=["docs/"]) SIGSEGVs or hangs | Pre-#4422 issue #4376: pyo3 PanicException (a BaseException) unwound the process instead of surfacing as a Python error. | Upgrade; panics are now caught and re-raised as RuntimeError with an actionable message. |
search() returns nothing after indexing .py / .js / other source files, or a code directory | Pre-#4788 release: files with unlisted extensions had their path stored as content, not their contents. | Upgrade to a release built from PraisonAI PR #4788; source files are now read and chunked. |
ValueError: Empty text file or ValueError: Cannot read <path> as UTF-8 text when indexing a directory | The file is empty, or is binary (image bytes with a .txt extension, encoded blob, etc.). | Remove or skip the file. Binary media (.png, .mp3, etc.) go through the media branch, not the text branch. |
After indexing a .md/.txt/.csv/.json/.xml/.html file, search() returns fewer, coarser, or lowercased results than the same content in a .pdf or .rst file. | Pre-#4831 release: the text branch stored the whole file as one memory and lowercased it, so chunk_size / chunk_overlap were ignored on these extensions. | Upgrade to a release built from PraisonAI PR #4831. Re-index the affected files so they are stored as chunks with case preserved. |
chunk_size set in the chunker config seems to have no effect on .md/.txt indexing. | Same root cause as above โ the text branch bypassed the chunker on pre-#4831 releases. | Upgrade to a build that includes PR #4831; the same config now applies uniformly to every text branch. |
ImportError: chonkie package not found. Please install it using: pip install 'praisonaiagents[knowledge]' when calling agent.start(...) with chunking_strategy="semantic" (the default), "sdpm", or "late", or with any string embedding_model | The chonkie package is not installed. The default chunker is semantic, so this fires on the first knowledge lookup even if you never set chunking_strategy explicitly. Since PraisonAI PR #5105 the error surfaces with an actionable hint instead of a raw ModuleNotFoundError. | pip install 'praisonaiagents[knowledge]' (quotes required in zsh). Or switch to a chunker that does not need chonkie embeddings by passing KnowledgeConfig(chunking_strategy="sentence") or "paragraph". |
ImportError mentioning chonkie.embeddings but without the pip install hint | chonkie is installed but its embeddings submodule failed to import (typically a broken or incompatible transitive dependency such as sentence-transformers, torch, or transformers). Since PraisonAI PR #5105 the original error is preserved so the real cause is not masked behind misleading install advice. | Read the underlying error and reinstall or upgrade the named package. pip install --upgrade sentence-transformers fixes the most common case. |
Async safety
Knowledge search runs on a worker thread when called from an async agent (agent.astart(...) or agent.astream(...)). It never blocks the event loop, so multiple async agents โ or an asyncio.gather(...) of tasks โ that all query the same knowledge base progress in parallel instead of serialising on the slowest lookup.
No user-facing change: the async path automatically dispatches the underlying (synchronous) embedding + vector-store call via asyncio.to_thread.
import asyncio
from praisonaiagents import Agent
agent = Agent(
name="Research Assistant",
instructions="Answer questions using the knowledge base.",
knowledge=["research_paper.pdf"],
)
async def main():
# Both lookups offload to worker threads โ the loop stays responsive.
await asyncio.gather(
agent.astart("What are the key findings?"),
agent.astart("Summarise the methodology"),
)
asyncio.run(main())See Async Safety for the full set of async guarantees.
Related
Build retrieval-augmented generation pipelines
Vector StoreStore and query embeddings with a pluggable, namespace-aware backend
Async SafetyHow knowledge search, memory writes, and the in-memory adapter behave under concurrent tasks
Cloud SourcesLoad knowledge from S3, Google Cloud Storage, and Azure Blob buckets