haiku.rag 0.12.1__tar.gz → 0.13.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of haiku.rag might be problematic. Click here for more details.

Files changed (97) hide show
  1. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/.dockerignore +12 -1
  2. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/.gitignore +5 -1
  3. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/PKG-INFO +20 -10
  4. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/README.md +17 -7
  5. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/mkdocs.yml +1 -0
  6. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/pyproject.toml +3 -3
  7. haiku_rag-0.13.1/server.json +42 -0
  8. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/benchmark.py +1 -1
  9. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/llm_judge.py +1 -1
  10. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/__init__.py +3 -3
  11. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/app.py +7 -5
  12. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/chunker.py +1 -1
  13. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/cli.py +72 -31
  14. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/client.py +36 -10
  15. haiku_rag-0.13.1/src/haiku/rag/config/__init__.py +50 -0
  16. haiku_rag-0.13.1/src/haiku/rag/config/loader.py +137 -0
  17. haiku_rag-0.13.1/src/haiku/rag/config/models.py +82 -0
  18. haiku_rag-0.13.1/src/haiku/rag/embeddings/__init__.py +49 -0
  19. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/embeddings/base.py +6 -4
  20. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/embeddings/ollama.py +3 -2
  21. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/embeddings/vllm.py +2 -2
  22. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/common.py +2 -2
  23. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/mcp.py +14 -8
  24. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/monitor.py +17 -4
  25. haiku_rag-0.13.1/src/haiku/rag/qa/__init__.py +33 -0
  26. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/agent.py +4 -2
  27. haiku_rag-0.13.1/src/haiku/rag/reranking/__init__.py +45 -0
  28. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/reranking/base.py +1 -1
  29. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/reranking/cohere.py +2 -2
  30. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/reranking/mxbai.py +1 -1
  31. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/reranking/vllm.py +1 -1
  32. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/engine.py +19 -12
  33. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/repositories/chunk.py +12 -8
  34. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/repositories/document.py +4 -4
  35. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/repositories/settings.py +19 -9
  36. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/utils.py +9 -9
  37. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/uv.lock +3 -1
  38. haiku_rag-0.12.1/server.json +0 -253
  39. haiku_rag-0.12.1/src/haiku/rag/config.py +0 -90
  40. haiku_rag-0.12.1/src/haiku/rag/embeddings/__init__.py +0 -35
  41. haiku_rag-0.12.1/src/haiku/rag/migration.py +0 -316
  42. haiku_rag-0.12.1/src/haiku/rag/qa/__init__.py +0 -20
  43. haiku_rag-0.12.1/src/haiku/rag/reranking/__init__.py +0 -37
  44. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/.pre-commit-config.yaml +0 -0
  45. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/.python-version +0 -0
  46. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/LICENSE +0 -0
  47. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/__init__.py +0 -0
  48. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/config.py +0 -0
  49. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/datasets/__init__.py +0 -0
  50. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/datasets/repliqa.py +0 -0
  51. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/datasets/wix.py +0 -0
  52. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/evaluations/prompts.py +0 -0
  53. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/__init__.py +0 -0
  54. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/client.py +0 -0
  55. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/context.py +0 -0
  56. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/models.py +0 -0
  57. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/prompts.py +0 -0
  58. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/skills.py +0 -0
  59. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/storage.py +0 -0
  60. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/a2a/worker.py +0 -0
  61. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/embeddings/openai.py +0 -0
  62. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/embeddings/voyageai.py +0 -0
  63. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/__init__.py +0 -0
  64. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/base.py +0 -0
  65. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/models.py +0 -0
  66. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/nodes/__init__.py +0 -0
  67. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/nodes/analysis.py +0 -0
  68. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/nodes/plan.py +0 -0
  69. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/nodes/search.py +0 -0
  70. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/nodes/synthesize.py +0 -0
  71. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/graph/prompts.py +0 -0
  72. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/logging.py +0 -0
  73. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/__init__.py +0 -0
  74. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/dependencies.py +0 -0
  75. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/graph.py +0 -0
  76. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/models.py +0 -0
  77. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/nodes.py +0 -0
  78. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/prompts.py +0 -0
  79. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/deep/state.py +0 -0
  80. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/qa/prompts.py +0 -0
  81. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/reader.py +0 -0
  82. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/__init__.py +0 -0
  83. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/common.py +0 -0
  84. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/dependencies.py +0 -0
  85. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/graph.py +0 -0
  86. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/models.py +0 -0
  87. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/prompts.py +0 -0
  88. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/state.py +0 -0
  89. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/research/stream.py +0 -0
  90. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/__init__.py +0 -0
  91. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/models/__init__.py +0 -0
  92. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/models/chunk.py +0 -0
  93. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/models/document.py +0 -0
  94. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/repositories/__init__.py +0 -0
  95. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/upgrades/__init__.py +0 -0
  96. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/upgrades/v0_10_1.py +0 -0
  97. {haiku_rag-0.12.1 → haiku_rag-0.13.1}/src/haiku/rag/store/upgrades/v0_9_3.py +0 -0
@@ -25,9 +25,19 @@ wheels/
25
25
  venv/
26
26
  env/
27
27
 
28
+ # Node.js
29
+ node_modules/
30
+ .next/
31
+ npm-debug.log*
32
+ yarn-debug.log*
33
+ yarn-error.log*
34
+
28
35
  # Data
29
36
  *.lancedb/
30
37
  data/
38
+
39
+ # Docs
40
+ mkdocs.yml
31
41
  docs/
32
42
 
33
43
  # IDE
@@ -50,6 +60,7 @@ tests/
50
60
  .pytest_cache/
51
61
  .coverage
52
62
  htmlcov/
53
-
63
+ src/evaluations/
64
+ server.json
54
65
  # Examples
55
66
  examples/
@@ -16,8 +16,9 @@ tests/data/
16
16
  .pytest_cache/
17
17
  .ruff_cache/
18
18
 
19
- # environment variables
19
+ # environment variables and config files
20
20
  .env
21
+ haiku.rag.yaml
21
22
  TODO.md
22
23
  PLAN.md
23
24
  DEVNOTES.md
@@ -25,3 +26,6 @@ DEVNOTES.md
25
26
  # mcp registry
26
27
  .mcpregistry_github_token
27
28
  .mcpregistry_registry_token
29
+
30
+ # MkDocs site directory when doing local docs builds
31
+ site/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haiku.rag
3
- Version: 0.12.1
3
+ Version: 0.13.1
4
4
  Summary: Agentic Retrieval Augmented Generation (RAG) with LanceDB
5
5
  Author-email: Yiorgis Gozadinos <ggozadinos@gmail.com>
6
6
  License: MIT
@@ -13,9 +13,8 @@ Classifier: Operating System :: MacOS
13
13
  Classifier: Operating System :: Microsoft :: Windows :: Windows 10
14
14
  Classifier: Operating System :: Microsoft :: Windows :: Windows 11
15
15
  Classifier: Operating System :: POSIX :: Linux
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
19
18
  Classifier: Typing :: Typed
20
19
  Requires-Python: >=3.12
21
20
  Requires-Dist: docling>=2.56.1
@@ -26,6 +25,7 @@ Requires-Dist: pydantic-ai>=1.0.18
26
25
  Requires-Dist: pydantic-graph>=1.0.18
27
26
  Requires-Dist: pydantic>=2.12.2
28
27
  Requires-Dist: python-dotenv>=1.1.1
28
+ Requires-Dist: pyyaml>=6.0.1
29
29
  Requires-Dist: rich>=14.2.0
30
30
  Requires-Dist: tiktoken>=0.12.0
31
31
  Requires-Dist: typer>=0.19.2
@@ -40,11 +40,13 @@ Description-Content-Type: text/markdown
40
40
 
41
41
  # Haiku RAG
42
42
 
43
+ mcp-name: io.github.ggozad/haiku-rag
44
+
43
45
  Retrieval-Augmented Generation (RAG) library built on LanceDB.
44
46
 
45
47
  `haiku.rag` is a Retrieval-Augmented Generation (RAG) library built to work with LanceDB as a local vector database. It uses LanceDB for storing embeddings and performs semantic (vector) search as well as full-text search combined through native hybrid search with Reciprocal Rank Fusion. Both open-source (Ollama) as well as commercial (OpenAI, VoyageAI) embedding providers are supported.
46
48
 
47
- > **Note**: Starting with version 0.7.0, haiku.rag uses LanceDB instead of SQLite. If you have an existing SQLite database, use `haiku-rag migrate old_database.sqlite` to migrate your data safely.
49
+ > **Note**: Configuration now uses YAML files instead of environment variables. If you're upgrading from an older version, run `haiku-rag init-config --from-env` to migrate your `.env` file to `haiku.rag.yaml`. See [Configuration](https://ggozad.github.io/haiku.rag/configuration/) for details.
48
50
 
49
51
  ## Features
50
52
 
@@ -65,6 +67,7 @@ Retrieval-Augmented Generation (RAG) library built on LanceDB.
65
67
 
66
68
  ```bash
67
69
  # Install
70
+ # Python 3.12 or newer required
68
71
  uv pip install haiku.rag
69
72
 
70
73
  # Add documents
@@ -98,14 +101,12 @@ haiku-rag research \
98
101
  # Rebuild database (re-chunk and re-embed all documents)
99
102
  haiku-rag rebuild
100
103
 
101
- # Migrate from SQLite to LanceDB
102
- haiku-rag migrate old_database.sqlite
103
-
104
104
  # Start server with file monitoring
105
- export MONITOR_DIRECTORIES="/path/to/docs"
106
- haiku-rag serve
105
+ haiku-rag serve --monitor
107
106
  ```
108
107
 
108
+ To customize settings, create a `haiku.rag.yaml` config file (see [Configuration](https://ggozad.github.io/haiku.rag/configuration/)).
109
+
109
110
  ## Python Usage
110
111
 
111
112
  ```python
@@ -197,17 +198,26 @@ haiku-rag a2aclient
197
198
  ```
198
199
 
199
200
  The A2A agent provides:
201
+
200
202
  - Multi-turn dialogue with context
201
203
  - Intelligent multi-search for complex questions
202
204
  - Source citations with titles and URIs
203
205
  - Full document retrieval on request
204
206
 
207
+ ## Examples
208
+
209
+ See the [examples directory](examples/) for working examples:
210
+
211
+ - **[Interactive Research Assistant](examples/ag-ui-research/)** - Full-stack research assistant with Pydantic AI and AG-UI featuring human-in-the-loop approval and real-time state synchronization
212
+ - **[Docker Setup](examples/docker/)** - Complete Docker deployment with file monitoring, MCP server, and A2A agent
213
+ - **[A2A Security](examples/a2a-security/)** - Authentication examples (API key, OAuth2, GitHub)
214
+
205
215
  ## Documentation
206
216
 
207
217
  Full documentation at: https://ggozad.github.io/haiku.rag/
208
218
 
209
219
  - [Installation](https://ggozad.github.io/haiku.rag/installation/) - Provider setup
210
- - [Configuration](https://ggozad.github.io/haiku.rag/configuration/) - Environment variables
220
+ - [Configuration](https://ggozad.github.io/haiku.rag/configuration/) - YAML configuration
211
221
  - [CLI](https://ggozad.github.io/haiku.rag/cli/) - Command reference
212
222
  - [Python API](https://ggozad.github.io/haiku.rag/python/) - Complete API docs
213
223
  - [Agents](https://ggozad.github.io/haiku.rag/agents/) - QA agent and multi-agent research
@@ -1,10 +1,12 @@
1
1
  # Haiku RAG
2
2
 
3
+ mcp-name: io.github.ggozad/haiku-rag
4
+
3
5
  Retrieval-Augmented Generation (RAG) library built on LanceDB.
4
6
 
5
7
  `haiku.rag` is a Retrieval-Augmented Generation (RAG) library built to work with LanceDB as a local vector database. It uses LanceDB for storing embeddings and performs semantic (vector) search as well as full-text search combined through native hybrid search with Reciprocal Rank Fusion. Both open-source (Ollama) as well as commercial (OpenAI, VoyageAI) embedding providers are supported.
6
8
 
7
- > **Note**: Starting with version 0.7.0, haiku.rag uses LanceDB instead of SQLite. If you have an existing SQLite database, use `haiku-rag migrate old_database.sqlite` to migrate your data safely.
9
+ > **Note**: Configuration now uses YAML files instead of environment variables. If you're upgrading from an older version, run `haiku-rag init-config --from-env` to migrate your `.env` file to `haiku.rag.yaml`. See [Configuration](https://ggozad.github.io/haiku.rag/configuration/) for details.
8
10
 
9
11
  ## Features
10
12
 
@@ -25,6 +27,7 @@ Retrieval-Augmented Generation (RAG) library built on LanceDB.
25
27
 
26
28
  ```bash
27
29
  # Install
30
+ # Python 3.12 or newer required
28
31
  uv pip install haiku.rag
29
32
 
30
33
  # Add documents
@@ -58,14 +61,12 @@ haiku-rag research \
58
61
  # Rebuild database (re-chunk and re-embed all documents)
59
62
  haiku-rag rebuild
60
63
 
61
- # Migrate from SQLite to LanceDB
62
- haiku-rag migrate old_database.sqlite
63
-
64
64
  # Start server with file monitoring
65
- export MONITOR_DIRECTORIES="/path/to/docs"
66
- haiku-rag serve
65
+ haiku-rag serve --monitor
67
66
  ```
68
67
 
68
+ To customize settings, create a `haiku.rag.yaml` config file (see [Configuration](https://ggozad.github.io/haiku.rag/configuration/)).
69
+
69
70
  ## Python Usage
70
71
 
71
72
  ```python
@@ -157,17 +158,26 @@ haiku-rag a2aclient
157
158
  ```
158
159
 
159
160
  The A2A agent provides:
161
+
160
162
  - Multi-turn dialogue with context
161
163
  - Intelligent multi-search for complex questions
162
164
  - Source citations with titles and URIs
163
165
  - Full document retrieval on request
164
166
 
167
+ ## Examples
168
+
169
+ See the [examples directory](examples/) for working examples:
170
+
171
+ - **[Interactive Research Assistant](examples/ag-ui-research/)** - Full-stack research assistant with Pydantic AI and AG-UI featuring human-in-the-loop approval and real-time state synchronization
172
+ - **[Docker Setup](examples/docker/)** - Complete Docker deployment with file monitoring, MCP server, and A2A agent
173
+ - **[A2A Security](examples/a2a-security/)** - Authentication examples (API key, OAuth2, GitHub)
174
+
165
175
  ## Documentation
166
176
 
167
177
  Full documentation at: https://ggozad.github.io/haiku.rag/
168
178
 
169
179
  - [Installation](https://ggozad.github.io/haiku.rag/installation/) - Provider setup
170
- - [Configuration](https://ggozad.github.io/haiku.rag/configuration/) - Environment variables
180
+ - [Configuration](https://ggozad.github.io/haiku.rag/configuration/) - YAML configuration
171
181
  - [CLI](https://ggozad.github.io/haiku.rag/cli/) - Command reference
172
182
  - [Python API](https://ggozad.github.io/haiku.rag/python/) - Complete API docs
173
183
  - [Agents](https://ggozad.github.io/haiku.rag/agents/) - QA agent and multi-agent research
@@ -57,6 +57,7 @@ plugins:
57
57
  nav:
58
58
  - haiku.rag:
59
59
  - index.md
60
+ - Getting started: tutorial.md
60
61
  - Installation: installation.md
61
62
  - Configuration: configuration.md
62
63
  - CLI: cli.md
@@ -2,7 +2,7 @@
2
2
 
3
3
  name = "haiku.rag"
4
4
  description = "Agentic Retrieval Augmented Generation (RAG) with LanceDB"
5
- version = "0.12.1"
5
+ version = "0.13.1"
6
6
  authors = [{ name = "Yiorgis Gozadinos", email = "ggozadinos@gmail.com" }]
7
7
  license = { text = "MIT" }
8
8
  readme = { file = "README.md", content-type = "text/markdown" }
@@ -16,9 +16,8 @@ classifiers = [
16
16
  "Operating System :: Microsoft :: Windows :: Windows 11",
17
17
  "Operating System :: MacOS",
18
18
  "Operating System :: POSIX :: Linux",
19
- "Programming Language :: Python :: 3.10",
20
- "Programming Language :: Python :: 3.11",
21
19
  "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
22
21
  "Typing :: Typed",
23
22
  ]
24
23
 
@@ -31,6 +30,7 @@ dependencies = [
31
30
  "pydantic-ai>=1.0.18",
32
31
  "pydantic-graph>=1.0.18",
33
32
  "python-dotenv>=1.1.1",
33
+ "pyyaml>=6.0.1",
34
34
  "rich>=14.2.0",
35
35
  "tiktoken>=0.12.0",
36
36
  "typer>=0.19.2",
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3
+ "name": "io.github.ggozad/haiku-rag",
4
+ "version": "{{VERSION}}",
5
+ "description": "Agentic Retrieval Augmented Generation (RAG) with LanceDB",
6
+ "repository": {
7
+ "url": "https://github.com/ggozad/haiku.rag",
8
+ "source": "github"
9
+ },
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "rag",
13
+ "lancedb",
14
+ "vector-database",
15
+ "embeddings",
16
+ "search",
17
+ "qa",
18
+ "research"
19
+ ],
20
+ "packages": [
21
+ {
22
+ "registryType": "pypi",
23
+ "registryBaseUrl": "https://pypi.org",
24
+ "identifier": "haiku-rag",
25
+ "version": "{{VERSION}}",
26
+ "runtimeHint": "uvx",
27
+ "runtimeArguments": [
28
+ {
29
+ "type": "positional",
30
+ "value": "serve"
31
+ },
32
+ {
33
+ "type": "named",
34
+ "name": "--mcp"
35
+ }
36
+ ],
37
+ "transport": {
38
+ "type": "stdio"
39
+ }
40
+ }
41
+ ]
42
+ }
@@ -174,7 +174,7 @@ async def run_qa_benchmark(
174
174
 
175
175
  judge_model = OpenAIChatModel(
176
176
  model_name=QA_JUDGE_MODEL,
177
- provider=OllamaProvider(base_url=f"{Config.OLLAMA_BASE_URL}/v1"),
177
+ provider=OllamaProvider(base_url=f"{Config.providers.ollama.base_url}/v1"),
178
178
  )
179
179
 
180
180
  evaluation_dataset = EvalDataset[str, str, dict[str, str]](
@@ -41,7 +41,7 @@ class LLMJudge:
41
41
  # Create Ollama model
42
42
  ollama_model = OpenAIChatModel(
43
43
  model_name=model,
44
- provider=OllamaProvider(base_url=f"{Config.OLLAMA_BASE_URL}/v1"),
44
+ provider=OllamaProvider(base_url=f"{Config.providers.ollama.base_url}/v1"),
45
45
  )
46
46
 
47
47
  # Create Pydantic AI agent
@@ -57,12 +57,12 @@ def create_a2a_app(
57
57
  """
58
58
  base_storage = InMemoryStorage()
59
59
  storage = LRUMemoryStorage(
60
- storage=base_storage, max_contexts=Config.A2A_MAX_CONTEXTS
60
+ storage=base_storage, max_contexts=Config.a2a.max_contexts
61
61
  )
62
62
  broker = InMemoryBroker()
63
63
 
64
64
  # Create the agent with native search tool
65
- model = get_model(Config.QA_PROVIDER, Config.QA_MODEL)
65
+ model = get_model(Config.qa.provider, Config.qa.model)
66
66
  agent = Agent(
67
67
  model=model,
68
68
  deps_type=AgentDependencies,
@@ -120,7 +120,7 @@ def create_a2a_app(
120
120
  # Create FastA2A app with custom worker lifecycle
121
121
  @asynccontextmanager
122
122
  async def lifespan(app):
123
- logger.info(f"Started A2A server (max contexts: {Config.A2A_MAX_CONTEXTS})")
123
+ logger.info(f"Started A2A server (max contexts: {Config.a2a.max_contexts})")
124
124
  async with app.task_manager:
125
125
  async with worker.run():
126
126
  yield
@@ -231,8 +231,8 @@ class HaikuRAGApp:
231
231
  )
232
232
 
233
233
  start_node = DeepQAPlanNode(
234
- provider=Config.QA_PROVIDER,
235
- model=Config.QA_MODEL,
234
+ provider=Config.qa.provider,
235
+ model=Config.qa.model,
236
236
  )
237
237
 
238
238
  result = await graph.run(
@@ -278,8 +278,8 @@ class HaikuRAGApp:
278
278
  )
279
279
 
280
280
  start = PlanNode(
281
- provider=Config.RESEARCH_PROVIDER or Config.QA_PROVIDER,
282
- model=Config.RESEARCH_MODEL or Config.QA_MODEL,
281
+ provider=Config.research.provider or Config.qa.provider,
282
+ model=Config.research.model or Config.qa.model,
283
283
  )
284
284
  report = None
285
285
  async for event in stream_research_graph(graph, start, state, deps):
@@ -474,7 +474,9 @@ class HaikuRAGApp:
474
474
 
475
475
  # Start file monitor if enabled
476
476
  if enable_monitor:
477
- monitor = FileWatcher(paths=Config.MONITOR_DIRECTORIES, client=client)
477
+ monitor = FileWatcher(
478
+ paths=Config.storage.monitor_directories, client=client
479
+ )
478
480
  monitor_task = asyncio.create_task(monitor.observe())
479
481
  tasks.append(monitor_task)
480
482
 
@@ -22,7 +22,7 @@ class Chunker:
22
22
 
23
23
  def __init__(
24
24
  self,
25
- chunk_size: int = Config.CHUNK_SIZE,
25
+ chunk_size: int = Config.processing.chunk_size,
26
26
  ):
27
27
  self.chunk_size = chunk_size
28
28
  tokenizer = OpenAITokenizer(
@@ -42,10 +42,21 @@ def main(
42
42
  callback=version_callback,
43
43
  help="Show version and exit",
44
44
  ),
45
+ config: Path | None = typer.Option(
46
+ None,
47
+ "--config",
48
+ help="Path to YAML configuration file",
49
+ ),
45
50
  ):
46
51
  """haiku.rag CLI - Vector database RAG system"""
52
+ # Store config path in environment for config loader to use
53
+ if config:
54
+ import os
55
+
56
+ os.environ["HAIKU_RAG_CONFIG_PATH"] = str(config.absolute())
57
+
47
58
  # Configure logging minimally for CLI context
48
- if Config.ENV == "development":
59
+ if Config.environment == "development":
49
60
  # Lazy import logfire only in development
50
61
  try:
51
62
  import logfire # type: ignore
@@ -69,7 +80,7 @@ def main(
69
80
  @cli.command("list", help="List all stored documents")
70
81
  def list_documents(
71
82
  db: Path = typer.Option(
72
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
83
+ Config.storage.data_dir / "haiku.rag.lancedb",
73
84
  "--db",
74
85
  help="Path to the LanceDB database file",
75
86
  ),
@@ -116,7 +127,7 @@ def add_document_text(
116
127
  metavar="KEY=VALUE",
117
128
  ),
118
129
  db: Path = typer.Option(
119
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
130
+ Config.storage.data_dir / "haiku.rag.lancedb",
120
131
  "--db",
121
132
  help="Path to the LanceDB database file",
122
133
  ),
@@ -145,7 +156,7 @@ def add_document_src(
145
156
  metavar="KEY=VALUE",
146
157
  ),
147
158
  db: Path = typer.Option(
148
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
159
+ Config.storage.data_dir / "haiku.rag.lancedb",
149
160
  "--db",
150
161
  help="Path to the LanceDB database file",
151
162
  ),
@@ -167,7 +178,7 @@ def get_document(
167
178
  help="The ID of the document to get",
168
179
  ),
169
180
  db: Path = typer.Option(
170
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
181
+ Config.storage.data_dir / "haiku.rag.lancedb",
171
182
  "--db",
172
183
  help="Path to the LanceDB database file",
173
184
  ),
@@ -184,7 +195,7 @@ def delete_document(
184
195
  help="The ID of the document to delete",
185
196
  ),
186
197
  db: Path = typer.Option(
187
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
198
+ Config.storage.data_dir / "haiku.rag.lancedb",
188
199
  "--db",
189
200
  help="Path to the LanceDB database file",
190
201
  ),
@@ -211,7 +222,7 @@ def search(
211
222
  help="Maximum number of results to return",
212
223
  ),
213
224
  db: Path = typer.Option(
214
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
225
+ Config.storage.data_dir / "haiku.rag.lancedb",
215
226
  "--db",
216
227
  help="Path to the LanceDB database file",
217
228
  ),
@@ -228,7 +239,7 @@ def ask(
228
239
  help="The question to ask",
229
240
  ),
230
241
  db: Path = typer.Option(
231
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
242
+ Config.storage.data_dir / "haiku.rag.lancedb",
232
243
  "--db",
233
244
  help="Path to the LanceDB database file",
234
245
  ),
@@ -276,7 +287,7 @@ def research(
276
287
  help="Max concurrent searches per iteration (planned)",
277
288
  ),
278
289
  db: Path = typer.Option(
279
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
290
+ Config.storage.data_dir / "haiku.rag.lancedb",
280
291
  "--db",
281
292
  help="Path to the LanceDB database file",
282
293
  ),
@@ -308,13 +319,61 @@ def settings():
308
319
  app.show_settings()
309
320
 
310
321
 
322
+ @cli.command("init-config", help="Generate a YAML configuration file")
323
+ def init_config(
324
+ output: Path = typer.Argument(
325
+ Path("haiku.rag.yaml"),
326
+ help="Output path for the config file",
327
+ ),
328
+ from_env: bool = typer.Option(
329
+ False,
330
+ "--from-env",
331
+ help="Migrate settings from .env file",
332
+ ),
333
+ ):
334
+ """Generate a YAML configuration file with defaults or from .env."""
335
+ import yaml
336
+
337
+ from haiku.rag.config.loader import generate_default_config, load_config_from_env
338
+
339
+ if output.exists():
340
+ typer.echo(
341
+ f"Error: {output} already exists. Remove it first or choose a different path."
342
+ )
343
+ raise typer.Exit(1)
344
+
345
+ if from_env:
346
+ # Load from environment variables (including .env if present)
347
+ from dotenv import load_dotenv
348
+
349
+ load_dotenv()
350
+ config_data = load_config_from_env()
351
+ if not config_data:
352
+ typer.echo("Warning: No environment variables found to migrate.")
353
+ typer.echo("Generating default configuration instead.")
354
+ config_data = generate_default_config()
355
+ else:
356
+ config_data = generate_default_config()
357
+
358
+ # Write YAML with comments
359
+ with open(output, "w") as f:
360
+ f.write("# haiku.rag configuration file\n")
361
+ f.write(
362
+ "# See https://ggozad.github.io/haiku.rag/configuration/ for details\n\n"
363
+ )
364
+ yaml.dump(config_data, f, default_flow_style=False, sort_keys=False)
365
+
366
+ typer.echo(f"Configuration file created: {output}")
367
+ typer.echo("Edit the file to customize your settings.")
368
+
369
+
311
370
  @cli.command(
312
371
  "rebuild",
313
372
  help="Rebuild the database by deleting all chunks and re-indexing all documents",
314
373
  )
315
374
  def rebuild(
316
375
  db: Path = typer.Option(
317
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
376
+ Config.storage.data_dir / "haiku.rag.lancedb",
318
377
  "--db",
319
378
  help="Path to the LanceDB database file",
320
379
  ),
@@ -328,7 +387,7 @@ def rebuild(
328
387
  @cli.command("vacuum", help="Optimize and clean up all tables to reduce disk usage")
329
388
  def vacuum(
330
389
  db: Path = typer.Option(
331
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
390
+ Config.storage.data_dir / "haiku.rag.lancedb",
332
391
  "--db",
333
392
  help="Path to the LanceDB database file",
334
393
  ),
@@ -342,7 +401,7 @@ def vacuum(
342
401
  @cli.command("info", help="Show read-only database info (no upgrades or writes)")
343
402
  def info(
344
403
  db: Path = typer.Option(
345
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
404
+ Config.storage.data_dir / "haiku.rag.lancedb",
346
405
  "--db",
347
406
  help="Path to the LanceDB database file",
348
407
  ),
@@ -371,7 +430,7 @@ def download_models_cmd():
371
430
  )
372
431
  def serve(
373
432
  db: Path = typer.Option(
374
- Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb",
433
+ Config.storage.data_dir / "haiku.rag.lancedb",
375
434
  "--db",
376
435
  help="Path to the LanceDB database file",
377
436
  ),
@@ -442,24 +501,6 @@ def serve(
442
501
  )
443
502
 
444
503
 
445
- @cli.command("migrate", help="Migrate an SQLite database to LanceDB")
446
- def migrate(
447
- sqlite_path: Path = typer.Argument(
448
- help="Path to the SQLite database file to migrate",
449
- ),
450
- ):
451
- # Generate LanceDB path in same parent directory
452
- lancedb_path = sqlite_path.parent / (sqlite_path.stem + ".lancedb")
453
-
454
- # Lazy import to avoid heavy deps on simple invocations
455
- from haiku.rag.migration import migrate_sqlite_to_lancedb
456
-
457
- success = asyncio.run(migrate_sqlite_to_lancedb(sqlite_path, lancedb_path))
458
-
459
- if not success:
460
- raise typer.Exit(1)
461
-
462
-
463
504
  @cli.command(
464
505
  "a2aclient", help="Run interactive client to chat with haiku.rag's A2A server"
465
506
  )