docqwise 0.2.1__tar.gz → 0.3.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.
- {docqwise-0.2.1 → docqwise-0.3.1}/PKG-INFO +92 -2
- {docqwise-0.2.1 → docqwise-0.3.1}/README.md +91 -1
- docqwise-0.3.1/docqwise/_version.py +1 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/engine.py +94 -3
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/field_extractor.py +1 -1
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/llm_extractor.py +3 -3
- docqwise-0.3.1/docqwise/extractors/multimodal_extractor.py +589 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/rag_extractor.py +10 -7
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/factory.py +4 -4
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/llm/hf_llm.py +3 -2
- docqwise-0.3.1/docqwise/llm/ollama.py +36 -0
- docqwise-0.3.1/docqwise/llm/openai_llm.py +51 -0
- docqwise-0.3.1/docqwise/retrieval/graphrag.py +430 -0
- docqwise-0.3.1/docqwise/retrieval/qa_engine.py +265 -0
- docqwise-0.3.1/docqwise/retrieval/rag_strategy.py +104 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/PKG-INFO +92 -2
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/SOURCES.txt +2 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/pyproject.toml +1 -1
- docqwise-0.2.1/docqwise/_version.py +0 -1
- docqwise-0.2.1/docqwise/extractors/multimodal_extractor.py +0 -240
- docqwise-0.2.1/docqwise/llm/ollama.py +0 -23
- docqwise-0.2.1/docqwise/llm/openai_llm.py +0 -26
- docqwise-0.2.1/docqwise/retrieval/qa_engine.py +0 -103
- {docqwise-0.2.1 → docqwise-0.3.1}/LICENSE +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/agent/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/benchmark/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/benchmark/runner.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/bridges/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/bridges/adaptive_bridge.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/bridges/evalkit_bridge.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/bridges/sightrag_bridge.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/bridges/sonarwise_bridge.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/chunkers/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/chunkers/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/chunkers/fixed_chunker.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/chunkers/sentence_chunker.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/chunkers/structure_chunker.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/classifier/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/classifier/zero_shot.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/cli/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/cli/main.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/comparator/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/comparator/text_diff.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/config.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/connectors/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/connectors/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/connectors/filesystem.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/bases.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/chunk.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/document.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/element.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/core/field.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/databases/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/databases/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/databases/sqlite_db.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/embedders/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/embedders/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/embedders/sentence_transformer.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/exceptions.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/export/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/export/csv_exporter.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/export/json_exporter.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/entity_extractor.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/image_extractor.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/metadata_extractor.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/table_extractor.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/extractors/text_extractor.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/graph/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/graph/backends/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/graph/document_graph.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/incremental/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/incremental/change_detector.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/incremental/watcher.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/layout/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/learning/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/learning/correction.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/llm/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/llm/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/ocr/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/ocr/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/ocr/easyocr_engine.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/ocr/tesseract_engine.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/pipeline/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/pipeline/pipeline.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/pipeline/prebuilt/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/auto_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/csv_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/docx_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/email_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/excel_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/html_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/image_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/json_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/parquet_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/pdf_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/pptx_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/readers/text_reader.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/retrieval/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/retrieval/hybrid_search.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/retrieval/query_router.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/retrieval/retriever.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/schema/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/schema/detector.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/schema/quality.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/schema/validator.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/security/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/security/pii_detector.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/server/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/server/api.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/server/mcp_server.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/server/routes/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/speed/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/speed/dispatcher.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/speed/progress.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/stores/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/stores/base.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/stores/faiss_store.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/stores/sqlite_store.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/strategy/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/strategy/profiler.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/strategy/router.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/templates/__init__.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/templates/contract.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/templates/invoice.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/templates/receipt.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise/templates/resume.py +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/dependency_links.txt +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/entry_points.txt +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/requires.txt +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/docqwise.egg-info/top_level.txt +0 -0
- {docqwise-0.2.1 → docqwise-0.3.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docqwise
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Read, Extract, Retrieve: Document intelligence that adapts, accelerates, and scales.
|
|
5
5
|
Author: Venkatkumar Rajan
|
|
6
6
|
License: Apache-2.0
|
|
@@ -95,7 +95,7 @@ Dynamic: license-file
|
|
|
95
95
|
</p>
|
|
96
96
|
|
|
97
97
|
<p align="center">
|
|
98
|
-
<a href="https://pypi.org/project/docqwise/"><img src="https://img.shields.io/badge/PyPI-
|
|
98
|
+
<a href="https://pypi.org/project/docqwise/"><img src="https://img.shields.io/badge/PyPI-v0.3.1-green" alt="PyPI"></a>
|
|
99
99
|
<a href="https://github.com/VK-Ant/docqwise/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
|
|
100
100
|
<a href="https://github.com/VK-Ant/docqwise/blob/main/notebooks/docqwise_getting_started.ipynb">
|
|
101
101
|
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"></a>
|
|
@@ -241,6 +241,38 @@ Return JSON matching the schema exactly.
|
|
|
241
241
|
""")
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
+
## System Prompt
|
|
245
|
+
|
|
246
|
+
Set the LLM's role before extraction. Works with all backends and all RAG modes.
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
# Set the role — LLM behaves as this specialist
|
|
250
|
+
dq.extract_fields("invoice.pdf",
|
|
251
|
+
system_prompt="You are a maritime document specialist with 20 years experience.",
|
|
252
|
+
prompt="Extract vessel name, port, and total cost.
|
|
253
|
+
|
|
254
|
+
Document:
|
|
255
|
+
{context}
|
|
256
|
+
|
|
257
|
+
JSON:",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# System prompt + schema + template — full control
|
|
261
|
+
dq.extract_fields("contract.pdf",
|
|
262
|
+
system_prompt="You are a legal analyst specializing in shipping law.",
|
|
263
|
+
schema={"parties": {"type": "array"}, "liability": {"type": "number"}},
|
|
264
|
+
prompt_template="Extract {schema} from:
|
|
265
|
+
{context}
|
|
266
|
+
JSON:",
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# System prompt with GraphRAG
|
|
270
|
+
dq.ask_rag("What is the liability cap?",
|
|
271
|
+
mode="graphrag",
|
|
272
|
+
system_prompt="You are a risk analyst. Be precise with numbers.",
|
|
273
|
+
)
|
|
274
|
+
```
|
|
275
|
+
|
|
244
276
|
## Self-Improving Corrections
|
|
245
277
|
|
|
246
278
|
```python
|
|
@@ -258,6 +290,64 @@ dq.ask("Which vendor has highest sales?") # GROUP BY + MAX
|
|
|
258
290
|
dq.ask("How many invoices are overdue?") # COUNT + WHERE
|
|
259
291
|
```
|
|
260
292
|
|
|
293
|
+
## Source Attribution
|
|
294
|
+
|
|
295
|
+
Every answer tells you which document it came from.
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
# Simple ask — shows source in output
|
|
299
|
+
answer = dq.ask("What is the total amount?")
|
|
300
|
+
print(answer)
|
|
301
|
+
# 2,18,300.00
|
|
302
|
+
# Source: sample_invoice.pdf
|
|
303
|
+
|
|
304
|
+
# Detailed answer with metadata
|
|
305
|
+
result = dq.ask_with_source("What is the governing law?")
|
|
306
|
+
print(result.answer) # "laws of India"
|
|
307
|
+
print(result.source_name) # "sample_contract.pdf"
|
|
308
|
+
print(result.confidence) # 0.85
|
|
309
|
+
print(result.method) # "llm"
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## RAG Modes
|
|
313
|
+
|
|
314
|
+
Choose your retrieval strategy:
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
dq = Docqwise()
|
|
318
|
+
dq.ingest("documents/")
|
|
319
|
+
|
|
320
|
+
# General RAG (default) — chunk → embed → retrieve → LLM
|
|
321
|
+
result = dq.ask_rag("total amount?", mode="general")
|
|
322
|
+
|
|
323
|
+
# GraphRAG — entity graph → graph traversal → cross-document answers
|
|
324
|
+
result = dq.ask_rag("Who is the vendor for PO-2012?", mode="graphrag")
|
|
325
|
+
print(result["answer"]) # "SuperStore"
|
|
326
|
+
print(result["source"]) # "invoice_001.pdf"
|
|
327
|
+
print(result["evidence"]) # [{entity, relation, target}, ...]
|
|
328
|
+
|
|
329
|
+
# Multimodal RAG — text + images → vision LLM
|
|
330
|
+
result = dq.ask_rag("What is in this scan?", mode="multimodal", source="scan.jpg")
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Graph Visualization
|
|
334
|
+
|
|
335
|
+
Build and visualize document knowledge graphs:
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
dq = Docqwise()
|
|
339
|
+
dq.ingest("documents/")
|
|
340
|
+
|
|
341
|
+
# Build knowledge graph from all documents
|
|
342
|
+
graphrag = dq.build_document_graph()
|
|
343
|
+
graph = graphrag.get_graph()
|
|
344
|
+
print(f"Nodes: {graph.node_count}, Edges: {graph.edge_count}")
|
|
345
|
+
|
|
346
|
+
# Generate interactive HTML visualization
|
|
347
|
+
dq.visualize_graph(output="my_graph.html")
|
|
348
|
+
# Open my_graph.html in browser — interactive, color-coded, draggable nodes
|
|
349
|
+
```
|
|
350
|
+
|
|
261
351
|
## All Features
|
|
262
352
|
|
|
263
353
|
```python
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
<a href="https://pypi.org/project/docqwise/"><img src="https://img.shields.io/badge/PyPI-
|
|
10
|
+
<a href="https://pypi.org/project/docqwise/"><img src="https://img.shields.io/badge/PyPI-v0.3.1-green" alt="PyPI"></a>
|
|
11
11
|
<a href="https://github.com/VK-Ant/docqwise/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
|
|
12
12
|
<a href="https://github.com/VK-Ant/docqwise/blob/main/notebooks/docqwise_getting_started.ipynb">
|
|
13
13
|
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"></a>
|
|
@@ -153,6 +153,38 @@ Return JSON matching the schema exactly.
|
|
|
153
153
|
""")
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
## System Prompt
|
|
157
|
+
|
|
158
|
+
Set the LLM's role before extraction. Works with all backends and all RAG modes.
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# Set the role — LLM behaves as this specialist
|
|
162
|
+
dq.extract_fields("invoice.pdf",
|
|
163
|
+
system_prompt="You are a maritime document specialist with 20 years experience.",
|
|
164
|
+
prompt="Extract vessel name, port, and total cost.
|
|
165
|
+
|
|
166
|
+
Document:
|
|
167
|
+
{context}
|
|
168
|
+
|
|
169
|
+
JSON:",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# System prompt + schema + template — full control
|
|
173
|
+
dq.extract_fields("contract.pdf",
|
|
174
|
+
system_prompt="You are a legal analyst specializing in shipping law.",
|
|
175
|
+
schema={"parties": {"type": "array"}, "liability": {"type": "number"}},
|
|
176
|
+
prompt_template="Extract {schema} from:
|
|
177
|
+
{context}
|
|
178
|
+
JSON:",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# System prompt with GraphRAG
|
|
182
|
+
dq.ask_rag("What is the liability cap?",
|
|
183
|
+
mode="graphrag",
|
|
184
|
+
system_prompt="You are a risk analyst. Be precise with numbers.",
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
156
188
|
## Self-Improving Corrections
|
|
157
189
|
|
|
158
190
|
```python
|
|
@@ -170,6 +202,64 @@ dq.ask("Which vendor has highest sales?") # GROUP BY + MAX
|
|
|
170
202
|
dq.ask("How many invoices are overdue?") # COUNT + WHERE
|
|
171
203
|
```
|
|
172
204
|
|
|
205
|
+
## Source Attribution
|
|
206
|
+
|
|
207
|
+
Every answer tells you which document it came from.
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
# Simple ask — shows source in output
|
|
211
|
+
answer = dq.ask("What is the total amount?")
|
|
212
|
+
print(answer)
|
|
213
|
+
# 2,18,300.00
|
|
214
|
+
# Source: sample_invoice.pdf
|
|
215
|
+
|
|
216
|
+
# Detailed answer with metadata
|
|
217
|
+
result = dq.ask_with_source("What is the governing law?")
|
|
218
|
+
print(result.answer) # "laws of India"
|
|
219
|
+
print(result.source_name) # "sample_contract.pdf"
|
|
220
|
+
print(result.confidence) # 0.85
|
|
221
|
+
print(result.method) # "llm"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## RAG Modes
|
|
225
|
+
|
|
226
|
+
Choose your retrieval strategy:
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
dq = Docqwise()
|
|
230
|
+
dq.ingest("documents/")
|
|
231
|
+
|
|
232
|
+
# General RAG (default) — chunk → embed → retrieve → LLM
|
|
233
|
+
result = dq.ask_rag("total amount?", mode="general")
|
|
234
|
+
|
|
235
|
+
# GraphRAG — entity graph → graph traversal → cross-document answers
|
|
236
|
+
result = dq.ask_rag("Who is the vendor for PO-2012?", mode="graphrag")
|
|
237
|
+
print(result["answer"]) # "SuperStore"
|
|
238
|
+
print(result["source"]) # "invoice_001.pdf"
|
|
239
|
+
print(result["evidence"]) # [{entity, relation, target}, ...]
|
|
240
|
+
|
|
241
|
+
# Multimodal RAG — text + images → vision LLM
|
|
242
|
+
result = dq.ask_rag("What is in this scan?", mode="multimodal", source="scan.jpg")
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Graph Visualization
|
|
246
|
+
|
|
247
|
+
Build and visualize document knowledge graphs:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
dq = Docqwise()
|
|
251
|
+
dq.ingest("documents/")
|
|
252
|
+
|
|
253
|
+
# Build knowledge graph from all documents
|
|
254
|
+
graphrag = dq.build_document_graph()
|
|
255
|
+
graph = graphrag.get_graph()
|
|
256
|
+
print(f"Nodes: {graph.node_count}, Edges: {graph.edge_count}")
|
|
257
|
+
|
|
258
|
+
# Generate interactive HTML visualization
|
|
259
|
+
dq.visualize_graph(output="my_graph.html")
|
|
260
|
+
# Open my_graph.html in browser — interactive, color-coded, draggable nodes
|
|
261
|
+
```
|
|
262
|
+
|
|
173
263
|
## All Features
|
|
174
264
|
|
|
175
265
|
```python
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.1"
|
|
@@ -226,7 +226,8 @@ class Docqwise:
|
|
|
226
226
|
def extract_fields(self, source: str, schema: dict = None,
|
|
227
227
|
template: str = None, method: str = "auto",
|
|
228
228
|
llm=None, prompt: str = None,
|
|
229
|
-
prompt_template: str = None,
|
|
229
|
+
prompt_template: str = None,
|
|
230
|
+
system_prompt: str = None, **kwargs) -> ExtractionResult:
|
|
230
231
|
"""Extract fields from a document.
|
|
231
232
|
|
|
232
233
|
Args:
|
|
@@ -235,8 +236,9 @@ class Docqwise:
|
|
|
235
236
|
template: pre-built template (invoice, contract, resume, receipt)
|
|
236
237
|
method: auto | rag | llm | vision | regex
|
|
237
238
|
llm: your own LLM instance
|
|
238
|
-
prompt: your
|
|
239
|
-
prompt_template: your
|
|
239
|
+
prompt: your extraction prompt — use {context} for document text
|
|
240
|
+
prompt_template: your template — use {context} and {schema} placeholders
|
|
241
|
+
system_prompt: LLM system role (e.g. "You are a maritime document specialist")
|
|
240
242
|
model: Ollama model name
|
|
241
243
|
"""
|
|
242
244
|
self._ensure_initialized()
|
|
@@ -269,6 +271,7 @@ class Docqwise:
|
|
|
269
271
|
result = extractor.extract_fields(
|
|
270
272
|
doc, schema=target_schema,
|
|
271
273
|
prompt=prompt, prompt_template=prompt_template,
|
|
274
|
+
system_prompt=system_prompt,
|
|
272
275
|
)
|
|
273
276
|
|
|
274
277
|
result._engine = self
|
|
@@ -365,10 +368,98 @@ class Docqwise:
|
|
|
365
368
|
filters=kwargs.get("filters"))
|
|
366
369
|
return []
|
|
367
370
|
|
|
371
|
+
def _ensure_qa_embedder(self):
|
|
372
|
+
if self._qa_engine._embedder is None:
|
|
373
|
+
from docqwise.factory import EmbedderFactory
|
|
374
|
+
embedder = EmbedderFactory.get(self._user_embedder)
|
|
375
|
+
if embedder:
|
|
376
|
+
self._qa_engine._embedder = embedder
|
|
377
|
+
|
|
368
378
|
def ask(self, question: str, source: str = None, **kwargs) -> str:
|
|
369
379
|
self._ensure_initialized()
|
|
380
|
+
self._ensure_qa_embedder()
|
|
370
381
|
return self._qa_engine.ask(question, source=source)
|
|
371
382
|
|
|
383
|
+
def ask_with_source(self, question: str, source: str = None, **kwargs):
|
|
384
|
+
"""Ask a question and get answer with source document attribution.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
QAAnswer with .answer, .source, .source_name, .confidence, .method
|
|
388
|
+
"""
|
|
389
|
+
self._ensure_initialized()
|
|
390
|
+
self._ensure_qa_embedder()
|
|
391
|
+
return self._qa_engine.ask_with_source(question, source=source)
|
|
392
|
+
|
|
393
|
+
def ask_rag(self, question: str, mode: str = "general",
|
|
394
|
+
source: str = None, prompt: str = None,
|
|
395
|
+
system_prompt: str = None, **kwargs) -> dict:
|
|
396
|
+
"""Ask using specific RAG strategy.
|
|
397
|
+
|
|
398
|
+
Modes:
|
|
399
|
+
general — chunk → embed → retrieve → LLM (default)
|
|
400
|
+
graphrag — extract entities → build graph → graph retrieval → LLM
|
|
401
|
+
multimodal — text + images → vision LLM → combined
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
question: your question
|
|
405
|
+
mode: general | graphrag | multimodal
|
|
406
|
+
source: specific document path (optional)
|
|
407
|
+
prompt: custom LLM prompt — use {context} for document text, {question} for the question
|
|
408
|
+
"""
|
|
409
|
+
self._ensure_initialized()
|
|
410
|
+
self._ensure_qa_embedder()
|
|
411
|
+
from docqwise.retrieval.rag_strategy import RAGStrategy
|
|
412
|
+
strategy = RAGStrategy(engine=self, mode=mode)
|
|
413
|
+
return strategy.ask(question, source=source, prompt=prompt, **kwargs)
|
|
414
|
+
|
|
415
|
+
def build_document_graph(self, sources: list[str] = None) -> Any:
|
|
416
|
+
"""Build knowledge graph from documents for GraphRAG."""
|
|
417
|
+
self._ensure_initialized()
|
|
418
|
+
from docqwise.retrieval.graphrag import GraphRAGEngine
|
|
419
|
+
graphrag = GraphRAGEngine(self)
|
|
420
|
+
graphrag.build_from_ingested(sources=sources)
|
|
421
|
+
self._doc_graph = graphrag
|
|
422
|
+
return graphrag
|
|
423
|
+
|
|
424
|
+
def visualize_graph(self, output: str = "docqwise_graph.png",
|
|
425
|
+
sources: list[str] = None) -> str:
|
|
426
|
+
"""Generate graph visualization as image or HTML.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
output: file path — .png, .svg, .pdf, .jpg, or .html
|
|
430
|
+
sources: list of document paths (builds from these, or uses all ingested)
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
path to saved file
|
|
434
|
+
"""
|
|
435
|
+
self._ensure_initialized()
|
|
436
|
+
if not hasattr(self, '_doc_graph') or self._doc_graph is None:
|
|
437
|
+
self.build_document_graph(sources=sources)
|
|
438
|
+
|
|
439
|
+
from docqwise.retrieval.graphrag import GraphVisualizer
|
|
440
|
+
graph = self._doc_graph.get_graph()
|
|
441
|
+
return GraphVisualizer.save(graph, output=output)
|
|
442
|
+
|
|
443
|
+
def visualize_query(self, question: str, output: str = "docqwise_query_graph.png",
|
|
444
|
+
sources: list[str] = None) -> dict:
|
|
445
|
+
"""Ask a question with GraphRAG and visualize the answer path.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
dict with "answer", "source", "evidence", "graph_file"
|
|
449
|
+
"""
|
|
450
|
+
self._ensure_initialized()
|
|
451
|
+
if not hasattr(self, '_doc_graph') or self._doc_graph is None:
|
|
452
|
+
self.build_document_graph(sources=sources)
|
|
453
|
+
|
|
454
|
+
result = self._doc_graph.query(question)
|
|
455
|
+
|
|
456
|
+
from docqwise.retrieval.graphrag import GraphVisualizer
|
|
457
|
+
graph = self._doc_graph.get_graph()
|
|
458
|
+
GraphVisualizer.from_query(graph, result, output=output)
|
|
459
|
+
|
|
460
|
+
result["graph_file"] = output
|
|
461
|
+
return result
|
|
462
|
+
|
|
372
463
|
def sql(self, query: str) -> list[dict]:
|
|
373
464
|
from docqwise.databases.sqlite_db import SQLiteDB
|
|
374
465
|
db = SQLiteDB(os.path.join(self._store_path, "structured.db"))
|
|
@@ -20,7 +20,7 @@ class RegexFieldExtractor(BaseFieldExtractor):
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
def extract_fields(self, document: DocqwiseDocument, schema: dict = None,
|
|
23
|
-
prompt: str = None, prompt_template: str = None) -> ExtractionResult:
|
|
23
|
+
prompt: str = None, prompt_template: str = None, system_prompt: str = None) -> ExtractionResult:
|
|
24
24
|
text = document.text
|
|
25
25
|
fields = {}
|
|
26
26
|
|
|
@@ -30,8 +30,8 @@ class LLMFieldExtractor(BaseFieldExtractor):
|
|
|
30
30
|
|
|
31
31
|
# Priority 1: Ollama
|
|
32
32
|
try:
|
|
33
|
-
import
|
|
34
|
-
|
|
33
|
+
from urllib.request import urlopen
|
|
34
|
+
urlopen("http://localhost:11434/api/tags", timeout=2)
|
|
35
35
|
from docqwise.llm.ollama import OllamaLLM
|
|
36
36
|
model = self._model or "nemotron-mini"
|
|
37
37
|
self._llm = OllamaLLM(model=model)
|
|
@@ -64,7 +64,7 @@ class LLMFieldExtractor(BaseFieldExtractor):
|
|
|
64
64
|
|
|
65
65
|
def extract_fields(self, document: DocqwiseDocument,
|
|
66
66
|
schema: dict = None, prompt: str = None,
|
|
67
|
-
prompt_template: str = None) -> ExtractionResult:
|
|
67
|
+
prompt_template: str = None, system_prompt: str = None) -> ExtractionResult:
|
|
68
68
|
llm = self._get_llm()
|
|
69
69
|
|
|
70
70
|
if llm is None:
|