Documentation updates
This commit is contained in:
parent
be0e3c3472
commit
8206498af8
6 changed files with 94 additions and 161 deletions
129
README.md
129
README.md
|
|
@ -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 (multi‑agent)**: 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
|
||||
|
||||
# Multi‑agent 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)
|
||||
|
||||
# Multi‑agent 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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (multi‑agent)**: 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:
|
||||
|
|
|
|||
|
|
@ -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)).
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue