Documentation updates

This commit is contained in:
Yiorgis Gozadinos 2025-12-10 13:02:49 +02:00
parent be0e3c3472
commit 8206498af8
No known key found for this signature in database
6 changed files with 94 additions and 161 deletions

129
README.md
View file

@ -1,22 +1,20 @@
# Haiku RAG
Opinionated agentic RAG powered by LanceDB, Pydantic AI, and Docling.
`haiku.rag` is an opinionated agentic RAG system that uses LanceDB for vector storage, Pydantic AI for multi-agent workflows, and Docling for document processing. It supports hybrid search (vector + full-text) with Reciprocal Rank Fusion, multiple embedding providers (Ollama, LM Studio, vLLM, OpenAI, VoyageAI), and includes research agents that plan, search, evaluate, and synthesize answers.
Agentic RAG built on [LanceDB](https://lancedb.com/), [Pydantic AI](https://ai.pydantic.dev/), and [Docling](https://docling-project.github.io/docling/).
## Features
- **Local LanceDB**: No external servers required, supports also LanceDB cloud storage, S3, Google Cloud & Azure
- **Multiple embedding providers**: Ollama, LM Studio, VoyageAI, OpenAI, vLLM
- **Multiple QA providers**: Any provider/model supported by Pydantic AI (Ollama, LM Studio, OpenAI, Anthropic, etc.)
- **Native hybrid search**: Vector + full-text search with native LanceDB RRF reranking
- **Reranking**: Default search result reranking with MixedBread AI, Cohere, Zero Entropy, or vLLM
- **Question answering**: Built-in QA agents on your documents
- **Research graph (multiagent)**: Plan → Search → Evaluate → Synthesize with agentic AI
- **File monitoring**: Auto-index files when run as server
- **CLI & Python API**: Use from command line or Python
- **MCP server**: Expose as tools for AI assistants
- **Flexible document processing**: Local (docling) or remote (docling-serve) processing
- **Hybrid search** — Vector + full-text with Reciprocal Rank Fusion
- **Reranking** — MxBAI, Cohere, Zero Entropy, or vLLM
- **Question answering** — QA agents with citations (page numbers, section headings)
- **Research agents** — Multi-agent workflows via pydantic-graph: plan, search, evaluate, synthesize
- **Document structure** — Stores full [DoclingDocument](https://docling-project.github.io/docling/concepts/docling_document/), enabling structure-aware context expansion and visual grounding
- **Multiple providers** — Embeddings: Ollama, OpenAI, VoyageAI, LM Studio, vLLM. QA/Research: any model supported by Pydantic AI
- **Local-first** — Embedded LanceDB, no servers required. Also supports S3, GCS, Azure, and LanceDB Cloud
- **MCP server** — Expose as tools for AI assistants (Claude Desktop, etc.)
- **File monitoring** — Watch directories and auto-index on changes
- **Inspector** — TUI for browsing documents, chunks, and search results
- **CLI & Python API** — Full functionality from command line or code
## Installation
@ -41,104 +39,51 @@ Install only the extras you need. See the [Installation](https://ggozad.github.i
## Quick Start
```bash
# Add documents
haiku-rag add "Your content here"
haiku-rag add "Your content here" --meta author=alice --meta topic=notes
haiku-rag add-src document.pdf --meta source=manual
# Index a PDF
haiku-rag add-src paper.pdf
# Search
haiku-rag search "query"
# Search with filters
haiku-rag search "query" --filter "uri LIKE '%.pdf' AND title LIKE '%paper%'"
# Ask questions
haiku-rag ask "Who is the author of haiku.rag?"
haiku-rag search "attention mechanism"
# Ask questions with citations
haiku-rag ask "Who is the author of haiku.rag?" --cite
haiku-rag ask "What datasets were used for evaluation?" --cite
# Deep QA (multi-agent question decomposition)
haiku-rag ask "Who is the author of haiku.rag?" --deep --cite
# Deep QA — decomposes complex questions into sub-queries
haiku-rag ask "How does the proposed method compare to the baseline on MMLU?" --deep
# Deep QA with verbose output
haiku-rag ask "Who is the author of haiku.rag?" --deep --verbose
# Research mode — iterative planning and search
haiku-rag research "What are the limitations of the approach?" --verbose
# Multiagent research (iterative plan/search/evaluate)
haiku-rag research \
"What are the main drivers and trends of global temperature anomalies since 1990?" \
--max-iterations 2 \
--confidence-threshold 0.8 \
--max-concurrency 3 \
--verbose
# Rebuild database (re-chunk and re-embed all documents)
haiku-rag rebuild
# Start server with file monitoring
# Watch a directory for changes
haiku-rag serve --monitor
```
To customize settings, create a `haiku.rag.yaml` config file (see [Configuration](https://ggozad.github.io/haiku.rag/configuration/)).
See [Configuration](https://ggozad.github.io/haiku.rag/configuration/) for customization options.
## Python Usage
## Python API
```python
from haiku.rag.client import HaikuRAG
from haiku.rag.config import Config
from haiku.rag.graph.agui import stream_graph
from haiku.rag.graph.research import (
ResearchContext,
ResearchDeps,
ResearchState,
build_research_graph,
)
async with HaikuRAG("database.lancedb") as client:
# Add document
doc = await client.create_document("Your content")
async with HaikuRAG("research.lancedb", create=True) as rag:
# Index documents
await rag.create_document_from_source("paper.pdf")
await rag.create_document_from_source("https://arxiv.org/pdf/1706.03762")
# Search (reranking enabled by default)
results = await client.search("query")
for chunk, score in results:
print(f"{score:.3f}: {chunk.content}")
# Search — returns chunks with provenance
results = await rag.search("self-attention")
for result in results:
print(f"{result.score:.2f} | p.{result.page_numbers} | {result.content[:100]}")
# Ask questions
answer = await client.ask("Who is the author of haiku.rag?")
# QA with citations
answer, citations = await rag.ask("What is the complexity of self-attention?")
print(answer)
# Ask questions with citations
answer = await client.ask("Who is the author of haiku.rag?", cite=True)
print(answer)
# Multiagent research pipeline (Plan → Search → Evaluate → Synthesize)
# Graph settings (provider, model, max_iterations, etc.) come from config
graph = build_research_graph(config=Config)
question = (
"What are the main drivers and trends of global temperature "
"anomalies since 1990?"
)
context = ResearchContext(original_question=question)
state = ResearchState.from_config(context=context, config=Config)
deps = ResearchDeps(client=client)
# Blocking run (final result only)
report = await graph.run(state=state, deps=deps)
print(report.title)
# Streaming progress (AG-UI events)
async for event in stream_graph(graph, state, deps):
if event["type"] == "STEP_STARTED":
print(f"Starting step: {event['stepName']}")
elif event["type"] == "ACTIVITY_SNAPSHOT":
print(f" {event['content']}")
elif event["type"] == "RUN_FINISHED":
print("\nResearch complete!\n")
result = event["result"]
print(result["title"])
print(result["executive_summary"])
for cite in citations:
print(f" [{cite.chunk_id}] p.{cite.page_numbers}: {cite.content[:80]}")
```
For research agents and streaming with [AG-UI](https://docs.ag-ui.com/), see the [Agents docs](https://ggozad.github.io/haiku.rag/agents/).
## MCP Server
Use with AI assistants like Claude Desktop:

View file

@ -53,14 +53,33 @@ Authentication is handled through standard cloud provider credentials (AWS CLI,
**Note:** Table optimization is automatically handled by LanceDB Cloud (`db://` URIs) and is disabled for better performance. For object storage backends (S3, Azure, GCS), optimization is still performed locally.
## Database Auto-creation
## Database Creation
haiku.rag intelligently handles database creation based on operation type:
Databases must be explicitly created before use:
- **Write operations** (add, add-src, delete, rebuild): Automatically create the database and required tables if they don't exist
- **Read operations** (list, get, search, ask, research): Fail with a clear error if the database doesn't exist
**CLI:**
```bash
# Create in default location (see Configuration File Locations below)
haiku-rag init
This prevents the common mistake where a search query accidentally creates an empty database. To initialize your database, simply add your first document using `haiku-rag add` or `haiku-rag add-src`.
# Create at custom path
haiku-rag init --db /path/to/database.lancedb
```
**Python:**
```python
# Create at custom path
async with HaikuRAG("/path/to/database.lancedb", create=True) as client:
...
# Create in default location
async with HaikuRAG(create=True) as client:
...
```
The [default location](index.md#configuration-file-locations) is platform-specific (e.g., `~/Library/Application Support/haiku.rag/` on macOS).
Operations on non-existent databases raise `FileNotFoundError`. This prevents accidental database creation from typos or misconfigured paths.
## Vector Indexing

View file

@ -1,21 +1,20 @@
# haiku.rag
`haiku.rag` is an opinionated agentic RAG system that uses LanceDB for vector storage, Pydantic AI for multi-agent workflows, and Docling for document processing. It supports hybrid search (vector + full-text) with Reciprocal Rank Fusion, multiple embedding providers (Ollama, LM Studio, vLLM, OpenAI, VoyageAI), and includes research agents that plan, search, evaluate, and synthesize answers.
Agentic RAG built on [LanceDB](https://lancedb.com/), [Pydantic AI](https://ai.pydantic.dev/), and [Docling](https://docling-project.github.io/docling/).
## Features
- **Local LanceDB**: No external servers required, supports also LanceDB cloud storage, S3, Google Cloud & Azure
- **Multiple embedding providers**: Ollama, LM Studio, VoyageAI, OpenAI, vLLM
- **Multiple QA providers**: Any provider/model supported by Pydantic AI (Ollama, LM Studio, OpenAI, Anthropic, etc.)
- **Native hybrid search**: Vector + full-text search with native LanceDB RRF reranking
- **Reranking**: Optional result reranking with MixedBread AI, Cohere, Zero Entropy, or vLLM
- **Question answering**: Built-in QA agents on your documents
- **Research graph (multiagent)**: Plan → Search → Evaluate → Synthesize with agentic AI
- **File monitoring**: Auto-index files when run as server
- **Extended file format support**: Parse PDF, DOCX, HTML, Markdown, images, code files and more
- **Flexible document processing**: Local processing with docling or remote with [docling-serve](remote-processing.md)
- **MCP server**: Expose as tools for AI assistants
- **CLI & Python API**: Use from command line or Python
- **Hybrid search** — Vector + full-text with Reciprocal Rank Fusion
- **Reranking** — MxBAI, Cohere, Zero Entropy, or vLLM
- **Question answering** — QA agents with citations (page numbers, section headings)
- **Research agents** — Multi-agent workflows via pydantic-graph: plan, search, evaluate, synthesize
- **Document structure** — Stores full [DoclingDocument](https://docling-project.github.io/docling/concepts/docling_document/), enabling structure-aware context expansion and visual grounding
- **Multiple providers** — Embeddings: Ollama, OpenAI, VoyageAI, LM Studio, vLLM. QA/Research: any model supported by Pydantic AI
- **Local-first** — Embedded LanceDB, no servers required. Also supports S3, GCS, Azure, and LanceDB Cloud
- **MCP server** — Expose as tools for AI assistants (Claude Desktop, etc.)
- **File monitoring** — Watch directories and auto-index on changes
- **Inspector** — TUI for browsing documents, chunks, and search results
- **CLI & Python API** — Full functionality from command line or code
## Quick Start
@ -30,15 +29,15 @@ Use from Python:
```python
from haiku.rag.client import HaikuRAG
async with HaikuRAG("database.lancedb") as client:
async with HaikuRAG("database.lancedb", create=True) as client:
# Add a document
doc = await client.create_document("Your content here")
# Search documents
results = await client.search("query")
# Ask questions
answer = await client.ask("Who is the author of haiku.rag?")
# Ask questions (returns answer and citations)
answer, citations = await client.ask("Who is the author of haiku.rag?")
```
Or use the CLI:

View file

@ -342,15 +342,10 @@ Context expansion uses your configuration settings:
Ask questions about your documents:
```python
answer = await client.ask("Who is the author of haiku.rag?")
print(answer)
```
Ask questions with citations showing source documents:
```python
answer = await client.ask("Who is the author of haiku.rag?", cite=True)
answer, citations = await client.ask("Who is the author of haiku.rag?")
print(answer)
for cite in citations:
print(f" [{cite.chunk_id}] {cite.document_title or cite.document_uri}")
```
Customize the QA agent's behavior with a custom system prompt:
@ -360,13 +355,13 @@ custom_prompt = """You are a technical support expert for WIX.
Answer questions based on the knowledge base documents provided.
Be concise and helpful."""
answer = await client.ask(
answer, citations = await client.ask(
"How do I create a blog?",
system_prompt=custom_prompt
)
```
The QA agent will search your documents for relevant information and use the configured LLM to generate a comprehensive answer. With `cite=True`, responses include citations showing which documents were used as sources. Citations prefer the document title when present, otherwise they use the URI.
The QA agent searches your documents for relevant information and uses the configured LLM to generate an answer. The method returns a tuple of `(answer_text, list[Citation])`. Citations include page numbers, section headings, and document references.
The QA provider and model are configured in `haiku.rag.yaml` or can be passed directly to the client (see [Configuration](configuration/index.md)).

View file

@ -70,7 +70,7 @@ from haiku.rag.client import HaikuRAG
async with HaikuRAG() as client:
# PDF is processed by docling-serve
doc = await client.create_document_from_file("complex.pdf")
doc = await client.create_document_from_source("complex.pdf")
```
### Remote Chunking

View file

@ -74,9 +74,9 @@ haiku-rag add "JavaScript is a popular programming language, but has a lot of wa
haiku-rag add "PHP is a bad programming language, because of spotted security history, horrible syntax and declining popularity"
```
What will happen
What will happen:
- The piece of text is send to OpenAI `/embeddings` API service
- The piece of text is sent to OpenAI `/embeddings` API service
- OpenAI translates the free form text to RAG embedding vectors needed for the retrieval
- The vector values will be stored in a local database
@ -86,19 +86,19 @@ Now you can view your [LanceDB](https://lancedb.com/) database, and the embeddin
haiku-rag info
```
You should get the back the information:
You should see output like:
```
haiku.rag database info
path: /Users/moo/Library/Application Support/haiku.rag/haiku.rag.lancedb
haiku.rag version (db): 0.13.3
haiku.rag version (db): 0.20.0
embeddings: openai/text-embedding-3-small (dim: 1536)
documents: 3
versions (documents): 3
versions (chunks): 3
documents: 3 (storage: 48.0 KB)
chunks: 3 (storage: 52.0 KB)
vector index: not created
──────────────────────────────────────────────────────────────────────────────────
Versions
haiku.rag: 0.13.3
haiku.rag: 0.20.0
lancedb: 0.25.2
docling: 2.58.0
```
@ -127,52 +127,27 @@ According to the document, Python is considered the best programming language in
## Programmatic interaction in Python
You can interact with Haiku RAG from Python in a similar manner as you can from the command line. Here we use Haiku RAG with the interactive Python command prompt (REPL).
First we need to install `ipython`, as built-in Python REPL does not support async blocks.
You can interact with haiku.rag from Python. Since the API is async, we'll use IPython which supports async/await directly.
```bash
uv pip install ipython
```
Run IPython:
```bash
ipython
```
Then copy paste in the snippet (you can use [%cpaste](https://ipythonbook.com/magic/cpaste.html) command):
Then run:
```python
import sys
import logging
from haiku.rag.client import HaikuRAG
# Increase logging verbosity so we see what happens behind the scenes,
# and check that the logger works
logging.basicConfig(
stream=sys.stdout,
level=logging.DEBUG,
format="%(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.debug("AGI here we come")
# Uses LanceDB database from default storage location
# (database must be initialized first with 'haiku-rag init' or create=True)
# Uses database from default location (must be initialized first)
async with HaikuRAG() as client:
answer = await client.ask("What is the best programming language in the world?")
answer, citations = await client.ask("What is the best programming language in the world?")
print(answer)
```
You should see:
```
2025-10-18 17:05:49,611 - DEBUG - HTTP Response: POST https://api.openai.com/v1/chat/completions "200 OK" Headers({'date': 'Sat, 18 Oct 2025 14:05:49 GMT', 'content-type': 'application/json', 'transfer-encoding': 'chunked', 'connection': 'keep-alive', 'access-control-expose-headers': 'X-Request-ID', 'openai-organization': 'xxx', 'openai-processing-ms': '788', 'openai-project': 'xxx', 'openai-version': '2020-10-01', 'x-envoy-upstream-service-time': '1050', 'x-ratelimit-limit-requests': '10000', 'x-ratelimit-limit-tokens': '200000', 'x-ratelimit-remaining-requests': '9998', 'x-ratelimit-remaining-tokens': '199603', 'x-ratelimit-reset-requests': '14.981s', 'x-ratelimit-reset-tokens': '119ms', 'x-request-id': 'req_9651a3691a144dd388e97066ad67a49c', 'x-openai-proxy-wasm': 'v0.1', 'cf-cache-status': 'DYNAMIC', 'strict-transport-security': 'max-age=31536000; includeSubDomains; preload', 'x-content-type-options': 'nosniff', 'server': 'cloudflare', 'cf-ray': '990897b6f8d270d7-ARN', 'content-encoding': 'gzip', 'alt-svc': 'h3=":443"; ma=86400'})
2025-10-18 17:05:49,611 - DEBUG - request_id: req_9651a3691a144dd388e97066ad67a49c
According to the document, Python is considered the best programming language in the world due to its flexibility, robust ecosystem, open-source licensing, and support from thousands of contributors.
```