vector-graph-rag 0.1.3__tar.gz → 0.1.4__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.
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/PKG-INFO +17 -3
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/README.md +11 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/faq.md +1 -1
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/getting-started.md +6 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/README.md +1 -1
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/pyproject.toml +6 -4
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/__init__.py +8 -8
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/api/app.py +130 -68
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/config.py +14 -27
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/graph/builder.py +5 -8
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/graph/graph.py +45 -21
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/graph/knowledge_graph.py +14 -11
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/graph/retriever.py +9 -10
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/llm/__init__.py +2 -2
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/llm/cache.py +23 -33
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/llm/extractor.py +22 -22
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/llm/reranker.py +7 -20
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/loaders/__init__.py +11 -19
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/loaders/chunker.py +3 -3
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/loaders/converter.py +7 -8
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/loaders/url_fetcher.py +25 -26
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/models.py +23 -36
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/rag.py +42 -37
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/storage/embeddings.py +19 -23
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/storage/milvus.py +27 -14
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/uv.lock +61 -54
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/.dockerignore +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/.env.example +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/.github/workflows/docs.yml +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/.github/workflows/release.yml +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/.gitignore +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/Dockerfile +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/LICENSE +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/api/__init__.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/api/main.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/api/schemas.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/assets/logo.png +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/assets/logo.svg +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/design-philosophy.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/evaluation.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/frontend.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/how-it-works.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/index.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/python-api.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/rest-api.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/stylesheets/custom.css +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/docs/use-cases.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/2wikimultihopqa.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/2wikimultihopqa_corpus.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/hotpotqa.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/hotpotqa_corpus.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/musique.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/musique_corpus.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/ner_cache/2wikimultihopqa_queries.named_entity_output.tsv +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/ner_cache/hotpotqa_queries.named_entity_output.tsv +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/ner_cache/hotpotqa_train_queries.named_entity_output.tsv +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/ner_cache/musique_queries.named_entity_output.tsv +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/ner_cache/sample_queries.named_entity_output.tsv +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/openie_2wikimultihopqa_results_ner_gpt-3.5-turbo-1106_6119.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/openie_hotpotqa_results_ner_gpt-3.5-turbo-1106_9221.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/openie_musique_results_ner_gpt-3.5-turbo-1106_11656.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/openie_test_sample_results_ner_gpt-3.5-turbo-1106_20.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/test_sample.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/data/test_sample_corpus.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/evaluation/evaluate.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/.gitignore +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/README.md +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/eslint.config.js +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/index.html +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/package-lock.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/package.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/public/vite.svg +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/App.css +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/App.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/api/client.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/api/queries.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/assets/react.svg +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/graph/EntityNode.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/graph/GraphCanvas.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/graph/GraphLegend.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/graph/RelationEdge.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/graph/index.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/CreateGraphDialog.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/FileUploader.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/GraphSelector.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/GraphStatsPreview.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/ImportDialog.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/ImportProgress.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/ImportSettings.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/import/UrlInput.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/panels/AnswerPanel.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/panels/NodeDetailPanel.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/panels/index.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/search/SearchInput.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/search/index.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/settings/SettingsDialog.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/timeline/ProcessTimeline.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/timeline/index.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/Header.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/button.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/dialog.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/input.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/label.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/progress.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/switch.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/components/ui/tabs.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/hooks/use-toast.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/index.css +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/main.tsx +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/stores/datasetStore.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/stores/graphStore.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/stores/searchStore.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/types/api.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/utils/cn.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/src/utils/graphLayout.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/tsconfig.app.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/tsconfig.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/tsconfig.node.json +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/frontend/vite.config.ts +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/mkdocs.yml +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/api/__init__.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/graph/__init__.py +4 -4
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/src/vector_graph_rag/storage/__init__.py +1 -1
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/tests/__init__.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/tests/conftest.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/tests/test_api.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/tests/test_graph.py +0 -0
- {vector_graph_rag-0.1.3 → vector_graph_rag-0.1.4}/tests/test_milvus_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vector-graph-rag
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A Graph RAG implementation using pure vector search with Milvus
|
|
5
5
|
Project-URL: Homepage, https://github.com/zilliztech/vector-graph-rag
|
|
6
6
|
Project-URL: Documentation, https://zilliztech.github.io/vector-graph-rag/
|
|
@@ -31,14 +31,14 @@ Requires-Dist: scipy>=1.10.0
|
|
|
31
31
|
Requires-Dist: setuptools<71
|
|
32
32
|
Requires-Dist: tenacity>=8.2.0
|
|
33
33
|
Requires-Dist: tiktoken>=0.5.0
|
|
34
|
-
Requires-Dist: torch>=2.0.0
|
|
35
34
|
Requires-Dist: tqdm>=4.65.0
|
|
36
|
-
Requires-Dist: transformers>=4.30.0
|
|
37
35
|
Provides-Extra: all
|
|
38
36
|
Requires-Dist: fastapi>=0.109.0; extra == 'all'
|
|
39
37
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'all'
|
|
40
38
|
Requires-Dist: pytest>=7.0.0; extra == 'all'
|
|
41
39
|
Requires-Dist: ruff>=0.1.0; extra == 'all'
|
|
40
|
+
Requires-Dist: torch>=2.0.0; extra == 'all'
|
|
41
|
+
Requires-Dist: transformers>=4.30.0; extra == 'all'
|
|
42
42
|
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'all'
|
|
43
43
|
Provides-Extra: api
|
|
44
44
|
Requires-Dist: fastapi>=0.109.0; extra == 'api'
|
|
@@ -49,6 +49,9 @@ Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
|
49
49
|
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
50
50
|
Provides-Extra: docs
|
|
51
51
|
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
|
|
52
|
+
Provides-Extra: hf
|
|
53
|
+
Requires-Dist: torch>=2.0.0; extra == 'hf'
|
|
54
|
+
Requires-Dist: transformers>=4.30.0; extra == 'hf'
|
|
52
55
|
Provides-Extra: loaders
|
|
53
56
|
Requires-Dist: lxml-html-clean; extra == 'loaders'
|
|
54
57
|
Requires-Dist: markitdown[docx,pdf]>=0.1.4; extra == 'loaders'
|
|
@@ -108,6 +111,17 @@ uv add "vector-graph-rag[loaders]"
|
|
|
108
111
|
|
|
109
112
|
</details>
|
|
110
113
|
|
|
114
|
+
<details>
|
|
115
|
+
<summary><b>With local HuggingFace embedding models</b></summary>
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install "vector-graph-rag[hf]"
|
|
119
|
+
# or
|
|
120
|
+
uv add "vector-graph-rag[hf]"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
111
125
|
## 🚀 Quick Start
|
|
112
126
|
|
|
113
127
|
```python
|
|
@@ -51,6 +51,17 @@ uv add "vector-graph-rag[loaders]"
|
|
|
51
51
|
|
|
52
52
|
</details>
|
|
53
53
|
|
|
54
|
+
<details>
|
|
55
|
+
<summary><b>With local HuggingFace embedding models</b></summary>
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install "vector-graph-rag[hf]"
|
|
59
|
+
# or
|
|
60
|
+
uv add "vector-graph-rag[hf]"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
</details>
|
|
64
|
+
|
|
54
65
|
## 🚀 Quick Start
|
|
55
66
|
|
|
56
67
|
```python
|
|
@@ -70,7 +70,7 @@ Frequently asked questions about Vector Graph RAG — covering when to use it, c
|
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
??? note "Can I use my own embeddings?"
|
|
73
|
-
Vector Graph RAG uses OpenAI embedding models by default (`text-embedding-3-large`), but you can configure the embedding model via the `embedding_model` parameter. Any model accessible through the OpenAI-compatible API will work. If you are using a local
|
|
73
|
+
Vector Graph RAG uses OpenAI embedding models by default (`text-embedding-3-large`), but you can configure the embedding model via the `embedding_model` parameter. Any model accessible through the OpenAI-compatible API will work. If you are using a local HuggingFace embedding model, install the optional dependencies with `pip install "vector-graph-rag[hf]"`. The embedding dimensionality is detected automatically. Note that all entities, relations, and passages in a single graph must use the same embedding model — mixing models within one collection prefix is not supported.
|
|
74
74
|
|
|
75
75
|
??? note "How do I deploy to production?"
|
|
76
76
|
For production deployments, use a remote Milvus instance instead of Milvus Lite for better performance, scalability, and persistence. Run the FastAPI backend behind a reverse proxy (e.g., Nginx) with appropriate rate limiting and authentication. The frontend can be built as static files and served from any CDN or static file server.
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
pip install "vector-graph-rag[loaders]"
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
=== "With local embeddings"
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install "vector-graph-rag[hf]"
|
|
27
|
+
```
|
|
28
|
+
|
|
23
29
|
!!! note "Prerequisites"
|
|
24
30
|
- Python 3.9+
|
|
25
31
|
- An OpenAI API key (set `OPENAI_API_KEY` environment variable)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vector-graph-rag"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
description = "A Graph RAG implementation using pure vector search with Milvus"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -32,8 +32,6 @@ dependencies = [
|
|
|
32
32
|
"tqdm>=4.65.0",
|
|
33
33
|
"tiktoken>=0.5.0",
|
|
34
34
|
"tenacity>=8.2.0",
|
|
35
|
-
"transformers>=4.30.0",
|
|
36
|
-
"torch>=2.0.0",
|
|
37
35
|
"langchain-core>=0.3.0",
|
|
38
36
|
"python-multipart>=0.0.22",
|
|
39
37
|
"setuptools<71", # Required for pkg_resources used by milvus-lite
|
|
@@ -49,8 +47,12 @@ api = [
|
|
|
49
47
|
"fastapi>=0.109.0",
|
|
50
48
|
"uvicorn[standard]>=0.27.0",
|
|
51
49
|
]
|
|
50
|
+
hf = [
|
|
51
|
+
"transformers>=4.30.0",
|
|
52
|
+
"torch>=2.0.0",
|
|
53
|
+
]
|
|
52
54
|
all = [
|
|
53
|
-
"vector-graph-rag[dev,api]",
|
|
55
|
+
"vector-graph-rag[dev,api,hf]",
|
|
54
56
|
]
|
|
55
57
|
loaders = [
|
|
56
58
|
"markitdown[docx,pdf]>=0.1.4",
|
|
@@ -6,19 +6,19 @@ using only vector similarity search, without requiring a separate graph database
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from vector_graph_rag.config import Settings
|
|
9
|
-
from vector_graph_rag.models import Document, Triplet, Entity, Relation, Passage
|
|
10
|
-
from vector_graph_rag.llm.extractor import TripletExtractor
|
|
11
|
-
from vector_graph_rag.storage.embeddings import EmbeddingModel
|
|
12
|
-
from vector_graph_rag.storage.milvus import MilvusStore
|
|
13
9
|
from vector_graph_rag.graph.builder import GraphBuilder
|
|
14
|
-
from vector_graph_rag.graph.retriever import GraphRetriever
|
|
15
|
-
from vector_graph_rag.graph.knowledge_graph import SubGraph
|
|
16
10
|
from vector_graph_rag.graph.graph import Graph
|
|
11
|
+
from vector_graph_rag.graph.knowledge_graph import SubGraph
|
|
12
|
+
from vector_graph_rag.graph.retriever import GraphRetriever
|
|
13
|
+
from vector_graph_rag.llm.cache import LLMCache, get_llm_cache
|
|
14
|
+
from vector_graph_rag.llm.extractor import TripletExtractor
|
|
17
15
|
from vector_graph_rag.llm.reranker import LLMReranker
|
|
16
|
+
from vector_graph_rag.models import Document, Entity, Passage, Relation, Triplet
|
|
18
17
|
from vector_graph_rag.rag import VectorGraphRAG, create_rag
|
|
19
|
-
from vector_graph_rag.
|
|
18
|
+
from vector_graph_rag.storage.embeddings import EmbeddingModel
|
|
19
|
+
from vector_graph_rag.storage.milvus import MilvusStore
|
|
20
20
|
|
|
21
|
-
__version__ = "0.1.
|
|
21
|
+
__version__ = "0.1.4"
|
|
22
22
|
|
|
23
23
|
__all__ = [
|
|
24
24
|
"Settings",
|
|
@@ -9,34 +9,35 @@ Provides RESTful API endpoints for:
|
|
|
9
9
|
- Graph exploration (stats, neighbors)
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
import os
|
|
13
|
-
import tempfile
|
|
14
12
|
import shutil
|
|
13
|
+
import tempfile
|
|
15
14
|
from pathlib import Path
|
|
16
|
-
from typing import
|
|
17
|
-
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
from fastapi import FastAPI, File, Form, HTTPException, Query, UploadFile
|
|
18
18
|
from fastapi.middleware.cors import CORSMiddleware
|
|
19
|
-
from fastapi.staticfiles import StaticFiles
|
|
20
19
|
from fastapi.responses import FileResponse
|
|
20
|
+
from fastapi.staticfiles import StaticFiles
|
|
21
21
|
from pydantic import BaseModel, Field
|
|
22
22
|
|
|
23
23
|
from vector_graph_rag import VectorGraphRAG, __version__
|
|
24
24
|
from vector_graph_rag.config import Settings, get_settings
|
|
25
|
-
from vector_graph_rag.storage.milvus import MilvusStore
|
|
26
25
|
from vector_graph_rag.graph.graph import Graph
|
|
27
|
-
from vector_graph_rag.
|
|
28
|
-
|
|
26
|
+
from vector_graph_rag.storage.milvus import MilvusStore
|
|
29
27
|
|
|
30
28
|
# ==================== Request/Response Schemas ====================
|
|
31
29
|
|
|
30
|
+
|
|
32
31
|
class HealthResponse(BaseModel):
|
|
33
32
|
"""Health check response."""
|
|
33
|
+
|
|
34
34
|
status: str = Field(default="ok", description="Service status")
|
|
35
35
|
version: str = Field(default=__version__, description="API version")
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class GraphInfo(BaseModel):
|
|
39
39
|
"""Information about a graph."""
|
|
40
|
+
|
|
40
41
|
name: str = Field(..., description="Graph name (collection prefix)")
|
|
41
42
|
entity_collection: str = Field(..., description="Entity collection name")
|
|
42
43
|
relation_collection: str = Field(..., description="Relation collection name")
|
|
@@ -46,11 +47,13 @@ class GraphInfo(BaseModel):
|
|
|
46
47
|
|
|
47
48
|
class ListGraphsResponse(BaseModel):
|
|
48
49
|
"""Response for listing graphs."""
|
|
50
|
+
|
|
49
51
|
graphs: List[GraphInfo] = Field(default_factory=list, description="Available graphs")
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
class TripletInput(BaseModel):
|
|
53
55
|
"""Input for a triplet."""
|
|
56
|
+
|
|
54
57
|
subject: str = Field(..., description="Subject entity")
|
|
55
58
|
predicate: str = Field(..., description="Predicate/relationship")
|
|
56
59
|
object: str = Field(..., description="Object entity")
|
|
@@ -58,17 +61,20 @@ class TripletInput(BaseModel):
|
|
|
58
61
|
|
|
59
62
|
class AddDocumentsRequest(BaseModel):
|
|
60
63
|
"""Request to add documents."""
|
|
64
|
+
|
|
61
65
|
documents: List[str] = Field(..., description="List of document texts")
|
|
62
66
|
ids: Optional[List[str]] = Field(default=None, description="Optional list of document IDs")
|
|
63
|
-
extract_triplets: bool = Field(
|
|
67
|
+
extract_triplets: bool = Field(
|
|
68
|
+
default=True, description="Whether to extract triplets using LLM"
|
|
69
|
+
)
|
|
64
70
|
triplets: Optional[List[List[TripletInput]]] = Field(
|
|
65
|
-
default=None,
|
|
66
|
-
description="Optional pre-extracted triplets for each document"
|
|
71
|
+
default=None, description="Optional pre-extracted triplets for each document"
|
|
67
72
|
)
|
|
68
73
|
|
|
69
74
|
|
|
70
75
|
class AddDocumentsResponse(BaseModel):
|
|
71
76
|
"""Response after adding documents."""
|
|
77
|
+
|
|
72
78
|
num_documents: int = Field(..., description="Number of documents added")
|
|
73
79
|
num_entities: int = Field(..., description="Number of entities created")
|
|
74
80
|
num_relations: int = Field(..., description="Number of relations created")
|
|
@@ -77,10 +83,11 @@ class AddDocumentsResponse(BaseModel):
|
|
|
77
83
|
|
|
78
84
|
class ImportRequest(BaseModel):
|
|
79
85
|
"""Request to import documents from various sources."""
|
|
86
|
+
|
|
80
87
|
sources: List[str] = Field(
|
|
81
88
|
...,
|
|
82
89
|
description="List of file paths or URLs to import",
|
|
83
|
-
examples=["/path/to/doc.pdf", "https://example.com/article"]
|
|
90
|
+
examples=["/path/to/doc.pdf", "https://example.com/article"],
|
|
84
91
|
)
|
|
85
92
|
chunk_documents: bool = Field(True, description="Whether to chunk large documents")
|
|
86
93
|
chunk_size: int = Field(1000, description="Max characters per chunk")
|
|
@@ -91,6 +98,7 @@ class ImportRequest(BaseModel):
|
|
|
91
98
|
|
|
92
99
|
class ImportResponse(BaseModel):
|
|
93
100
|
"""Response from document import."""
|
|
101
|
+
|
|
94
102
|
success: bool
|
|
95
103
|
num_sources: int = Field(..., description="Number of input sources")
|
|
96
104
|
num_documents: int = Field(..., description="Number of documents after conversion")
|
|
@@ -102,15 +110,19 @@ class ImportResponse(BaseModel):
|
|
|
102
110
|
|
|
103
111
|
class QueryRequest(BaseModel):
|
|
104
112
|
"""Request to query the knowledge base."""
|
|
113
|
+
|
|
105
114
|
question: str = Field(..., description="Question to answer")
|
|
106
115
|
use_reranking: bool = Field(default=True, description="Whether to use LLM reranking")
|
|
107
116
|
entity_top_k: Optional[int] = Field(default=None, description="Number of entities to retrieve")
|
|
108
|
-
relation_top_k: Optional[int] = Field(
|
|
117
|
+
relation_top_k: Optional[int] = Field(
|
|
118
|
+
default=None, description="Number of relations to retrieve"
|
|
119
|
+
)
|
|
109
120
|
expansion_degree: Optional[int] = Field(default=None, description="Subgraph expansion degree")
|
|
110
121
|
|
|
111
122
|
|
|
112
123
|
class EntitySchema(BaseModel):
|
|
113
124
|
"""Schema for an entity in the subgraph."""
|
|
125
|
+
|
|
114
126
|
id: str = Field(..., description="Entity ID")
|
|
115
127
|
name: str = Field(..., description="Entity name")
|
|
116
128
|
relation_ids: List[str] = Field(default_factory=list, description="Connected relation IDs")
|
|
@@ -119,61 +131,84 @@ class EntitySchema(BaseModel):
|
|
|
119
131
|
|
|
120
132
|
class RelationSchema(BaseModel):
|
|
121
133
|
"""Schema for a relation in the subgraph."""
|
|
134
|
+
|
|
122
135
|
id: str = Field(..., description="Relation ID")
|
|
123
136
|
text: str = Field(..., description="Full relation text")
|
|
124
137
|
subject: str = Field(..., description="Subject entity name")
|
|
125
138
|
predicate: str = Field(..., description="Predicate/relationship")
|
|
126
139
|
object: str = Field(..., description="Object entity name")
|
|
127
|
-
entity_ids: List[str] = Field(
|
|
140
|
+
entity_ids: List[str] = Field(
|
|
141
|
+
default_factory=list, description="Connected entity IDs [subject_id, object_id]"
|
|
142
|
+
)
|
|
128
143
|
passage_ids: List[str] = Field(default_factory=list, description="Source passage IDs")
|
|
129
144
|
|
|
130
145
|
|
|
131
146
|
class PassageSchema(BaseModel):
|
|
132
147
|
"""Schema for a passage in the subgraph."""
|
|
148
|
+
|
|
133
149
|
id: str = Field(..., description="Passage ID")
|
|
134
150
|
text: str = Field(..., description="Passage text")
|
|
135
151
|
|
|
136
152
|
|
|
137
153
|
class ExpansionStepSchema(BaseModel):
|
|
138
154
|
"""Schema for an expansion step in the history."""
|
|
155
|
+
|
|
139
156
|
step: int = Field(..., description="Step number")
|
|
140
157
|
operation: str = Field(..., description="Operation type")
|
|
141
158
|
description: Optional[str] = Field(default=None, description="Operation description")
|
|
142
|
-
added_entity_ids: List[str] = Field(
|
|
143
|
-
|
|
159
|
+
added_entity_ids: List[str] = Field(
|
|
160
|
+
default_factory=list, description="Entity IDs added in this step"
|
|
161
|
+
)
|
|
162
|
+
added_relation_ids: List[str] = Field(
|
|
163
|
+
default_factory=list, description="Relation IDs added in this step"
|
|
164
|
+
)
|
|
144
165
|
total_entities: int = Field(default=0, description="Total entities after this step")
|
|
145
166
|
total_relations: int = Field(default=0, description="Total relations after this step")
|
|
146
167
|
|
|
147
168
|
|
|
148
169
|
class SubGraphSchema(BaseModel):
|
|
149
170
|
"""Schema for the expanded subgraph."""
|
|
171
|
+
|
|
150
172
|
entity_ids: List[str] = Field(default_factory=list, description="All entity IDs in subgraph")
|
|
151
|
-
relation_ids: List[str] = Field(
|
|
173
|
+
relation_ids: List[str] = Field(
|
|
174
|
+
default_factory=list, description="All relation IDs in subgraph"
|
|
175
|
+
)
|
|
152
176
|
passage_ids: List[str] = Field(default_factory=list, description="All passage IDs in subgraph")
|
|
153
177
|
entities: List[EntitySchema] = Field(default_factory=list, description="Entity details")
|
|
154
178
|
relations: List[RelationSchema] = Field(default_factory=list, description="Relation details")
|
|
155
179
|
passages: List[PassageSchema] = Field(default_factory=list, description="Passage details")
|
|
156
|
-
expansion_history: List[ExpansionStepSchema] = Field(
|
|
180
|
+
expansion_history: List[ExpansionStepSchema] = Field(
|
|
181
|
+
default_factory=list, description="Expansion history"
|
|
182
|
+
)
|
|
157
183
|
|
|
158
184
|
|
|
159
185
|
class RetrievalDetailSchema(BaseModel):
|
|
160
186
|
"""Schema for retrieval details."""
|
|
187
|
+
|
|
161
188
|
entity_ids: List[str] = Field(default_factory=list, description="Retrieved entity IDs")
|
|
162
189
|
entity_texts: List[str] = Field(default_factory=list, description="Retrieved entity names")
|
|
163
190
|
entity_scores: List[float] = Field(default_factory=list, description="Entity similarity scores")
|
|
164
191
|
relation_ids: List[str] = Field(default_factory=list, description="Retrieved relation IDs")
|
|
165
192
|
relation_texts: List[str] = Field(default_factory=list, description="Retrieved relation texts")
|
|
166
|
-
relation_scores: List[float] = Field(
|
|
193
|
+
relation_scores: List[float] = Field(
|
|
194
|
+
default_factory=list, description="Relation similarity scores"
|
|
195
|
+
)
|
|
167
196
|
|
|
168
197
|
|
|
169
198
|
class RerankResultSchema(BaseModel):
|
|
170
199
|
"""Schema for rerank results."""
|
|
171
|
-
|
|
172
|
-
|
|
200
|
+
|
|
201
|
+
selected_relation_ids: List[str] = Field(
|
|
202
|
+
default_factory=list, description="Selected relation IDs"
|
|
203
|
+
)
|
|
204
|
+
selected_relation_texts: List[str] = Field(
|
|
205
|
+
default_factory=list, description="Selected relation texts"
|
|
206
|
+
)
|
|
173
207
|
|
|
174
208
|
|
|
175
209
|
class EvictionResultSchema(BaseModel):
|
|
176
210
|
"""Schema for eviction results (when relations exceed threshold)."""
|
|
211
|
+
|
|
177
212
|
occurred: bool = Field(default=False, description="Whether eviction occurred")
|
|
178
213
|
before_count: int = Field(default=0, description="Number of relations before eviction")
|
|
179
214
|
after_count: int = Field(default=0, description="Number of relations after eviction")
|
|
@@ -181,44 +216,62 @@ class EvictionResultSchema(BaseModel):
|
|
|
181
216
|
|
|
182
217
|
class QueryResponse(BaseModel):
|
|
183
218
|
"""Response for a query."""
|
|
219
|
+
|
|
184
220
|
question: str = Field(..., description="Original question")
|
|
185
221
|
answer: str = Field(..., description="Generated answer")
|
|
186
|
-
query_entities: List[str] = Field(
|
|
187
|
-
|
|
222
|
+
query_entities: List[str] = Field(
|
|
223
|
+
default_factory=list, description="Entities extracted from query"
|
|
224
|
+
)
|
|
225
|
+
subgraph: Optional[SubGraphSchema] = Field(
|
|
226
|
+
default=None, description="Expanded subgraph for visualization"
|
|
227
|
+
)
|
|
188
228
|
retrieved_passages: List[str] = Field(default_factory=list, description="Retrieved passages")
|
|
189
229
|
stats: Dict[str, Any] = Field(default_factory=dict, description="Query statistics")
|
|
190
|
-
retrieval_detail: Optional[RetrievalDetailSchema] = Field(
|
|
191
|
-
|
|
192
|
-
|
|
230
|
+
retrieval_detail: Optional[RetrievalDetailSchema] = Field(
|
|
231
|
+
default=None, description="Initial retrieval details"
|
|
232
|
+
)
|
|
233
|
+
rerank_result: Optional[RerankResultSchema] = Field(
|
|
234
|
+
default=None, description="LLM rerank results"
|
|
235
|
+
)
|
|
236
|
+
eviction_result: Optional[EvictionResultSchema] = Field(
|
|
237
|
+
default=None, description="Eviction results if relations exceeded threshold"
|
|
238
|
+
)
|
|
193
239
|
|
|
194
240
|
|
|
195
241
|
class DocumentResponse(BaseModel):
|
|
196
242
|
"""Response for a single document."""
|
|
243
|
+
|
|
197
244
|
id: str = Field(..., description="Document ID")
|
|
198
245
|
text: str = Field(..., description="Document text")
|
|
199
246
|
entity_ids: List[str] = Field(default_factory=list, description="Entity IDs in this document")
|
|
200
|
-
relation_ids: List[str] = Field(
|
|
247
|
+
relation_ids: List[str] = Field(
|
|
248
|
+
default_factory=list, description="Relation IDs from this document"
|
|
249
|
+
)
|
|
201
250
|
|
|
202
251
|
|
|
203
252
|
class ListDocumentsResponse(BaseModel):
|
|
204
253
|
"""Response for listing documents."""
|
|
254
|
+
|
|
205
255
|
documents: List[DocumentResponse] = Field(default_factory=list, description="List of documents")
|
|
206
256
|
total: int = Field(..., description="Total number of documents returned")
|
|
207
257
|
|
|
208
258
|
|
|
209
259
|
class UpdateDocumentRequest(BaseModel):
|
|
210
260
|
"""Request to update a document."""
|
|
261
|
+
|
|
211
262
|
text: Optional[str] = Field(default=None, description="New document text")
|
|
212
263
|
|
|
213
264
|
|
|
214
265
|
class DeleteResponse(BaseModel):
|
|
215
266
|
"""Response for delete operations."""
|
|
267
|
+
|
|
216
268
|
success: bool = Field(..., description="Whether deletion succeeded")
|
|
217
269
|
message: str = Field(default="", description="Additional message")
|
|
218
270
|
|
|
219
271
|
|
|
220
272
|
class GraphStatsResponse(BaseModel):
|
|
221
273
|
"""Response for graph statistics."""
|
|
274
|
+
|
|
222
275
|
graph_name: str = Field(..., description="Graph name")
|
|
223
276
|
entity_count: int = Field(default=0, description="Number of entities")
|
|
224
277
|
relation_count: int = Field(default=0, description="Number of relations")
|
|
@@ -227,13 +280,17 @@ class GraphStatsResponse(BaseModel):
|
|
|
227
280
|
|
|
228
281
|
class NeighborResponse(BaseModel):
|
|
229
282
|
"""Response for entity neighbors."""
|
|
283
|
+
|
|
230
284
|
entity_id: str = Field(..., description="Central entity ID")
|
|
231
285
|
neighbors: List[EntitySchema] = Field(default_factory=list, description="Neighbor entities")
|
|
232
|
-
relations: List[RelationSchema] = Field(
|
|
286
|
+
relations: List[RelationSchema] = Field(
|
|
287
|
+
default_factory=list, description="Connecting relations"
|
|
288
|
+
)
|
|
233
289
|
|
|
234
290
|
|
|
235
291
|
class SettingsResponse(BaseModel):
|
|
236
292
|
"""Response for system settings."""
|
|
293
|
+
|
|
237
294
|
llm_model: str = Field(..., description="LLM model name")
|
|
238
295
|
embedding_model: str = Field(..., description="Embedding model name")
|
|
239
296
|
embedding_dimension: int = Field(..., description="Embedding dimension")
|
|
@@ -245,6 +302,7 @@ class SettingsResponse(BaseModel):
|
|
|
245
302
|
|
|
246
303
|
# ==================== Application Factory ====================
|
|
247
304
|
|
|
305
|
+
|
|
248
306
|
def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
249
307
|
"""
|
|
250
308
|
Create and configure the FastAPI application.
|
|
@@ -314,9 +372,7 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
314
372
|
milvus_token=app.state.settings.milvus_token,
|
|
315
373
|
milvus_db=app.state.settings.milvus_db,
|
|
316
374
|
)
|
|
317
|
-
return ListGraphsResponse(
|
|
318
|
-
graphs=[GraphInfo(**g) for g in graphs]
|
|
319
|
-
)
|
|
375
|
+
return ListGraphsResponse(graphs=[GraphInfo(**g) for g in graphs])
|
|
320
376
|
|
|
321
377
|
@app.get("/settings", response_model=SettingsResponse, tags=["System"])
|
|
322
378
|
async def get_system_settings():
|
|
@@ -362,19 +418,15 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
362
418
|
if deleted:
|
|
363
419
|
return DeleteResponse(
|
|
364
420
|
success=True,
|
|
365
|
-
message=f"Successfully deleted graph '{graph_name}' and all its collections"
|
|
421
|
+
message=f"Successfully deleted graph '{graph_name}' and all its collections",
|
|
366
422
|
)
|
|
367
423
|
else:
|
|
368
424
|
return DeleteResponse(
|
|
369
|
-
success=False,
|
|
370
|
-
message=f"Graph '{graph_name}' not found or already deleted"
|
|
425
|
+
success=False, message=f"Graph '{graph_name}' not found or already deleted"
|
|
371
426
|
)
|
|
372
427
|
|
|
373
428
|
except Exception as e:
|
|
374
|
-
raise HTTPException(
|
|
375
|
-
status_code=500,
|
|
376
|
-
detail=f"Failed to delete graph: {str(e)}"
|
|
377
|
-
)
|
|
429
|
+
raise HTTPException(status_code=500, detail=f"Failed to delete graph: {str(e)}")
|
|
378
430
|
|
|
379
431
|
@app.post("/add_documents", response_model=AddDocumentsResponse, tags=["Documents"])
|
|
380
432
|
async def add_documents(
|
|
@@ -395,10 +447,9 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
395
447
|
for i, text in enumerate(request.documents):
|
|
396
448
|
doc_data = {
|
|
397
449
|
"passage": text,
|
|
398
|
-
"triplets": [
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
] if i < len(request.triplets) else [],
|
|
450
|
+
"triplets": [[t.subject, t.predicate, t.object] for t in request.triplets[i]]
|
|
451
|
+
if i < len(request.triplets)
|
|
452
|
+
else [],
|
|
402
453
|
}
|
|
403
454
|
if request.ids and i < len(request.ids):
|
|
404
455
|
doc_data["id"] = request.ids[i]
|
|
@@ -575,9 +626,9 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
575
626
|
if result.subgraph:
|
|
576
627
|
sg = result.subgraph
|
|
577
628
|
subgraph_schema = SubGraphSchema(
|
|
578
|
-
entity_ids=list(sg.entity_ids) if hasattr(sg,
|
|
579
|
-
relation_ids=list(sg.relation_ids) if hasattr(sg,
|
|
580
|
-
passage_ids=list(sg.passage_ids) if hasattr(sg,
|
|
629
|
+
entity_ids=list(sg.entity_ids) if hasattr(sg, "entity_ids") else [],
|
|
630
|
+
relation_ids=list(sg.relation_ids) if hasattr(sg, "relation_ids") else [],
|
|
631
|
+
passage_ids=list(sg.passage_ids) if hasattr(sg, "passage_ids") else [],
|
|
581
632
|
entities=[
|
|
582
633
|
EntitySchema(
|
|
583
634
|
id=e.id,
|
|
@@ -585,7 +636,7 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
585
636
|
relation_ids=e.relation_ids,
|
|
586
637
|
passage_ids=e.passage_ids,
|
|
587
638
|
)
|
|
588
|
-
for e in (sg.entities if hasattr(sg,
|
|
639
|
+
for e in (sg.entities if hasattr(sg, "entities") else [])
|
|
589
640
|
],
|
|
590
641
|
relations=[
|
|
591
642
|
RelationSchema(
|
|
@@ -597,23 +648,27 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
597
648
|
entity_ids=r.entity_ids,
|
|
598
649
|
passage_ids=r.passage_ids,
|
|
599
650
|
)
|
|
600
|
-
for r in (sg.relations if hasattr(sg,
|
|
651
|
+
for r in (sg.relations if hasattr(sg, "relations") else [])
|
|
601
652
|
],
|
|
602
653
|
passages=[
|
|
603
654
|
PassageSchema(id=p.id, text=p.text)
|
|
604
|
-
for p in (sg.passages if hasattr(sg,
|
|
655
|
+
for p in (sg.passages if hasattr(sg, "passages") else [])
|
|
605
656
|
],
|
|
606
657
|
expansion_history=[
|
|
607
658
|
ExpansionStepSchema(
|
|
608
|
-
step=h.get(
|
|
609
|
-
operation=h.get(
|
|
610
|
-
description=h.get(
|
|
611
|
-
added_entity_ids=h.get(
|
|
612
|
-
added_relation_ids=h.get(
|
|
613
|
-
|
|
614
|
-
|
|
659
|
+
step=h.get("step", i),
|
|
660
|
+
operation=h.get("operation", "unknown"),
|
|
661
|
+
description=h.get("description"),
|
|
662
|
+
added_entity_ids=h.get("added_entity_ids", h.get("new_entity_ids", [])),
|
|
663
|
+
added_relation_ids=h.get(
|
|
664
|
+
"added_relation_ids", h.get("new_relation_ids", [])
|
|
665
|
+
),
|
|
666
|
+
total_entities=h.get("total_entities", 0),
|
|
667
|
+
total_relations=h.get("total_relations", 0),
|
|
668
|
+
)
|
|
669
|
+
for i, h in enumerate(
|
|
670
|
+
sg.expansion_history if hasattr(sg, "expansion_history") else []
|
|
615
671
|
)
|
|
616
|
-
for i, h in enumerate(sg.expansion_history if hasattr(sg, 'expansion_history') else [])
|
|
617
672
|
],
|
|
618
673
|
)
|
|
619
674
|
|
|
@@ -681,11 +736,11 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
681
736
|
stats = graph.get_stats()
|
|
682
737
|
return GraphStatsResponse(
|
|
683
738
|
graph_name=graph_name,
|
|
684
|
-
entity_count=stats.get(
|
|
685
|
-
relation_count=stats.get(
|
|
686
|
-
passage_count=stats.get(
|
|
739
|
+
entity_count=stats.get("entity_count", 0),
|
|
740
|
+
relation_count=stats.get("relation_count", 0),
|
|
741
|
+
passage_count=stats.get("passage_count", 0),
|
|
687
742
|
)
|
|
688
|
-
except Exception
|
|
743
|
+
except Exception:
|
|
689
744
|
# If stats not available, return zeros
|
|
690
745
|
return GraphStatsResponse(
|
|
691
746
|
graph_name=graph_name,
|
|
@@ -694,7 +749,9 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
694
749
|
passage_count=0,
|
|
695
750
|
)
|
|
696
751
|
|
|
697
|
-
@app.get(
|
|
752
|
+
@app.get(
|
|
753
|
+
"/graph/{graph_name}/neighbors/{entity_id}", response_model=NeighborResponse, tags=["Graph"]
|
|
754
|
+
)
|
|
698
755
|
async def get_entity_neighbors(
|
|
699
756
|
graph_name: str,
|
|
700
757
|
entity_id: str,
|
|
@@ -729,12 +786,14 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
729
786
|
for nid in list(neighbor_ids)[:limit]:
|
|
730
787
|
neighbor = graph.get_entity(nid)
|
|
731
788
|
if neighbor:
|
|
732
|
-
neighbors.append(
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
789
|
+
neighbors.append(
|
|
790
|
+
EntitySchema(
|
|
791
|
+
id=neighbor.id,
|
|
792
|
+
name=neighbor.name,
|
|
793
|
+
relation_ids=neighbor.relation_ids,
|
|
794
|
+
passage_ids=neighbor.passage_ids,
|
|
795
|
+
)
|
|
796
|
+
)
|
|
738
797
|
|
|
739
798
|
# Convert relations to schema
|
|
740
799
|
relation_schemas = [
|
|
@@ -786,7 +845,9 @@ def create_app(settings: Optional[Settings] = None) -> FastAPI:
|
|
|
786
845
|
@app.get("/documents", response_model=ListDocumentsResponse, tags=["Documents"])
|
|
787
846
|
async def list_documents(
|
|
788
847
|
graph_name: Optional[str] = Query(default=None, description="Graph name to use"),
|
|
789
|
-
query: Optional[str] = Query(
|
|
848
|
+
query: Optional[str] = Query(
|
|
849
|
+
default=None, description="Optional search query for vector similarity"
|
|
850
|
+
),
|
|
790
851
|
top_k: int = Query(default=10, description="Number of documents to return"),
|
|
791
852
|
):
|
|
792
853
|
"""
|
|
@@ -921,6 +982,7 @@ def run_server(host: str = "0.0.0.0", port: int = 8000, reload: bool = False):
|
|
|
921
982
|
reload: Whether to enable auto-reload.
|
|
922
983
|
"""
|
|
923
984
|
import uvicorn
|
|
985
|
+
|
|
924
986
|
uvicorn.run("vector_graph_rag.api.app:app", host=host, port=port, reload=reload)
|
|
925
987
|
|
|
926
988
|
|