ragbits-cli 0.0.1__tar.gz → 0.0.8.dev23005__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.
- {ragbits_cli-0.0.1 → ragbits_cli-0.0.8.dev23005}/.gitignore +22 -3
- ragbits_cli-0.0.8.dev23005/CHANGELOG.md +219 -0
- ragbits_cli-0.0.8.dev23005/PKG-INFO +71 -0
- ragbits_cli-0.0.8.dev23005/README.md +43 -0
- {ragbits_cli-0.0.1 → ragbits_cli-0.0.8.dev23005}/pyproject.toml +11 -6
- ragbits_cli-0.0.8.dev23005/src/ragbits/cli/__init__.py +89 -0
- ragbits_cli-0.0.8.dev23005/src/ragbits/cli/_utils.py +67 -0
- ragbits_cli-0.0.8.dev23005/src/ragbits/cli/py.typed +0 -0
- ragbits_cli-0.0.8.dev23005/src/ragbits/cli/state.py +151 -0
- ragbits_cli-0.0.8.dev23005/tests/unit/test_state.py +121 -0
- ragbits_cli-0.0.8.dev23005/tests/unit/test_utils.py +38 -0
- ragbits_cli-0.0.1/PKG-INFO +0 -23
- ragbits_cli-0.0.1/README.md +0 -1
- ragbits_cli-0.0.1/src/ragbits/cli/__init__.py +0 -31
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
.pytest_cache/
|
|
6
6
|
.mypy_cache/
|
|
7
7
|
venv/
|
|
8
|
+
.venv/
|
|
8
9
|
__pycache__/
|
|
9
10
|
**.egg-info/
|
|
11
|
+
.deepeval/
|
|
12
|
+
|
|
13
|
+
# Local cursor rules
|
|
14
|
+
.cursor/rules/local/
|
|
10
15
|
|
|
11
16
|
# Byte-compiled / optimized / DLL files
|
|
12
17
|
__pycache__/
|
|
@@ -87,11 +92,25 @@ cmake-build-*/
|
|
|
87
92
|
**/.terraform.lock.hcl
|
|
88
93
|
**/.terraform
|
|
89
94
|
|
|
90
|
-
# benchmarks
|
|
91
|
-
benchmarks/sql/data/
|
|
92
|
-
|
|
93
95
|
# mkdocs generated files
|
|
94
96
|
site/
|
|
95
97
|
|
|
96
98
|
# build artifacts
|
|
97
99
|
dist/
|
|
100
|
+
|
|
101
|
+
# examples
|
|
102
|
+
chroma/
|
|
103
|
+
qdrant/
|
|
104
|
+
|
|
105
|
+
.aider*
|
|
106
|
+
|
|
107
|
+
.DS_Store
|
|
108
|
+
node_modules/
|
|
109
|
+
|
|
110
|
+
lazygit
|
|
111
|
+
|
|
112
|
+
lazygit.tar.gz
|
|
113
|
+
|
|
114
|
+
# chat conversation logs
|
|
115
|
+
duet_conversation.log
|
|
116
|
+
worktrees/
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 1.3.0 (2025-09-11)
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- ragbits-core updated to version v1.3.0
|
|
10
|
+
|
|
11
|
+
- feat: add current working directory to Python path for better CLI module discovery
|
|
12
|
+
|
|
13
|
+
## 1.2.2 (2025-08-08)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- ragbits-core updated to version v1.2.2
|
|
18
|
+
|
|
19
|
+
## 1.2.1 (2025-08-04)
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- ragbits-core updated to version v1.2.1
|
|
24
|
+
|
|
25
|
+
## 1.2.0 (2025-08-01)
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- ragbits-core updated to version v1.2.0
|
|
30
|
+
|
|
31
|
+
## 1.1.0 (2025-07-09)
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- ragbits-core updated to version v1.1.0
|
|
36
|
+
|
|
37
|
+
## 1.0.0 (2025-06-04)
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- ragbits-core updated to version v1.0.0
|
|
42
|
+
|
|
43
|
+
## 0.20.1 (2025-06-04)
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- ragbits-core updated to version v0.20.1
|
|
48
|
+
|
|
49
|
+
## 0.20.0 (2025-06-03)
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- ragbits-core updated to version v0.20.0
|
|
54
|
+
|
|
55
|
+
## 0.19.1 (2025-05-27)
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- ragbits-core updated to version v0.19.1
|
|
60
|
+
|
|
61
|
+
## 0.19.0 (2025-05-27)
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- ragbits-core updated to version v0.19.0
|
|
66
|
+
|
|
67
|
+
## 0.18.0 (2025-05-22)
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- ragbits-core updated to version v0.18.0
|
|
72
|
+
|
|
73
|
+
- Update audit imports (#427)
|
|
74
|
+
|
|
75
|
+
## 0.17.1 (2025-05-09)
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
|
|
79
|
+
- ragbits-core updated to version v0.17.1
|
|
80
|
+
|
|
81
|
+
## 0.17.0 (2025-05-06)
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- ragbits-core updated to version v0.17.0
|
|
86
|
+
|
|
87
|
+
## 0.16.0 (2025-04-29)
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
|
|
91
|
+
- ragbits-core updated to version v0.16.0
|
|
92
|
+
|
|
93
|
+
## 0.15.0 (2025-04-28)
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
|
|
97
|
+
- ragbits-core updated to version v0.15.0
|
|
98
|
+
|
|
99
|
+
## 0.14.0 (2025-04-22)
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- ragbits-core updated to version v0.14.0
|
|
104
|
+
|
|
105
|
+
- do not download litellm costmap in CLI commands (#521)
|
|
106
|
+
|
|
107
|
+
## 0.13.0 (2025-04-02)
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- ragbits-core updated to version v0.13.0
|
|
112
|
+
|
|
113
|
+
## 0.12.0 (2025-03-25)
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- ragbits-core updated to version v0.12.0
|
|
118
|
+
|
|
119
|
+
## 0.11.0 (2025-03-25)
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
|
|
123
|
+
- ragbits-core updated to version v0.11.0
|
|
124
|
+
|
|
125
|
+
## 0.10.2 (2025-03-21)
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
|
|
129
|
+
- ragbits-core updated to version v0.10.2
|
|
130
|
+
|
|
131
|
+
## 0.10.1 (2025-03-19)
|
|
132
|
+
|
|
133
|
+
### Changed
|
|
134
|
+
|
|
135
|
+
- ragbits-core updated to version v0.10.1
|
|
136
|
+
|
|
137
|
+
## 0.10.0 (2025-03-17)
|
|
138
|
+
|
|
139
|
+
### Changed
|
|
140
|
+
|
|
141
|
+
- ragbits-core updated to version v0.10.0
|
|
142
|
+
|
|
143
|
+
- ragbits-conversations added traceable
|
|
144
|
+
- ragbits-core added traceable
|
|
145
|
+
- ragbits-document-search added traceable
|
|
146
|
+
- ragbits-evaluate added traceable
|
|
147
|
+
|
|
148
|
+
## 0.9.0 (2025-02-25)
|
|
149
|
+
|
|
150
|
+
### Changed
|
|
151
|
+
|
|
152
|
+
- ragbits-core updated to version v0.9.0
|
|
153
|
+
|
|
154
|
+
## 0.8.0 (2025-01-29)
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
|
|
158
|
+
- ragbits-core updated to version v0.8.0
|
|
159
|
+
|
|
160
|
+
## 0.7.0 (2025-01-21)
|
|
161
|
+
|
|
162
|
+
### Changed
|
|
163
|
+
|
|
164
|
+
- ragbits-core updated to version v0.7.0
|
|
165
|
+
|
|
166
|
+
## 0.6.0 (2024-12-27)
|
|
167
|
+
|
|
168
|
+
### Added
|
|
169
|
+
|
|
170
|
+
- Better error handling when dynamic importing fails in the CLI (#259).
|
|
171
|
+
- Add option to choose what columns to display in the output (#257).
|
|
172
|
+
|
|
173
|
+
### Changed
|
|
174
|
+
|
|
175
|
+
- ragbits-core updated to version v0.6.0
|
|
176
|
+
|
|
177
|
+
## 0.5.1 (2024-12-09)
|
|
178
|
+
|
|
179
|
+
### Changed
|
|
180
|
+
|
|
181
|
+
- ragbits-core updated to version v0.5.1
|
|
182
|
+
|
|
183
|
+
## 0.5.0 (2024-12-05)
|
|
184
|
+
|
|
185
|
+
### Added
|
|
186
|
+
|
|
187
|
+
- Add global flag to specify output type: text or json (#232).
|
|
188
|
+
|
|
189
|
+
### Changed
|
|
190
|
+
|
|
191
|
+
- ragbits-core updated to version v0.5.0
|
|
192
|
+
|
|
193
|
+
## 0.4.0 (2024-11-27)
|
|
194
|
+
|
|
195
|
+
### Changed
|
|
196
|
+
|
|
197
|
+
- ragbits-core updated to version v0.4.0
|
|
198
|
+
|
|
199
|
+
## 0.3.0 (2024-11-06)
|
|
200
|
+
|
|
201
|
+
### Changed
|
|
202
|
+
|
|
203
|
+
- ragbits-core updated to version v0.3.0
|
|
204
|
+
|
|
205
|
+
## 0.2.0 (2024-10-23)
|
|
206
|
+
|
|
207
|
+
### Changed
|
|
208
|
+
|
|
209
|
+
- Improved performance by lazy-loading the modules (#111 #113 #120)
|
|
210
|
+
- ragbits-core updated to version v0.2.0
|
|
211
|
+
|
|
212
|
+
## 0.1.0 (2024-10-08)
|
|
213
|
+
|
|
214
|
+
### Added
|
|
215
|
+
|
|
216
|
+
- Initial release of the package.
|
|
217
|
+
- Add prompts lab command.
|
|
218
|
+
- Add prompts generate-promptfoo-configs command.
|
|
219
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ragbits-cli
|
|
3
|
+
Version: 0.0.8.dev23005
|
|
4
|
+
Summary: A CLI application for ragbits - building blocks for rapid development of GenAI applications
|
|
5
|
+
Project-URL: Homepage, https://github.com/deepsense-ai/ragbits
|
|
6
|
+
Project-URL: Bug Reports, https://github.com/deepsense-ai/ragbits/issues
|
|
7
|
+
Project-URL: Documentation, https://ragbits.deepsense.ai/
|
|
8
|
+
Project-URL: Source, https://github.com/deepsense-ai/ragbits
|
|
9
|
+
Author-email: "deepsense.ai" <ragbits@deepsense.ai>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: GenAI,Generative AI,LLMs,Large Language Models,Prompt Management,RAG,Retrieval Augmented Generation
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: ragbits-core==0.0.8.dev23005
|
|
26
|
+
Requires-Dist: typer<1.0.0,>=0.12.5
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Ragbits CLI
|
|
30
|
+
|
|
31
|
+
Ragbits CLI provides the `ragbits` command-line interface (CLI) tool that allows you to interact with Ragbits from the terminal. Other packages can extend the CLI by adding their own commands, so the exact set of available commands may vary depending on the installed packages.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
To use the complete Ragbits stack, install the `ragbits` package:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
pip install ragbits
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Example Usage
|
|
42
|
+
The following example assumes that `ragbits-core` is installed and that the current ddirectory contains a `song_prompt.py` file with a prompt class named `SongPrompt`, as defined in the [Quickstart Guide](https://ragbits.deepsense.ai/quickstart/quickstart1_prompts/#making-the-prompt-dynamic).
|
|
43
|
+
|
|
44
|
+
The example demonstrates how to execute the prompt using the `ragbits` CLI tool.
|
|
45
|
+
The left side of the table shows the system and user prompts (rendered with placeholders replaced by the provided values), and the right side shows the generated response from the Large Language Model.
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
$ ragbits prompts exec song_prompt:SongPrompt --payload '{"subject": "unicorns", "age_group": 12, "genre": "pop"}'
|
|
49
|
+
|
|
50
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
51
|
+
┃ Question ┃ Answer ┃
|
|
52
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
53
|
+
│ [{'role': 'system', 'content': 'You │ (Verse 1) │
|
|
54
|
+
│ are a professional songwriter. │ In a land of rainbows and glitter, │
|
|
55
|
+
│ You only use language that is │ Where flowers bloom and skies are │
|
|
56
|
+
│ appropriate for children.'}, │ brighter, │
|
|
57
|
+
│ {'role': 'user', 'content': 'Write a │ There's a magical creature so rare, │
|
|
58
|
+
│ song about a unicorns for 12 years │ With a horn that sparkles in the air. │
|
|
59
|
+
│ old pop fans.'}] │ │
|
|
60
|
+
│ │ (Chorus) │
|
|
61
|
+
│ │ Unicorns, unicorns, oh so divine, │
|
|
62
|
+
│ │ With their mane that shines and eyes │
|
|
63
|
+
│ │ that shine, │
|
|
64
|
+
│ │ Gallop through the meadows, so free, │
|
|
65
|
+
│ │ In a world of wonder, just you and │
|
|
66
|
+
│ │ me. │
|
|
67
|
+
└───────────────────────────────────────┴───────────────────────────────────────┘
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
* [Documentation of the `ragbits` CLI](https://ragbits.deepsense.ai/cli/main/)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Ragbits CLI
|
|
2
|
+
|
|
3
|
+
Ragbits CLI provides the `ragbits` command-line interface (CLI) tool that allows you to interact with Ragbits from the terminal. Other packages can extend the CLI by adding their own commands, so the exact set of available commands may vary depending on the installed packages.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To use the complete Ragbits stack, install the `ragbits` package:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pip install ragbits
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Example Usage
|
|
14
|
+
The following example assumes that `ragbits-core` is installed and that the current ddirectory contains a `song_prompt.py` file with a prompt class named `SongPrompt`, as defined in the [Quickstart Guide](https://ragbits.deepsense.ai/quickstart/quickstart1_prompts/#making-the-prompt-dynamic).
|
|
15
|
+
|
|
16
|
+
The example demonstrates how to execute the prompt using the `ragbits` CLI tool.
|
|
17
|
+
The left side of the table shows the system and user prompts (rendered with placeholders replaced by the provided values), and the right side shows the generated response from the Large Language Model.
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
$ ragbits prompts exec song_prompt:SongPrompt --payload '{"subject": "unicorns", "age_group": 12, "genre": "pop"}'
|
|
21
|
+
|
|
22
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
23
|
+
┃ Question ┃ Answer ┃
|
|
24
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
25
|
+
│ [{'role': 'system', 'content': 'You │ (Verse 1) │
|
|
26
|
+
│ are a professional songwriter. │ In a land of rainbows and glitter, │
|
|
27
|
+
│ You only use language that is │ Where flowers bloom and skies are │
|
|
28
|
+
│ appropriate for children.'}, │ brighter, │
|
|
29
|
+
│ {'role': 'user', 'content': 'Write a │ There's a magical creature so rare, │
|
|
30
|
+
│ song about a unicorns for 12 years │ With a horn that sparkles in the air. │
|
|
31
|
+
│ old pop fans.'}] │ │
|
|
32
|
+
│ │ (Chorus) │
|
|
33
|
+
│ │ Unicorns, unicorns, oh so divine, │
|
|
34
|
+
│ │ With their mane that shines and eyes │
|
|
35
|
+
│ │ that shine, │
|
|
36
|
+
│ │ Gallop through the meadows, so free, │
|
|
37
|
+
│ │ In a world of wonder, just you and │
|
|
38
|
+
│ │ me. │
|
|
39
|
+
└───────────────────────────────────────┴───────────────────────────────────────┘
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
* [Documentation of the `ragbits` CLI](https://ragbits.deepsense.ai/cli/main/)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ragbits-cli"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.8.dev23005"
|
|
4
4
|
description = "A CLI application for ragbits - building blocks for rapid development of GenAI applications"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
license = "MIT"
|
|
8
8
|
authors = [
|
|
9
|
-
{ name = "deepsense.ai", email = "
|
|
9
|
+
{ name = "deepsense.ai", email = "ragbits@deepsense.ai"}
|
|
10
10
|
]
|
|
11
11
|
keywords = [
|
|
12
12
|
"Retrieval Augmented Generation",
|
|
@@ -18,7 +18,7 @@ keywords = [
|
|
|
18
18
|
"Prompt Management"
|
|
19
19
|
]
|
|
20
20
|
classifiers = [
|
|
21
|
-
"Development Status ::
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
22
|
"Environment :: Console",
|
|
23
23
|
"Intended Audience :: Science/Research",
|
|
24
24
|
"License :: OSI Approved :: MIT License",
|
|
@@ -27,12 +27,17 @@ classifiers = [
|
|
|
27
27
|
"Programming Language :: Python :: 3.10",
|
|
28
28
|
"Programming Language :: Python :: 3.11",
|
|
29
29
|
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Programming Language :: Python :: 3.13",
|
|
30
31
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
31
32
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
32
33
|
]
|
|
33
|
-
dependencies = [
|
|
34
|
-
|
|
35
|
-
]
|
|
34
|
+
dependencies = ["typer>=0.12.5,<1.0.0", "ragbits-core==0.0.8.dev23005"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
"Homepage" = "https://github.com/deepsense-ai/ragbits"
|
|
38
|
+
"Bug Reports" = "https://github.com/deepsense-ai/ragbits/issues"
|
|
39
|
+
"Documentation" = "https://ragbits.deepsense.ai/"
|
|
40
|
+
"Source" = "https://github.com/deepsense-ai/ragbits"
|
|
36
41
|
|
|
37
42
|
[project.scripts]
|
|
38
43
|
ragbits = "ragbits.cli:main"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
import os
|
|
3
|
+
import pkgutil
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
# litellm downloads cost map on import, which creates extra latency in CLI.
|
|
9
|
+
# This config disables it.
|
|
10
|
+
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
import typer
|
|
14
|
+
from typer.main import get_command
|
|
15
|
+
|
|
16
|
+
import ragbits
|
|
17
|
+
from ragbits.core.audit.traces import set_trace_handlers
|
|
18
|
+
|
|
19
|
+
from .state import OutputType, cli_state, print_output
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"OutputType",
|
|
23
|
+
"app",
|
|
24
|
+
"cli_state",
|
|
25
|
+
"print_output",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
app = typer.Typer(no_args_is_help=True)
|
|
29
|
+
_click_app: click.Command | None = None # initialized in the `init_for_mkdocs` function
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@app.callback()
|
|
33
|
+
def ragbits_cli(
|
|
34
|
+
# `OutputType.text.value` used as a workaround for the issue with `typer.Option` not accepting Enum values
|
|
35
|
+
output: Annotated[
|
|
36
|
+
OutputType, typer.Option("--output", "-o", help="Set the output type (text or json)")
|
|
37
|
+
] = OutputType.text.value, # type: ignore
|
|
38
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Print additional information"),
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Common CLI arguments for all ragbits commands."""
|
|
41
|
+
cli_state.output_type = output
|
|
42
|
+
cli_state.verbose = verbose
|
|
43
|
+
|
|
44
|
+
if verbose == 1:
|
|
45
|
+
typer.echo("Verbose mode is enabled.")
|
|
46
|
+
set_trace_handlers("cli")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def autoregister() -> None:
|
|
50
|
+
"""
|
|
51
|
+
Autodiscover and register all the CLI modules in the ragbits packages.
|
|
52
|
+
|
|
53
|
+
This function registers all the CLI modules in the ragbits packages:
|
|
54
|
+
- iterates over every package in the ragbits.* namespace
|
|
55
|
+
- it looks for `cli` package / module
|
|
56
|
+
- if found it imports the `register` function from the `cli` module and calls it with the `app` object
|
|
57
|
+
- register function should add the CLI commands to the `app` object
|
|
58
|
+
"""
|
|
59
|
+
cli_enabled_modules = [
|
|
60
|
+
module
|
|
61
|
+
for module in pkgutil.iter_modules(ragbits.__path__)
|
|
62
|
+
if module.ispkg and module.name != "cli" and (Path(module.module_finder.path) / module.name / "cli.py").exists() # type: ignore
|
|
63
|
+
]
|
|
64
|
+
sys.path.append(os.getcwd())
|
|
65
|
+
|
|
66
|
+
for module in cli_enabled_modules:
|
|
67
|
+
register_func = importlib.import_module(f"ragbits.{module.name}.cli").register
|
|
68
|
+
register_func(app)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _init_for_mkdocs() -> None:
|
|
72
|
+
"""
|
|
73
|
+
Initializes the CLI app for the mkdocs environment.
|
|
74
|
+
|
|
75
|
+
This function registers all the CLI commands and sets the `_click_app` variable to a click
|
|
76
|
+
command object containing all the CLI commands. This way the `mkdocs-click` plugin can
|
|
77
|
+
create an automatic CLI documentation.
|
|
78
|
+
"""
|
|
79
|
+
global _click_app # noqa: PLW0603
|
|
80
|
+
autoregister()
|
|
81
|
+
_click_app = get_command(app)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def main() -> None:
|
|
85
|
+
"""
|
|
86
|
+
Main entry point for the CLI. Registers all the CLI commands and runs the app.
|
|
87
|
+
"""
|
|
88
|
+
autoregister()
|
|
89
|
+
app()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Protocol, TypeVar
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from pydantic.alias_generators import to_snake
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
from ragbits.core.config import CoreConfig, core_config
|
|
9
|
+
from ragbits.core.utils.config_handling import InvalidConfigError, NoPreferredConfigError, WithConstructionConfig
|
|
10
|
+
|
|
11
|
+
WithConstructionConfigT_co = TypeVar("WithConstructionConfigT_co", bound=WithConstructionConfig, covariant=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Using a Protocol instead of simply typing the `cls` argument to `get_instance_or_exit`
|
|
15
|
+
# as `type[WithConstructionConfigT]` in order to workaround the issue of mypy not allowing abstract classes
|
|
16
|
+
# to be used as types: https://github.com/python/mypy/issues/4717
|
|
17
|
+
class WithConstructionConfigProtocol(Protocol[WithConstructionConfigT_co]):
|
|
18
|
+
@classmethod
|
|
19
|
+
def preferred_subclass(
|
|
20
|
+
cls, config: CoreConfig, factory_path_override: str | None = None, yaml_path_override: Path | None = None
|
|
21
|
+
) -> WithConstructionConfigT_co: ...
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_instance_or_exit(
|
|
25
|
+
cls: WithConstructionConfigProtocol[WithConstructionConfigT_co],
|
|
26
|
+
type_name: str | None = None,
|
|
27
|
+
yaml_path: Path | None = None,
|
|
28
|
+
factory_path: str | None = None,
|
|
29
|
+
config_override: CoreConfig | None = None,
|
|
30
|
+
yaml_path_argument_name: str = "--yaml-path",
|
|
31
|
+
factory_path_argument_name: str = "--factory-path",
|
|
32
|
+
) -> WithConstructionConfigT_co:
|
|
33
|
+
"""
|
|
34
|
+
Returns an instance of the provided class, initialized using its `preferred_subclass` method.
|
|
35
|
+
If the instance can't be created, prints an error message and exits the program.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
cls: The class to create an instance of.
|
|
39
|
+
type_name: The name to use in error messages. If None, inferred from the class name.
|
|
40
|
+
yaml_path: Path to a YAML configuration file to use for initialization.
|
|
41
|
+
factory_path: Python path to a factory function to use for initialization.
|
|
42
|
+
yaml_path_argument_name: The name of the argument to use in error messages for the YAML path.
|
|
43
|
+
config_override: A config instance to be used
|
|
44
|
+
factory_path_argument_name: The name of the argument to use in error messages for the factory path.
|
|
45
|
+
"""
|
|
46
|
+
if not isinstance(cls, type):
|
|
47
|
+
raise TypeError(f"get_instance_or_exit expects the `cls` argument to be a class, got {cls}")
|
|
48
|
+
|
|
49
|
+
type_name = type_name or to_snake(cls.__name__).replace("_", " ")
|
|
50
|
+
try:
|
|
51
|
+
return cls.preferred_subclass(
|
|
52
|
+
config_override or core_config,
|
|
53
|
+
factory_path_override=factory_path,
|
|
54
|
+
yaml_path_override=yaml_path,
|
|
55
|
+
)
|
|
56
|
+
except NoPreferredConfigError as e:
|
|
57
|
+
Console(
|
|
58
|
+
stderr=True
|
|
59
|
+
).print(f"""You need to provide the [b]{type_name}[/b] instance to be used. You can do this by either:
|
|
60
|
+
- providing a path to a YAML configuration file with the [b]{yaml_path_argument_name}[/b] option
|
|
61
|
+
- providing a Python path to a function that creates a vector store with the [b]{factory_path_argument_name}[/b] option
|
|
62
|
+
- setting the preferred {type_name} configuration in your project's [b]pyproject.toml[/b] file
|
|
63
|
+
(see https://ragbits.deepsense.ai/how-to/project/component_preferences/ for more information)""")
|
|
64
|
+
raise typer.Exit(1) from e
|
|
65
|
+
except InvalidConfigError as e:
|
|
66
|
+
Console(stderr=True).print(e)
|
|
67
|
+
raise typer.Exit(1) from e
|
|
File without changes
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections.abc import Mapping, Sequence
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from types import UnionType
|
|
6
|
+
from typing import Optional, TypeVar, Union, get_args, get_origin
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
from pydantic.fields import FieldInfo
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.table import Column, Table
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OutputType(Enum):
|
|
16
|
+
"""Indicates a type of CLI output formatting"""
|
|
17
|
+
|
|
18
|
+
text = "text"
|
|
19
|
+
json = "json"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass()
|
|
23
|
+
class CliState:
|
|
24
|
+
"""A dataclass describing CLI state"""
|
|
25
|
+
|
|
26
|
+
verbose: bool = False
|
|
27
|
+
output_type: OutputType = OutputType.text
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
cli_state = CliState()
|
|
31
|
+
|
|
32
|
+
ModelT = TypeVar("ModelT", bound=BaseModel)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def print_output_table(
|
|
36
|
+
data: Sequence[ModelT], columns: Mapping[str, Column] | Sequence[str] | str | None = None
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Display data from Pydantic models in a table format.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
data: a list of pydantic models representing output of CLI function
|
|
43
|
+
columns: a list of columns to display in the output table: either as a list, string with comma separated names,
|
|
44
|
+
or for grater control over how the data is displayed a mapping of column names to Column objects.
|
|
45
|
+
If not provided, the columns will be inferred from the model schema.
|
|
46
|
+
"""
|
|
47
|
+
console = Console()
|
|
48
|
+
|
|
49
|
+
if not data:
|
|
50
|
+
console.print("No results")
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
base_fields = {**data[0].model_fields, **data[0].model_computed_fields}
|
|
54
|
+
|
|
55
|
+
# Normalize the list of columns
|
|
56
|
+
if columns is None:
|
|
57
|
+
columns = {key: Column() for key in base_fields}
|
|
58
|
+
elif isinstance(columns, str):
|
|
59
|
+
columns = {key: Column() for key in columns.split(",")}
|
|
60
|
+
elif isinstance(columns, Sequence):
|
|
61
|
+
columns = {key: Column() for key in columns}
|
|
62
|
+
|
|
63
|
+
# check if columns are correct
|
|
64
|
+
for column_name in columns:
|
|
65
|
+
field = _get_nested_field(column_name, base_fields)
|
|
66
|
+
column = columns[column_name]
|
|
67
|
+
if column.header == "":
|
|
68
|
+
column.header = field.title if field.title else column_name.replace("_", " ").replace(".", " ").title()
|
|
69
|
+
|
|
70
|
+
# Create and print the table
|
|
71
|
+
table = Table(*columns.values(), show_header=True, header_style="bold magenta")
|
|
72
|
+
|
|
73
|
+
for row in data:
|
|
74
|
+
row_to_add = []
|
|
75
|
+
for key in columns:
|
|
76
|
+
*path_fragments, field_name = key.strip().split(".")
|
|
77
|
+
base_row = row
|
|
78
|
+
for fragment in path_fragments:
|
|
79
|
+
base_row = getattr(base_row, fragment)
|
|
80
|
+
z = getattr(base_row, field_name)
|
|
81
|
+
row_to_add.append(str(z))
|
|
82
|
+
table.add_row(*row_to_add)
|
|
83
|
+
|
|
84
|
+
console.print(table)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _get_nested_field(column_name: str, base_fields: dict) -> FieldInfo:
|
|
88
|
+
"""
|
|
89
|
+
Check if column name exists in the model schema.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
column_name: name of the column to check
|
|
93
|
+
base_fields: model fields
|
|
94
|
+
Returns:
|
|
95
|
+
field: nested field
|
|
96
|
+
"""
|
|
97
|
+
fields = base_fields
|
|
98
|
+
*path_fragments, field_name = column_name.strip().split(".")
|
|
99
|
+
for fragment in path_fragments:
|
|
100
|
+
if fragment not in fields:
|
|
101
|
+
Console(stderr=True).print(
|
|
102
|
+
f"Unknown column: {'.'.join(path_fragments + [field_name])} ({fragment} not found)"
|
|
103
|
+
)
|
|
104
|
+
raise typer.Exit(1)
|
|
105
|
+
model_class = fields[fragment].annotation
|
|
106
|
+
if get_origin(model_class) in [UnionType, Optional, Union]:
|
|
107
|
+
types = get_args(model_class)
|
|
108
|
+
model_class = next((t for t in types if t is not type(None)), None)
|
|
109
|
+
if model_class and issubclass(model_class, BaseModel):
|
|
110
|
+
fields = {**model_class.model_fields, **model_class.model_computed_fields}
|
|
111
|
+
if field_name not in fields:
|
|
112
|
+
Console(stderr=True).print(
|
|
113
|
+
f"Unknown column: {'.'.join(path_fragments + [field_name])} ({field_name} not found)"
|
|
114
|
+
)
|
|
115
|
+
raise typer.Exit(1)
|
|
116
|
+
return fields[field_name]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def print_output_json(data: Sequence[ModelT]) -> None:
|
|
120
|
+
"""
|
|
121
|
+
Display data from Pydantic models in a JSON format.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
data: a list of pydantic models representing output of CLI function
|
|
125
|
+
"""
|
|
126
|
+
console = Console()
|
|
127
|
+
console.print(json.dumps([output.model_dump(mode="json") for output in data], indent=4))
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def print_output(
|
|
131
|
+
data: Sequence[ModelT] | ModelT, columns: Mapping[str, Column] | Sequence[str] | str | None = None
|
|
132
|
+
) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Process and display output based on the current state's output type.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
data: a list of pydantic models representing output of CLI function
|
|
138
|
+
columns: a list of columns to display in the output table: either as a list, string with comma separated names,
|
|
139
|
+
or for grater control over how the data is displayed a mapping of column names to Column objects.
|
|
140
|
+
If not provided, the columns will be inferred from the model schema.
|
|
141
|
+
"""
|
|
142
|
+
if not isinstance(data, Sequence):
|
|
143
|
+
data = [data]
|
|
144
|
+
|
|
145
|
+
match cli_state.output_type:
|
|
146
|
+
case OutputType.text:
|
|
147
|
+
print_output_table(data, columns)
|
|
148
|
+
case OutputType.json:
|
|
149
|
+
print_output_json(data)
|
|
150
|
+
case _:
|
|
151
|
+
raise ValueError(f"Unsupported output type: {cli_state.output_type}")
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from unittest.mock import MagicMock, patch
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
import typer
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from pydantic.fields import Field, FieldInfo
|
|
8
|
+
from rich.table import Column, Table
|
|
9
|
+
|
|
10
|
+
from ragbits.cli.state import OutputType, _get_nested_field, print_output, print_output_table
|
|
11
|
+
from ragbits.core.sources.local import LocalFileSource
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InnerTestModel(BaseModel):
|
|
15
|
+
id: int
|
|
16
|
+
name: str = Field(title="Name of the inner model", description="Name of the inner model")
|
|
17
|
+
location: LocalFileSource
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class OtherTestModel(BaseModel):
|
|
21
|
+
id: int
|
|
22
|
+
name: str
|
|
23
|
+
location: InnerTestModel
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MainTestModel(BaseModel):
|
|
27
|
+
id: int
|
|
28
|
+
name: str
|
|
29
|
+
model: OtherTestModel | None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
data = [
|
|
33
|
+
MainTestModel(
|
|
34
|
+
id=1,
|
|
35
|
+
name="A",
|
|
36
|
+
model=OtherTestModel(
|
|
37
|
+
id=11,
|
|
38
|
+
name="aa",
|
|
39
|
+
location=InnerTestModel(id=111, name="aa1", location=LocalFileSource(path=Path("folder_1"))),
|
|
40
|
+
),
|
|
41
|
+
),
|
|
42
|
+
MainTestModel(
|
|
43
|
+
id=2,
|
|
44
|
+
name="B",
|
|
45
|
+
model=OtherTestModel(
|
|
46
|
+
id=22,
|
|
47
|
+
name="bb",
|
|
48
|
+
location=InnerTestModel(id=222, name="aa2", location=LocalFileSource(path=Path("folder_2"))),
|
|
49
|
+
),
|
|
50
|
+
),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@patch("ragbits.cli.state.print_output_table")
|
|
55
|
+
@patch("ragbits.cli.state.print_output_json")
|
|
56
|
+
def test_print_output_text(mock_print_output_json: MagicMock, mock_print_output_table: MagicMock):
|
|
57
|
+
with patch("ragbits.cli.state.cli_state") as mock_cli_state:
|
|
58
|
+
mock_cli_state.output_type = OutputType.text
|
|
59
|
+
columns = {"id": Column(), "name": Column()}
|
|
60
|
+
print_output(data, columns=columns)
|
|
61
|
+
mock_print_output_table.assert_called_once_with(data, columns)
|
|
62
|
+
mock_print_output_json.assert_not_called()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@patch("ragbits.cli.state.print_output_table")
|
|
66
|
+
@patch("ragbits.cli.state.print_output_json")
|
|
67
|
+
def test_print_output_json(mock_print_output_json: MagicMock, mock_print_output_table: MagicMock):
|
|
68
|
+
with patch("ragbits.cli.state.cli_state") as mock_cli_state:
|
|
69
|
+
mock_cli_state.output_type = OutputType.json
|
|
70
|
+
print_output(data)
|
|
71
|
+
mock_print_output_table.assert_not_called()
|
|
72
|
+
mock_print_output_json.assert_called_once_with(data)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_print_output_unsupported_output_type():
|
|
76
|
+
with patch("ragbits.cli.state.cli_state") as mock_cli_state:
|
|
77
|
+
mock_cli_state.output_type = "unsupported_type"
|
|
78
|
+
with pytest.raises(ValueError, match="Unsupported output type: unsupported_type"):
|
|
79
|
+
print_output(data)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_print_output_table():
|
|
83
|
+
with patch("rich.console.Console.print") as mock_print:
|
|
84
|
+
columns = {"id": Column(), "model.location.location.path": Column(), "model.location.name": Column()}
|
|
85
|
+
print_output_table(data, columns)
|
|
86
|
+
mock_print.assert_called_once()
|
|
87
|
+
args, _ = mock_print.call_args_list[0]
|
|
88
|
+
printed_table = args[0]
|
|
89
|
+
assert isinstance(printed_table, Table)
|
|
90
|
+
assert printed_table.columns[0].header == "Id"
|
|
91
|
+
assert printed_table.columns[1].header == "Model Location Location Path"
|
|
92
|
+
assert printed_table.columns[2].header == "Name of the inner model"
|
|
93
|
+
assert printed_table.row_count == 2
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_get_nested_field():
|
|
97
|
+
column = "model.location.location.path"
|
|
98
|
+
fields = {"name": FieldInfo(annotation=str), "model": FieldInfo(annotation=OtherTestModel)}
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
result = _get_nested_field(column, fields)
|
|
102
|
+
assert result.annotation == Path
|
|
103
|
+
except typer.Exit:
|
|
104
|
+
pytest.fail("typer.Exit was raised unexpectedly")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_get_nested_field_wrong_field():
|
|
108
|
+
column_names = [
|
|
109
|
+
("model.location.wrong_field", "wrong_field"),
|
|
110
|
+
("model.wrong_path.location.path", "wrong_path"),
|
|
111
|
+
("wrong_path.location.location.path", "wrong_path"),
|
|
112
|
+
("model.location.path", "path"),
|
|
113
|
+
("model.location.location.path.additional_field", "additional_field"),
|
|
114
|
+
]
|
|
115
|
+
fields = {"name": FieldInfo(annotation=str), "model": FieldInfo(annotation=OtherTestModel)}
|
|
116
|
+
|
|
117
|
+
for wrong_column, wrong_fragment in column_names:
|
|
118
|
+
with patch("rich.console.Console.print") as mock_print:
|
|
119
|
+
with pytest.raises(typer.Exit, match="1"):
|
|
120
|
+
_get_nested_field(wrong_column, fields)
|
|
121
|
+
mock_print.assert_called_once_with(f"Unknown column: {wrong_column} ({wrong_fragment} not found)")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from ragbits.cli._utils import get_instance_or_exit
|
|
4
|
+
from ragbits.core.utils.config_handling import WithConstructionConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ExampleClassForCLI(WithConstructionConfig):
|
|
8
|
+
default_module = sys.modules[__name__]
|
|
9
|
+
configuration_key = "example_cli"
|
|
10
|
+
|
|
11
|
+
def __init__(self, foo: str, bar: int) -> None:
|
|
12
|
+
self.foo = foo
|
|
13
|
+
self.bar = bar
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def sync_factory_for_cli() -> ExampleClassForCLI:
|
|
17
|
+
return ExampleClassForCLI("sync_cli", 123)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def async_factory_for_cli() -> ExampleClassForCLI:
|
|
21
|
+
"""Async factory function for testing CLI with async support."""
|
|
22
|
+
return ExampleClassForCLI("async_cli", 456)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_get_instance_or_exit_with_sync_factory():
|
|
26
|
+
"""Test that get_instance_or_exit works with sync factory functions."""
|
|
27
|
+
instance = get_instance_or_exit(ExampleClassForCLI, factory_path="sync_factory_for_cli")
|
|
28
|
+
assert isinstance(instance, ExampleClassForCLI)
|
|
29
|
+
assert instance.foo == "sync_cli"
|
|
30
|
+
assert instance.bar == 123
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_get_instance_or_exit_with_async_factory():
|
|
34
|
+
"""Test that get_instance_or_exit works with async factory functions."""
|
|
35
|
+
instance = get_instance_or_exit(ExampleClassForCLI, factory_path="async_factory_for_cli")
|
|
36
|
+
assert isinstance(instance, ExampleClassForCLI)
|
|
37
|
+
assert instance.foo == "async_cli"
|
|
38
|
+
assert instance.bar == 456
|
ragbits_cli-0.0.1/PKG-INFO
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: ragbits-cli
|
|
3
|
-
Version: 0.0.1
|
|
4
|
-
Summary: A CLI application for ragbits - building blocks for rapid development of GenAI applications
|
|
5
|
-
Author-email: "deepsense.ai" <contact@deepsense.ai>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Keywords: GenAI,Generative AI,LLMs,Large Language Models,Prompt Management,RAG,Retrieval Augmented Generation
|
|
8
|
-
Classifier: Development Status :: 1 - Planning
|
|
9
|
-
Classifier: Environment :: Console
|
|
10
|
-
Classifier: Intended Audience :: Science/Research
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Natural Language :: English
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
-
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: typer>=0.12.5
|
|
21
|
-
Description-Content-Type: text/markdown
|
|
22
|
-
|
|
23
|
-
# Ragbits CLI
|
ragbits_cli-0.0.1/README.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Ragbits CLI
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import importlib.util
|
|
2
|
-
import pkgutil
|
|
3
|
-
|
|
4
|
-
from typer import Typer
|
|
5
|
-
|
|
6
|
-
import ragbits
|
|
7
|
-
|
|
8
|
-
app = Typer(no_args_is_help=True)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def main() -> None:
|
|
12
|
-
"""
|
|
13
|
-
Main entry point for the CLI.
|
|
14
|
-
|
|
15
|
-
This function registers all the CLI modules in the ragbits packages:
|
|
16
|
-
- iterates over every package in the ragbits.* namespace
|
|
17
|
-
- it looks for `cli` package / module
|
|
18
|
-
- if found it imports the `register` function from the `cli` module and calls it with the `app` object
|
|
19
|
-
- register function should add the CLI commands to the `app` object
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
cli_enabled_modules = [
|
|
23
|
-
module
|
|
24
|
-
for module in pkgutil.iter_modules(ragbits.__path__)
|
|
25
|
-
if module.ispkg and module.name != "cli" and importlib.util.find_spec(f"ragbits.{module.name}.cli")
|
|
26
|
-
]
|
|
27
|
-
for module in cli_enabled_modules:
|
|
28
|
-
register_func = importlib.import_module(f"ragbits.{module.name}.cli").register
|
|
29
|
-
register_func(app)
|
|
30
|
-
|
|
31
|
-
app()
|