docpilot-cli 1.0.0__tar.gz → 1.0.2__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.
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/PKG-INFO +13 -3
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/README.md +12 -2
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/pyproject.toml +1 -2
- docpilot_cli-1.0.2/src/docpilot/__main__.py +4 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/chat.py +14 -2
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/cli.py +22 -4
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/embed.py +2 -2
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/store.py +27 -1
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/PKG-INFO +13 -3
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/SOURCES.txt +1 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/tests/test_store.py +1 -4
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/LICENSE +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/setup.cfg +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/__init__.py +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot/scrape.py +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/dependency_links.txt +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/entry_points.txt +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/requires.txt +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/src/docpilot_cli.egg-info/top_level.txt +0 -0
- {docpilot_cli-1.0.0 → docpilot_cli-1.0.2}/tests/test_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docpilot-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: A local-first RAG pipeline CLI tool
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -20,9 +20,9 @@ Requires-Dist: pyfiglet>=0.8.0
|
|
|
20
20
|
Requires-Dist: rich>=13.0.0
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
|
-
# 🚀 DocPilot CLI
|
|
23
|
+
# 🚀 [DocPilot CLI](https://pypi.org/project/docpilot-cli/)
|
|
24
24
|
|
|
25
|
-

|
|
25
|
+
[](https://pypi.org/project/docpilot-cli/)
|
|
26
26
|

|
|
27
27
|

|
|
28
28
|
|
|
@@ -87,6 +87,9 @@ docpilot ingest "./docs/engineering_handbook.pdf"
|
|
|
87
87
|
docpilot ingest "./data/faq.csv"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
> [!TIP]
|
|
91
|
+
> If you installed via standard `pip` and get a "command not found" error because your binary path isn't configured, you can always run docpilot by prefixing commands with `python -m docpilot` (e.g., `python -m docpilot ingest ...`).
|
|
92
|
+
|
|
90
93
|
### 2. Ask Questions
|
|
91
94
|
Query your newly created local knowledge base:
|
|
92
95
|
|
|
@@ -103,6 +106,13 @@ Manage your configuration, models, and local database with ease.
|
|
|
103
106
|
### `docpilot setup`
|
|
104
107
|
Re-run the interactive setup wizard at any time to change your default models.
|
|
105
108
|
|
|
109
|
+
### `docpilot project`
|
|
110
|
+
Switch to a different project or check the active project. Each project has its own isolated vector database.
|
|
111
|
+
```bash
|
|
112
|
+
docpilot project
|
|
113
|
+
docpilot project <project-name>
|
|
114
|
+
```
|
|
115
|
+
|
|
106
116
|
### `docpilot clear`
|
|
107
117
|
Wipe your local Chroma vector database to start fresh. Prompts for safety confirmation.
|
|
108
118
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# 🚀 DocPilot CLI
|
|
1
|
+
# 🚀 [DocPilot CLI](https://pypi.org/project/docpilot-cli/)
|
|
2
2
|
|
|
3
|
-

|
|
3
|
+
[](https://pypi.org/project/docpilot-cli/)
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|
|
|
@@ -65,6 +65,9 @@ docpilot ingest "./docs/engineering_handbook.pdf"
|
|
|
65
65
|
docpilot ingest "./data/faq.csv"
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
> [!TIP]
|
|
69
|
+
> If you installed via standard `pip` and get a "command not found" error because your binary path isn't configured, you can always run docpilot by prefixing commands with `python -m docpilot` (e.g., `python -m docpilot ingest ...`).
|
|
70
|
+
|
|
68
71
|
### 2. Ask Questions
|
|
69
72
|
Query your newly created local knowledge base:
|
|
70
73
|
|
|
@@ -81,6 +84,13 @@ Manage your configuration, models, and local database with ease.
|
|
|
81
84
|
### `docpilot setup`
|
|
82
85
|
Re-run the interactive setup wizard at any time to change your default models.
|
|
83
86
|
|
|
87
|
+
### `docpilot project`
|
|
88
|
+
Switch to a different project or check the active project. Each project has its own isolated vector database.
|
|
89
|
+
```bash
|
|
90
|
+
docpilot project
|
|
91
|
+
docpilot project <project-name>
|
|
92
|
+
```
|
|
93
|
+
|
|
84
94
|
### `docpilot clear`
|
|
85
95
|
Wipe your local Chroma vector database to start fresh. Prompts for safety confirmation.
|
|
86
96
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "docpilot-cli"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.2"
|
|
4
4
|
description = "A local-first RAG pipeline CLI tool"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -29,7 +29,6 @@ where = ["src"]
|
|
|
29
29
|
[build-system]
|
|
30
30
|
requires = ["setuptools>=68", "wheel"]
|
|
31
31
|
build-backend = "setuptools.build_meta"
|
|
32
|
-
|
|
33
32
|
[dependency-groups]
|
|
34
33
|
dev = [
|
|
35
34
|
"pytest>=8.0.0",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from langchain_ollama.llms import OllamaLLM as Ollama
|
|
2
2
|
from langchain_core.prompts import ChatPromptTemplate
|
|
3
|
-
from .embed import vectorstore
|
|
4
3
|
import os
|
|
5
4
|
from . import store
|
|
5
|
+
from langchain_chroma import Chroma
|
|
6
|
+
from langchain_ollama import OllamaEmbeddings
|
|
6
7
|
|
|
7
8
|
config = store.load_config()
|
|
8
9
|
retrieval_k = int(config.get("retrieval_k", 6))
|
|
@@ -17,7 +18,16 @@ model = Ollama(
|
|
|
17
18
|
temperature=float(config.get("temperature", 0.1)),
|
|
18
19
|
)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
def _get_vectorstore():
|
|
23
|
+
"""Get vectorstore for the active project."""
|
|
24
|
+
embeddings = OllamaEmbeddings(model=config.get("default_embed_model", "mxbai-embed-large:335m"))
|
|
25
|
+
db_location = store.get_active_project_path()
|
|
26
|
+
return Chroma(collection_name="documents", persist_directory=str(db_location), embedding_function=embeddings)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
retriever = None
|
|
30
|
+
|
|
21
31
|
template = """
|
|
22
32
|
You are an assistant for answering questions based on the following ingested documents.
|
|
23
33
|
Use the information in the documents to answer the question as best as you can.
|
|
@@ -47,6 +57,8 @@ def _build_bounded_context(docs, max_total_chars: int = 6000, max_doc_chars: int
|
|
|
47
57
|
|
|
48
58
|
|
|
49
59
|
def askai(question):
|
|
60
|
+
vectorstore = _get_vectorstore()
|
|
61
|
+
retriever = vectorstore.as_retriever(search_kwargs={"k": retrieval_k})
|
|
50
62
|
rag = retriever.invoke(question)
|
|
51
63
|
rag_text = _build_bounded_context(
|
|
52
64
|
rag,
|
|
@@ -21,11 +21,30 @@ console = Console()
|
|
|
21
21
|
app = typer.Typer()
|
|
22
22
|
|
|
23
23
|
# Project metadata
|
|
24
|
-
PROJECT_VERSION = "
|
|
24
|
+
PROJECT_VERSION = "1.0.2"
|
|
25
25
|
PROJECT_NAME = "docpilot"
|
|
26
26
|
PROJECT_DESCRIPTION = "A local-first RAG pipeline CLI tool"
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
@app.command()
|
|
30
|
+
def project(
|
|
31
|
+
action: str = typer.Argument(None, help="Action: 'status' to show active project, or project name to switch"),
|
|
32
|
+
):
|
|
33
|
+
"""Manage projects: show status or switch to a project."""
|
|
34
|
+
if action is None or action == "status":
|
|
35
|
+
active = store.get_active_project()
|
|
36
|
+
path = store.get_active_project_path()
|
|
37
|
+
console.print(f"[bold cyan]Active Project:[/bold cyan] {active}")
|
|
38
|
+
console.print(f"[dim]DB path:[/dim] {path}")
|
|
39
|
+
else:
|
|
40
|
+
try:
|
|
41
|
+
project_path = store.set_active_project(action)
|
|
42
|
+
console.print(f"[green]✓ Switched to project:[/green] [bold]{action}[/bold]")
|
|
43
|
+
console.print(f"[dim]DB path:[/dim] {project_path}")
|
|
44
|
+
except Exception as e:
|
|
45
|
+
console.print(f"[red]Error setting project:[/red] {e}")
|
|
46
|
+
|
|
47
|
+
|
|
29
48
|
def loadpdf(file_path: Path) -> list[str]:
|
|
30
49
|
try:
|
|
31
50
|
PdfReader = importlib.import_module("pypdf").PdfReader
|
|
@@ -212,9 +231,8 @@ def ask(question: str):
|
|
|
212
231
|
|
|
213
232
|
@app.command()
|
|
214
233
|
def clear():
|
|
215
|
-
"""Clear the local vector database."""
|
|
216
|
-
|
|
217
|
-
db_path = Path(config.get("db_path", ""))
|
|
234
|
+
"""Clear the local vector database for the active project."""
|
|
235
|
+
db_path = store.get_active_project_path()
|
|
218
236
|
|
|
219
237
|
if not db_path.exists():
|
|
220
238
|
console.print("[yellow]Database is already empty or does not exist.[/yellow]")
|
|
@@ -88,9 +88,9 @@ def _print_progress(label: str, current: int, total: int, width: int = 28) -> No
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
embeddings = OllamaEmbeddings(model=store.load_config().get("default_embed_model", "mxbai-embed-large:335m"))
|
|
91
|
-
db_location = store.
|
|
91
|
+
db_location = store.get_active_project_path()
|
|
92
92
|
|
|
93
|
-
vectorstore = Chroma(collection_name="documents", persist_directory=db_location, embedding_function=embeddings)
|
|
93
|
+
vectorstore = Chroma(collection_name="documents", persist_directory=str(db_location), embedding_function=embeddings)
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
def chunk_text(
|
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
|
|
7
7
|
path = Path.home() / ".docpilot"
|
|
8
8
|
CONFIG_PATH = path / "config.toml"
|
|
9
|
+
PROJECTS_DIR = path / "projects"
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def _get_available_models():
|
|
@@ -22,7 +23,7 @@ _AVAILABLE_MODELS = _get_available_models()
|
|
|
22
23
|
DEFAULT_CONFIG = {
|
|
23
24
|
"default_embed_model": _AVAILABLE_MODELS[0] if _AVAILABLE_MODELS else "mxbai-embed-large:335m",
|
|
24
25
|
"default_model": _AVAILABLE_MODELS[1] if len(_AVAILABLE_MODELS) > 1 else "llama2",
|
|
25
|
-
"
|
|
26
|
+
"active_project": "default",
|
|
26
27
|
"log_level": "info",
|
|
27
28
|
"retrieval_k": 6,
|
|
28
29
|
"max_context_chars": 3500,
|
|
@@ -52,6 +53,8 @@ def init_config():
|
|
|
52
53
|
"""Initialize config file with defaults if it doesn't exist."""
|
|
53
54
|
if not CONFIG_PATH.exists():
|
|
54
55
|
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
56
|
+
PROJECTS_DIR.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
(PROJECTS_DIR / "default").mkdir(parents=True, exist_ok=True)
|
|
55
58
|
interactive_setup(first_time=True)
|
|
56
59
|
return load_config()
|
|
57
60
|
|
|
@@ -111,3 +114,26 @@ def save_config(config: dict):
|
|
|
111
114
|
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
112
115
|
with open(CONFIG_PATH, "wb") as f:
|
|
113
116
|
tomli_w.dump(config, f)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_active_project() -> str:
|
|
120
|
+
"""Get the currently active project name."""
|
|
121
|
+
config = load_config()
|
|
122
|
+
return config.get("active_project", "default")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def set_active_project(project_name: str) -> Path:
|
|
126
|
+
"""Set active project and ensure its directory exists. Returns the project path."""
|
|
127
|
+
project_path = PROJECTS_DIR / project_name / "chroma_langchain_db"
|
|
128
|
+
project_path.parent.mkdir(parents=True, exist_ok=True)
|
|
129
|
+
|
|
130
|
+
config = load_config()
|
|
131
|
+
config["active_project"] = project_name
|
|
132
|
+
save_config(config)
|
|
133
|
+
return project_path
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def get_active_project_path() -> Path:
|
|
137
|
+
"""Get the Chroma DB path for the currently active project."""
|
|
138
|
+
active_project = get_active_project()
|
|
139
|
+
return PROJECTS_DIR / active_project / "chroma_langchain_db"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docpilot-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: A local-first RAG pipeline CLI tool
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -20,9 +20,9 @@ Requires-Dist: pyfiglet>=0.8.0
|
|
|
20
20
|
Requires-Dist: rich>=13.0.0
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
|
-
# 🚀 DocPilot CLI
|
|
23
|
+
# 🚀 [DocPilot CLI](https://pypi.org/project/docpilot-cli/)
|
|
24
24
|
|
|
25
|
-

|
|
25
|
+
[](https://pypi.org/project/docpilot-cli/)
|
|
26
26
|

|
|
27
27
|

|
|
28
28
|
|
|
@@ -87,6 +87,9 @@ docpilot ingest "./docs/engineering_handbook.pdf"
|
|
|
87
87
|
docpilot ingest "./data/faq.csv"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
> [!TIP]
|
|
91
|
+
> If you installed via standard `pip` and get a "command not found" error because your binary path isn't configured, you can always run docpilot by prefixing commands with `python -m docpilot` (e.g., `python -m docpilot ingest ...`).
|
|
92
|
+
|
|
90
93
|
### 2. Ask Questions
|
|
91
94
|
Query your newly created local knowledge base:
|
|
92
95
|
|
|
@@ -103,6 +106,13 @@ Manage your configuration, models, and local database with ease.
|
|
|
103
106
|
### `docpilot setup`
|
|
104
107
|
Re-run the interactive setup wizard at any time to change your default models.
|
|
105
108
|
|
|
109
|
+
### `docpilot project`
|
|
110
|
+
Switch to a different project or check the active project. Each project has its own isolated vector database.
|
|
111
|
+
```bash
|
|
112
|
+
docpilot project
|
|
113
|
+
docpilot project <project-name>
|
|
114
|
+
```
|
|
115
|
+
|
|
106
116
|
### `docpilot clear`
|
|
107
117
|
Wipe your local Chroma vector database to start fresh. Prompts for safety confirmation.
|
|
108
118
|
|
|
@@ -16,8 +16,5 @@ def test_init_config_creates_file(temp_config_path):
|
|
|
16
16
|
with patch("docpilot.store.interactive_setup") as mock_setup:
|
|
17
17
|
# Prevent it from prompting
|
|
18
18
|
mock_setup.return_value = None
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# We don't check for file existence because we mocked the setup function
|
|
22
|
-
# that normally creates the file. We just verify it was called.
|
|
19
|
+
store.init_config()
|
|
23
20
|
mock_setup.assert_called_once()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|